Login auth

Exchanges a machine credential for an IAM bearer token.

POST /v1/kms/auth/login

Addresshttps://api.hanzo.ai/v1/kms/auth/login
MethodPOST
Operationpost_kms_auth_login
AuthAuthorization: Bearer $HANZO_API_KEY

Exchanges a machine credential for an IAM bearer token.

Takes a tenant's machine credential — a client id and client secret — and returns an owner-scoped IAM access token with its lifetime, which is the bearer the caller then carries on the org-scoped secret operations.

It is deliberately public and unauthenticated, because it IS the credential exchange and runs before any principal exists. That makes it the one route in this subsystem rate-limited PER SOURCE IP, keyed on the real TCP peer rather than on any caller-supplied header, and body-capped in the same place.

The submitted secret is never logged and never echoed, and failures collapse to one clean status with no upstream detail: 401 when the credential does not authenticate, 502 when the identity provider is unreachable, 503 when no issuer is configured. That is on purpose — a richer error would be a validity oracle for guessed credentials.

Request

2 fields, body application/json (required).

FieldInTypeRequiredDescription
clientIdbodystring—ClientID is the machine identity's id, as IAM issued it.
clientSecretbodystring—ClientSecret is that identity's secret.

Response

StatusBodyMeaning
200kms.kmsTokenok
defaultproblem-detailsrefused

200 body — 3 fields.

FieldInTypeAlwaysDescription
accessTokenbodystring—AccessToken is IAM's own JWT, verbatim.
expiresInbodyinteger (int64)—ExpiresIn is the token's lifetime in seconds, as IAM reported it.
tokenTypebodystring—TokenType is Bearer.

Failure carries the platform error shape — see Errors.

Examples

hanzo kms auth login
import { Configuration, KmsApi } from 'hanzoai';

const api = new KmsApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.postKmsAuthLogin({ clientId: "<clientId>", clientSecret: "<clientSecret>" });
from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import KmsApi

client = ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"]))
result = KmsApi(client).post_kms_auth_login(client_id="<clientId>", client_secret="<clientSecret>")
cfg := hanzoai.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := hanzoai.NewAPIClient(cfg)

resp, _, err := client.KmsAPI.PostKmsAuthLogin(context.Background()).Execute()
if err != nil {
	return err
}
use hanzo_client::apis::{configuration::Configuration, kms_api};

let mut cfg = Configuration::new();
cfg.bearer_access_token = std::env::var("HANZO_API_KEY").ok();

let result = kms_api::post_kms_auth_login(&cfg, Default::default()).await?;
import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.KmsApi;

ApiClient client = new ApiClient();
client.setBearerToken(System.getenv("HANZO_API_KEY"));

var result = new KmsApi(client).postKmsAuthLogin();
curl -X POST https://api.hanzo.ai/v1/kms/auth/login \
  -H "Authorization: Bearer $HANZO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
       "clientId": "<clientId>",
       "clientSecret": "<clientSecret>"
     }'

MCP reaches kms through the kms tool, which names its 2 operations with its own verbs — this one among them, under a name only MCP declares. describe explains any of them:

curl -X POST https://api.hanzo.ai/v1/mcp \
  -H "Content-Type: application/json" \
  -d '{
       "jsonrpc": "2.0",
       "id": 1,
       "method": "tools/call",
       "params": {
         "name": "describe",
         "arguments": {
           "op": "get_kms_config"
         }
       }
     }'

KMS API · All Hanzo APIs · Interactive reference

Was this page useful?