Oauth
OAuth-style PKCE flow for issuing user-scoped API keys to external apps. The user grants consent in the Hadrian UI; the external app exchanges the resulting code at /oauth/token for an API key bound to that user.
Serve the OAuth 2.0 Authorization Server Metadata document.
Authorization
api_key API key authentication using Bearer token format
In: header
Response Body
application/json
application/json
curl -X GET "https://loading/.well-known/oauth-authorization-server"{
"authorization_endpoint": "string",
"code_challenge_methods_supported": [
"string"
],
"grant_types_supported": [
"string"
],
"issuer": "string",
"response_types_supported": [
"string"
],
"scopes_supported": [
"string"
],
"service_documentation": "string",
"token_endpoint": "string",
"token_endpoint_auth_methods_supported": [
"string"
]
}{
"error": {
"code": "budget_exceeded",
"message": "Budget limit exceeded for monthly period",
"param": null,
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"type": "invalid_request_error"
}
}Issue an authorization code after explicit user consent.
Authorization
api_key API key authentication using Bearer token format
In: header
Request Body
application/json
Optional human-readable name of the requesting app, shown on the consent screen.
Where the external app expects the user to land after consent. The exchange endpoint requires this exact same value when redeeming.
PKCE challenge supplied by the external app. RFC 7636 §4.1 mandates
43–128 characters for both the verifier and (by extension) the
S256 / plain challenges.
Method used to derive the challenge. S256 unless auth.oauth_pkce.allow_plain_method is set.
"S256" | "plain"User's choices for the API key that will be issued on exchange. Mirrors the fields shown in the self-service "Create API Key" modal.
Response Body
application/json
application/json
application/json
application/json
curl -X POST "https://loading/admin/v1/oauth/authorize" \ -H "Content-Type: application/json" \ -d '{ "callback_url": "string", "code_challenge": "string", "code_challenge_method": "S256" }'{
"code": "string",
"expires_at": "2019-08-24T14:15:22Z",
"redirect_url": "string"
}{
"error": {
"code": "budget_exceeded",
"message": "Budget limit exceeded for monthly period",
"param": null,
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"type": "invalid_request_error"
}
}{
"error": {
"code": "budget_exceeded",
"message": "Budget limit exceeded for monthly period",
"param": null,
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"type": "invalid_request_error"
}
}{
"error": {
"code": "budget_exceeded",
"message": "Budget limit exceeded for monthly period",
"param": null,
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"type": "invalid_request_error"
}
}Validate a `callback_url` against the deployment's OAuth PKCE policy without issuing a code. The consent UI calls this on mount and refuses to render if the URL is rejected — closing the gap where a "Deny" click could otherwise redirect to a host the operator denied.
Authorization
api_key API key authentication using Bearer token format
In: header
Query Parameters
The callback URL the external app intends to use.
Response Body
application/json
application/json
application/json
application/json
curl -X GET "https://loading/admin/v1/oauth/preflight?callback_url=string"{
"callback_host": "string"
}{
"error": {
"code": "budget_exceeded",
"message": "Budget limit exceeded for monthly period",
"param": null,
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"type": "invalid_request_error"
}
}{
"error": {
"code": "budget_exceeded",
"message": "Budget limit exceeded for monthly period",
"param": null,
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"type": "invalid_request_error"
}
}{
"error": {
"code": "budget_exceeded",
"message": "Budget limit exceeded for monthly period",
"param": null,
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"type": "invalid_request_error"
}
}Exchange a PKCE authorization code for a user-scoped API key.
Authorization
api_key API key authentication using Bearer token format
In: header
Request Body
application/json
The authorization code received via the callback URL. We generate 256-bit codes, so anything shorter than ~32 chars is definitely not one of ours; the upper bound just defends the deserializer.
The original PKCE verifier the external app generated. Length range matches RFC 7636 §4.1, which mandates 43–128 URL-safe characters.
Response Body
application/json
application/json
application/json
curl -X POST "https://loading/oauth/token" \ -H "Content-Type: application/json" \ -d '{ "code": "string", "code_verifier": "string" }'{
"key": "string",
"key_id": "1e779c8a-6786-4c89-b7c3-a6666f5fd6b5",
"key_prefix": "string"
}{
"error": {
"code": "budget_exceeded",
"message": "Budget limit exceeded for monthly period",
"param": null,
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"type": "invalid_request_error"
}
}{
"error": {
"code": "budget_exceeded",
"message": "Budget limit exceeded for monthly period",
"param": null,
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"type": "invalid_request_error"
}
}