Skip to content

API Endpoints

This page provides detailed documentation for all Voidkey broker API endpoints.

  • Base URL: https://your-broker.example.com
  • Content Type: application/json
  • Authentication: Bearer token (OIDC) in Authorization header
  • API Version: v1 (current)
MethodEndpointDescriptionAuth Required
POST/credentials/mintMint temporary credentialsYes
GET/credentials/keysList available keysYes
GET/credentials/idp-providersList identity providersNo
GET/healthHealth checkNo

Mint temporary credentials for the specified keys.

POST /credentials/mint HTTP/1.1
Host: broker.example.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
Content-Type: application/json
{
"keys": ["AWS_DEPLOY", "GCP_READONLY"]
}
{
"type": "object",
"properties": {
"oidcToken": {
"type": "string",
"description": "OIDC token (alternative to Authorization header)"
},
"keys": {
"type": "array",
"items": {
"type": "string"
},
"description": "Array of key names to mint",
"minItems": 1,
"maxItems": 10
}
},
"required": ["keys"],
"additionalProperties": false
}
{
"type": "object",
"properties": {
"credentials": {
"type": "object",
"description": "Map of key names to credential objects"
},
"expiresAt": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp when credentials expire"
},
"subject": {
"type": "string",
"description": "Subject claim from the OIDC token"
},
"issuedAt": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 timestamp when credentials were issued"
}
},
"required": ["credentials", "expiresAt", "subject", "issuedAt"]
}

AWS Credentials Response:

{
"credentials": {
"AWS_DEPLOY": {
"AWS_ACCESS_KEY_ID": "ASIATESTACCESSKEY",
"AWS_SECRET_ACCESS_KEY": "wJalrXUtnFEMI/K7MDENG/bPxRfiCY",
"AWS_SESSION_TOKEN": "FwoGZXIvYXdzEBYaD...",
"AWS_REGION": "us-east-1"
}
},
"expiresAt": "2024-01-15T11:00:00Z",
"subject": "repo:myorg/myapp:ref:refs/heads/main",
"issuedAt": "2024-01-15T10:00:00Z"
}

Multi-Provider Response:

{
"credentials": {
"AWS_DEPLOY": {
"AWS_ACCESS_KEY_ID": "ASIATESTACCESSKEY",
"AWS_SECRET_ACCESS_KEY": "wJalrXUtnFEMI/K7MDENG/bPxRfiCY",
"AWS_SESSION_TOKEN": "FwoGZXIvYXdzEBYaD..."
},
"GCP_READONLY": {
"GOOGLE_OAUTH_ACCESS_TOKEN": "ya29.A0ARrdaM...",
"GOOGLE_TOKEN_EXPIRY": "2024-01-15T11:00:00Z",
"GOOGLE_PROJECT_ID": "my-project-123"
},
"MINIO_STORAGE": {
"MINIO_ACCESS_KEY": "minioadmin",
"MINIO_SECRET_KEY": "minioadmin123",
"MINIO_SESSION_TOKEN": "temp-token",
"MINIO_ENDPOINT": "https://minio.example.com"
}
},
"expiresAt": "2024-01-15T11:00:00Z",
"subject": "repo:myorg/myapp:ref:refs/heads/main",
"issuedAt": "2024-01-15T10:00:00Z"
}

400 Bad Request - Invalid Keys:

{
"error": "INVALID_REQUEST",
"message": "Invalid keys array",
"details": {
"field": "keys",
"issues": [
"Key 'INVALID_KEY' is not valid",
"Maximum 10 keys allowed"
]
}
}

401 Unauthorized:

{
"error": "UNAUTHORIZED",
"message": "Invalid or expired OIDC token",
"details": {
"reason": "token_expired",
"expiredAt": "2024-01-15T09:30:00Z"
}
}

403 Forbidden:

{
"error": "FORBIDDEN",
"message": "Subject does not have access to requested keys",
"details": {
"subject": "repo:myorg/myapp:ref:refs/heads/feature",
"deniedKeys": ["AWS_PROD_DEPLOY"],
"allowedKeys": ["AWS_DEV_DEPLOY"]
}
}

404 Not Found:

{
"error": "NOT_FOUND",
"message": "Keys not found for subject",
"details": {
"subject": "unknown-subject",
"missingKeys": ["UNKNOWN_KEY"]
}
}

500 Internal Server Error:

{
"error": "CREDENTIAL_MINT_FAILED",
"message": "Failed to mint credentials from provider",
"details": {
"provider": "aws-prod",
"key": "AWS_DEPLOY",
"reason": "assume_role_failed"
},
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}

List all keys available to the authenticated subject.

GET /credentials/keys HTTP/1.1
Host: broker.example.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...

Alternative with query parameter:

GET /credentials/keys?token=eyJhbGciOiJSUzI1NiIs... HTTP/1.1
Host: broker.example.com
ParameterTypeRequiredDescription
tokenstringNo*OIDC token (if not in Authorization header)

*Required if Authorization header is not provided

{
"type": "object",
"properties": {
"subject": {
"type": "string",
"description": "Subject claim from the token"
},
"idp": {
"type": "string",
"description": "Identity provider name"
},
"keys": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Key identifier"
},
"provider": {
"type": "string",
"description": "Access provider name"
},
"description": {
"type": "string",
"description": "Human-readable description"
},
"maxDuration": {
"type": "integer",
"description": "Maximum session duration in seconds"
}
}
}
}
}
}
{
"subject": "repo:myorg/myapp:ref:refs/heads/main",
"idp": "github-actions",
"keys": [
{
"name": "AWS_PROD_DEPLOY",
"provider": "aws-prod",
"description": "AWS production deployment credentials",
"maxDuration": 3600
},
{
"name": "GCP_ANALYTICS",
"provider": "gcp-analytics",
"description": "GCP BigQuery read access",
"maxDuration": 7200
},
{
"name": "MINIO_STORAGE",
"provider": "minio-prod",
"description": "MinIO object storage access",
"maxDuration": 1800
}
]
}

401 Unauthorized:

{
"error": "UNAUTHORIZED",
"message": "Missing or invalid authentication token"
}

404 Not Found:

{
"error": "SUBJECT_NOT_FOUND",
"message": "No configuration found for subject",
"details": {
"subject": "unknown-subject",
"idp": "github-actions"
}
}

List all configured identity providers. This endpoint does not require authentication.

GET /credentials/idp-providers HTTP/1.1
Host: broker.example.com
{
"type": "object",
"properties": {
"providers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Provider name"
},
"issuer": {
"type": "string",
"description": "OIDC issuer URL"
},
"type": {
"type": "string",
"description": "Provider type (always 'oidc')"
}
}
}
}
}
}
{
"providers": [
{
"name": "github-actions",
"issuer": "https://token.actions.githubusercontent.com",
"type": "oidc"
},
{
"name": "auth0-dev",
"issuer": "https://dev.myorg.auth0.com/",
"type": "oidc"
},
{
"name": "keycloak",
"issuer": "https://auth.example.com/realms/developers",
"type": "oidc"
}
]
}

Health check endpoint for monitoring and load balancers.

GET /health HTTP/1.1
Host: broker.example.com
{
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": ["healthy", "unhealthy"],
"description": "Overall health status"
},
"timestamp": {
"type": "string",
"format": "date-time",
"description": "Health check timestamp"
},
"version": {
"type": "string",
"description": "Application version"
},
"uptime": {
"type": "integer",
"description": "Uptime in seconds"
},
"checks": {
"type": "object",
"description": "Individual health check results"
},
"errors": {
"type": "array",
"items": {
"type": "string"
},
"description": "Error messages (only when unhealthy)"
}
}
}
{
"status": "healthy",
"timestamp": "2024-01-15T10:30:00Z",
"version": "0.8.0",
"uptime": 3600,
"checks": {
"broker_idp": "healthy",
"config": "healthy",
"memory": "healthy",
"database": "healthy"
}
}

Unhealthy Response (503 Service Unavailable)

Section titled “Unhealthy Response (503 Service Unavailable)”
{
"status": "unhealthy",
"timestamp": "2024-01-15T10:30:00Z",
"version": "0.8.0",
"uptime": 3600,
"checks": {
"broker_idp": "unhealthy",
"config": "healthy",
"memory": "healthy",
"database": "unhealthy"
},
"errors": [
"Cannot connect to broker IdP at https://auth.example.com",
"Database connection timeout"
]
}

All endpoints (except /health) are subject to rate limiting:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 99
X-RateLimit-Reset: 1705316400
X-RateLimit-Window: 60
{
"error": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests. Please retry after 60 seconds",
"retryAfter": 60,
"details": {
"limit": 100,
"window": 60,
"resetAt": "2024-01-15T10:31:00Z"
}
}

The API supports CORS for browser-based clients:

OPTIONS /credentials/mint HTTP/1.1
Host: broker.example.com
Origin: https://app.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: authorization,content-type
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: authorization, content-type, x-request-id
Access-Control-Max-Age: 86400
Access-Control-Allow-Credentials: true

All errors follow the same JSON structure:

{
"error": "ERROR_CODE",
"message": "Human-readable error message",
"details": {
"additional": "context-specific details"
},
"requestId": "correlation-id-for-tracing",
"timestamp": "2024-01-15T10:30:00Z"
}
CodeHTTP StatusDescription
INVALID_REQUEST400Malformed request or validation error
UNAUTHORIZED401Missing, invalid, or expired authentication
FORBIDDEN403Authenticated but not authorized
NOT_FOUND404Requested resource does not exist
RATE_LIMIT_EXCEEDED429Too many requests
INTERNAL_ERROR500Unexpected server error
SERVICE_UNAVAILABLE503Service temporarily unavailable

Currently, the API is unversioned (v1 implicit). Future versions will use URL path versioning:

https://broker.example.com/v2/credentials/mint

Version support policy:

  • Current version: Fully supported
  • Previous version: Supported for 12 months after new version release
  • Deprecated versions: 6 months notice before removal