🔑 API Key Management Service

Create, revoke, and validate UUID v4 API keys scoped to tenants with optional per-user binding, IP restrictions, and JWT delegation.

Base URL: http://keys.magicrunez.com

All endpoints require the X-Tenant-ID request header to scope the operation to the correct tenant. The :identifier path segment accepts either a numeric id or the UUID api_key string. The :propertyIdentifier path segment accepts either a numeric property id or the property name string.

POST http://keys.magicrunez.com/apikey/create Create a new API key for a tenant

Generates a new UUID v4 API key associated with the tenant specified in the X-Tenant-ID header. The tenant is validated against the Auth Service before the key is created. An optional set of initial properties and IP address restrictions can be supplied in the same request.

Headers

HeaderRequiredNotes
X-Tenant-IDrequiredTenant that owns the key
AuthorizationoptionalBearer <jwt> — forwarded to Auth Service for tenant validation
Content-Typerequiredapplication/json

Request Body

FieldTypeRequiredDescription
namestringrequiredHuman-readable label for the key
user_idnumberoptionalAssociate the key with a specific user
propertiesarrayoptionalInitial [{name, value}] metadata pairs
allowed_ipsstring[]optionalIP allowlist; use "*" to permit any IP

Example Request

POST http://keys.magicrunez.com/apikey/create
Content-Type: application/json
Authorization: Bearer eyJ..._token
X-Tenant-ID: abf2150b-1a4d-11f1-b99c-fe88d4cc3569

{
  "user_id": 42,
  "name": "GitHub Integration Key",
  "properties": [
    { "name": "environment", "value": "prod" },
    { "name": "service", "value": "github" }
  ],
  "allowed_ips": ["192.168.1.5", "*"]
}

Responses

// 201 Created
{
  "id": 123,
  "api_key": "f8e2e4c1-b47e-4bb0-9f77-ef01fbe7c9c2"
}

// 400 Bad Request
{ "error": { "message": "name is required" } }

// 400 Bad Request
{ "error": { "message": "X-Tenant-ID header is required" } }
POST http://keys.magicrunez.com/apikey/revoke Permanently revoke an API key

Sets the key status to revoked. Revoked keys cannot be validated but are retained for audit purposes. This operation is irreversible.

Headers

HeaderRequiredNotes
X-Tenant-IDrequiredMust match the tenant that owns the key
Content-Typerequiredapplication/json

Request Body

FieldTypeRequiredDescription
api_keystring (UUID)requiredThe UUID of the key to revoke

Example Request

POST http://keys.magicrunez.com/apikey/revoke
Content-Type: application/json
X-Tenant-ID: abf2150b-1a4d-11f1-b99c-fe88d4cc3569

{
  "api_key": "f8e2e4c1-b47e-4bb0-9f77-ef01fbe7c9c2"
}

Responses

// 200 OK
{ "success": true }

// 404 Not Found
{ "error": { "message": "API key not found" } }
POST http://keys.magicrunez.com/validate/key Validate an API key

Checks whether the supplied API key is active and satisfies all restrictions (user match, IP allowlist, optional JWT). On success the key's properties are returned. Every call is recorded in the validation log.

ⓘ The caller IP is derived automatically from the HTTP connection — it is never sent in the request body. If a JWT is required, pass it in the standard Authorization: Bearer <token> header.

Headers

HeaderRequiredNotes
X-Tenant-IDrequiredTenant context for the validation
AuthorizationoptionalBearer <jwt> — if present, the JWT is verified against the Auth Service
Content-Typerequiredapplication/json

Request Body

FieldTypeRequiredDescription
api_keystring (UUID)requiredThe UUID to validate
user_idnumberoptionalIf supplied, the key must be bound to this user

Validation Failure Reasons

Reason CodeMeaning
INVALID_KEYKey does not exist for the given tenant
REVOKEDKey has been revoked
USER_MISMATCHKey is bound to a different user (or unbound key used with a user_id)
IP_NOT_ALLOWEDCaller IP is not on the key's allowlist
JWT_INVALIDJWT verification failed or JWT does not match tenant/user

Example Request

POST http://keys.magicrunez.com/validate/key
Content-Type: application/json
X-Tenant-ID: abf2150b-1a4d-11f1-b99c-fe88d4cc3569
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

{
  "user_id": 42,
  "api_key": "f8e2e4c1-b47e-4bb0-9f77-ef01fbe7c9c2"
}

Responses

// 200 OK — valid
{
  "valid": true,
  "key_id": 123,
  "properties": [
    { "name": "environment", "value": "prod" }
  ]
}

// 200 OK — invalid
{
  "valid": false,
  "reason": "USER_MISMATCH"
}
GET http://keys.magicrunez.com/apikey/:identifier/property List all properties for an API key

Returns all name/value properties associated with the specified API key. The :identifier may be the numeric id or the UUID string of the key.

Headers

HeaderRequiredNotes
X-Tenant-IDrequiredOnly keys belonging to this tenant are accessible

Example Request

GET http://keys.magicrunez.com/apikey/f8e2e4c1-b47e-4bb0-9f77-ef01fbe7c9c2/property
Accept: application/json
X-Tenant-ID: abf2150b-1a4d-11f1-b99c-fe88d4cc3569

Responses

// 200 OK
{
  "data": [
    {
      "id": 1,
      "api_key_id": 123,
      "name": "environment",
      "value": "prod"
    }
  ]
}

// 404 Not Found
{ "error": { "message": "API key not found" } }
GET http://keys.magicrunez.com/apikey/:identifier/property/:propertyIdentifier Get a single property

Returns one property. :propertyIdentifier may be the numeric property id or the property name string (e.g. environment).

Headers

HeaderRequiredNotes
X-Tenant-IDrequiredScopes the key lookup to this tenant

Example Request

GET http://keys.magicrunez.com/apikey/f8e2e4c1-b47e-4bb0-9f77-ef01fbe7c9c2/property/environment
Accept: application/json
X-Tenant-ID: abf2150b-1a4d-11f1-b99c-fe88d4cc3569

Responses

// 200 OK
{
  "data": {
    "id": 1,
    "api_key_id": 123,
    "name": "environment",
    "value": "prod"
  }
}

// 404 Not Found
{ "error": { "message": "Property not found" } }
POST http://keys.magicrunez.com/apikey/:identifier/property Add a property to an API key

Creates a new name/value property on the specified API key.

Headers

HeaderRequiredNotes
X-Tenant-IDrequiredMust match the tenant that owns the key
Content-Typerequiredapplication/json

Request Body

FieldTypeRequiredDescription
namestringrequiredProperty name
valuestringoptionalProperty value (defaults to empty string)

Example Request

POST http://keys.magicrunez.com/apikey/f8e2e4c1-b47e-4bb0-9f77-ef01fbe7c9c2/property
Content-Type: application/json
X-Tenant-ID: abf2150b-1a4d-11f1-b99c-fe88d4cc3569

{
  "name": "environment",
  "value": "production"
}

Responses

// 201 Created
{
  "data": {
    "id": 2,
    "api_key_id": 123,
    "name": "environment",
    "value": "production"
  }
}

// 400 Bad Request
{ "error": { "message": "name is required" } }
PUT http://keys.magicrunez.com/apikey/:identifier/property/:propertyIdentifier Replace a property

Fully replaces an existing property's name and value. :propertyIdentifier may be the numeric id or the property name.

Headers

HeaderRequiredNotes
X-Tenant-IDrequiredMust match the tenant that owns the key
Content-Typerequiredapplication/json

Request Body

FieldTypeRequiredDescription
namestringrequiredNew property name
valuestringoptionalNew property value

Example Request

PUT http://keys.magicrunez.com/apikey/f8e2e4c1-b47e-4bb0-9f77-ef01fbe7c9c2/property/environment
Content-Type: application/json
X-Tenant-ID: abf2150b-1a4d-11f1-b99c-fe88d4cc3569

{
  "name": "environment",
  "value": "staging"
}

Responses

// 200 OK
{ "success": true }

// 404 Not Found
{ "error": { "message": "Property not found" } }
PATCH http://keys.magicrunez.com/apikey/:identifier/property/:propertyIdentifier Partially update a property (alias for PUT)

Behaves identically to PUT. Provided as a convenience alias for clients that prefer PATCH semantics.

Headers

HeaderRequiredNotes
X-Tenant-IDrequiredMust match the tenant that owns the key
Content-Typerequiredapplication/json

Example Request

PATCH http://keys.magicrunez.com/apikey/f8e2e4c1-b47e-4bb0-9f77-ef01fbe7c9c2/property/environment
Content-Type: application/json
X-Tenant-ID: abf2150b-1a4d-11f1-b99c-fe88d4cc3569

{
  "name": "environment",
  "value": "production"
}

Responses

// 200 OK
{ "success": true }

// 404 Not Found
{ "error": { "message": "Property not found" } }
DELETE http://keys.magicrunez.com/apikey/:identifier/property/:propertyIdentifier Delete a property from an API key

Permanently removes the specified property from the API key. :propertyIdentifier may be the numeric id or the property name.

Headers

HeaderRequiredNotes
X-Tenant-IDrequiredMust match the tenant that owns the key

Example Request

DELETE http://keys.magicrunez.com/apikey/f8e2e4c1-b47e-4bb0-9f77-ef01fbe7c9c2/property/environment
Accept: application/json
X-Tenant-ID: abf2150b-1a4d-11f1-b99c-fe88d4cc3569

Responses

// 200 OK
{ "success": true }

// 404 Not Found
{ "error": { "message": "Property not found" } }
PUT http://keys.magicrunez.com/apikey/:identifier Regenerate an API key

Generates a new UUID value for an existing API key and returns it to the caller. The old key value is immediately invalidated. :identifier may be the numeric id or the current UUID api_key string. PATCH /apikey/:identifier is an alias for this endpoint.

Headers

HeaderRequiredNotes
X-Tenant-IDrequiredMust match the tenant that owns the key

Example Request

PUT http://keys.magicrunez.com/apikey/123
Accept: application/json
X-Tenant-ID: abf2150b-1a4d-11f1-b99c-fe88d4cc3569

Responses

// 200 OK
{ "id": 123, "api_key": "new-uuid-value" }

// 404 Not Found
{ "error": { "message": "API key not found" } }