Skip to content
Micup API

Admin API keys

An Admin API key is a credential for the Admin API that lasts at most 90 days. It authenticates as the account that created it, has its own ACL set, and authenticates only requests to paths below /v1/admin.

Creating or updating a key requires a session or Admin OAuth2 bearer token, two-factor authentication on the acting account, and sudo mode. An Admin API key cannot create or update keys. Resetting or changing the owner’s password, ending all of the owner’s sessions, turning off the owner’s last second factor, a ban, or closing the account revokes every key the owner created.

Every operation on this page requires admin_api_key:manage. A successful operation records one Admin audit entry with target type admin_api_key and the X-Audit-Log-Reason header as its reason. A request that returns an error records no entry. An operation that addresses one key returns 404 ADMIN_API_KEY_NOT_FOUND when any of these holds:

  • No key has that identifier.
  • Another account created the key.
  • The key has expired.

A key is owned by the account that created it, and it stores its own ACL set. Removing an ACL from the owning account and removing an ACL from the key are separate changes.

Micup checks both sets when a request presents a key. A request passes when all of these hold:

  • The owning account holds admin:authenticate or *, can still sign in, and has two-factor authentication.
  • The owning account holds the ACL the operation requires, or *.
  • The key itself has that ACL, or *.

A key therefore never has wider permission than the account behind it.

FieldTypeDescription
key_idsnowflakeThe ID of the key
namestringThe name given to the key (1-100 characters)
acls1array[string]The ACLs stored on the key
created_by_user_id2snowflakeThe ID of the account that created the key, and whose identity the key assumes
created_atISO8601 timestampTime the key was created
last_used_at3?ISO8601 timestampTime the key last authenticated a request, or null when it never has
expires_at4?ISO8601 timestampTime the key stops working

1 Bounded at the size of the ACL registry. Every value written through this API is a registry member

2 Never changes, so a key cannot be transferred to another account

3 Written on every successful authentication, including when the authenticated operation is a read

4 The earlier of the stored expiry and 90 days after created_at, also for keys created before the limit. An expired key is absent from every listing and is reported as not found

{
"key_id": "1501314428688998182",
"name": "moderation-tooling",
"acls": ["user:lookup", "report:view", "report:resolve"],
"created_by_user_id": "1489200013322551296",
"created_at": "2026-05-14T09:12:44.183000+00:00",
"last_used_at": "2026-06-02T18:40:11.902000+00:00",
"expires_at": null
}

Only Create Admin API key returns this object. It has the raw credential and omits last_used_at and created_by_user_id.

FieldTypeDescription
key_idsnowflakeThe ID of the key
key1stringThe raw credential the key authenticates with
namestringThe name given to the key (1-100 characters)
created_atISO8601 timestampTime the key was created
expires_at2?ISO8601 timestampTime the key expires
acls3array[string]The ACLs stored on the key

1 An opaque key, presented as Admin <token> in the Authorization header

2 Derived from expires_in_days at the instant the key is created

3 Reflects the stored set, so a value repeated in the request appears once and a value outside the ACL registry is left out

{
"key_id": "1501314428688998182",
"key": "fa_1501314428688998182_7Qk2ZbW9xLmR4TnP0vAeJdCyHs6UgF1B",
"name": "moderation-tooling",
"created_at": "2026-05-14T09:12:44.183000+00:00",
"expires_at": "2026-08-12T09:12:44.183000+00:00",
"acls": ["user:lookup", "report:view"]
}
GET/v1/admin/api-keysAudit reason

Returns every Admin API key object the acting account created, as a bare JSON array with no ordering guarantee. Requires admin_api_key:manage.

A key past its expiry is never returned.

StatusBodyCondition
2001array[Admin API key object]Keys were returned

1 An account that created no key receives an empty array

The operation records one Admin audit entry with action list_admin_api_keys, target type admin_api_key, target ID 0, and metadata key result_count.

200 requests per minute for each authenticated user, on the admin:lookup bucket.

POST/v1/admin/api-keysAudit reason

Creates a key and returns an Admin API key creation object that has the raw credential, with HTTP 200, not 201. Requires admin_api_key:manage.

The acting credential must already have every value in acls, unless it has *. The key authenticates immediately, and its effective permission is the intersection described under Admin API key object.

FieldTypeDescription
name1stringThe name given to the key (1-100 characters)
expires_in_days2integerThe number of days until the key expires (1-90)
acls3array[string]The ACLs stored on the key, each a registry value (at most 103)
password?stringSudo verification password
mfa_method?stringSudo verification method, either totp or webauthn
mfa_code?stringSudo verification authenticator code or unconsumed backup code
webauthn_response?WebAuthn assertion objectSudo verification assertion
webauthn_challenge?stringChallenge bound to the WebAuthn assertion

1 A value that is empty after trimming is rejected, so whitespace alone is not a name

2 The stored expiry is the request instant plus this many days

3 An empty array produces a key that satisfies no operation. Micup compares acls against the presenting key’s own ACLs, so a key cannot issue a broader key

Micup rejects the request with 403 MISSING_ACL on the first ungrantable value. A request that names several ungrantable ACLs reports only that one.

StatusBodyCondition
200Admin API key creation objectKey was created
400error responseBody validation fails, including an acls value outside the ACL registry, returned as INVALID_FORM_BODY
400error responseexpires_in_days is missing or outside 1-90, returned as INVALID_FORM_BODY
400error responseThe acting account has no two-factor authentication, returned as TWO_FACTOR_REQUIRED
403error responseThe request presents an Admin API key, returned as ACCESS_DENIED
403error responseSudo mode is missing, returned as SUDO_MODE_REQUIRED
403error responseCredential type is refused, admin_api_key:manage is absent, or acls names a value the acting credential does not have

The operation records one Admin audit entry with action create_admin_api_key, target type admin_api_key, target ID equal to the new key_id, and metadata keys acls and expires_in_days. acls is the stored ACL set joined with commas. The entry has no name, no raw credential, and no sudo field.

30 requests per minute for each authenticated user, on the admin:code:generation bucket.

GET/v1/admin/api-keys/{key_id}Audit reason

Returns one Admin API key object. Requires admin_api_key:manage.

This operation never returns the raw credential.

FieldTypeDescription
key_idsnowflakeThe ID of the key
StatusBodyCondition
200Admin API key objectKey was returned
404error responseADMIN_API_KEY_NOT_FOUND, which also covers an expired key and a key created by another account

The operation records one Admin audit entry with action get_admin_api_key, target type admin_api_key, target ID equal to key_id, and no metadata.

200 requests per minute for each authenticated user, on the admin:lookup bucket.

PATCH/v1/admin/api-keys/{key_id}Audit reason

Renames a key or replaces its ACL set, and returns the updated Admin API key object. Requires admin_api_key:manage and sudo mode, and refuses an Admin API key credential.

Micup leaves an omitted field unchanged, and the supplied fields take effect on the key’s next authenticated request. The acting credential must already have every value in a supplied acls, unless it has *. A key with an expiry keeps it.

FieldTypeDescription
key_idsnowflakeThe ID of the key
FieldTypeDescription
name?1stringThe replacement name for the key (1-100 characters)
acls?2array[string]The complete replacement set of ACLs, each a registry value (at most 103)
password?stringSudo verification password
mfa_method?stringSudo verification method, either totp or webauthn
mfa_code?stringSudo verification authenticator code or unconsumed backup code
webauthn_response?WebAuthn assertion objectSudo verification assertion
webauthn_challenge?stringChallenge bound to the WebAuthn assertion

1 A value that is empty after trimming is rejected

2 An empty array leaves the key with no ACLs, so the key satisfies no operation. An empty request body is accepted and changes nothing

StatusBodyCondition
200Admin API key objectKey was updated
400error responseBody validation fails, including an acls value outside the ACL registry, returned as INVALID_FORM_BODY
400error responseThe acting account has no two-factor authentication, returned as TWO_FACTOR_REQUIRED
403error responseThe request presents an Admin API key, returned as ACCESS_DENIED
403error responseSudo mode is missing, returned as SUDO_MODE_REQUIRED
4031error responseCredential type is refused, admin_api_key:manage is absent, or acls names a value the acting credential does not have
404error responseADMIN_API_KEY_NOT_FOUND, which also covers an expired key and a key created by another account

1 The ownership check runs before the ACL grant check, so a key belonging to another account returns 404, not 403

The operation records one Admin audit entry with action update_admin_api_key, target type admin_api_key, target ID equal to key_id, and metadata keys fields and acls. fields lists the supplied field names joined with commas, and is empty for an empty body. acls is the stored ACL set joined with commas, present only when the request supplied acls. The entry has no name.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.

DELETE/v1/admin/api-keys/{key_id}Audit reason

Revokes an Admin API key and returns HTTP 200 with a response body. Requires admin_api_key:manage.

The credential stops authenticating on its next use. A request already in flight runs to completion.

FieldTypeDescription
key_idsnowflakeThe ID of the key
FieldTypeDescription
successbooleanAlways true
StatusBodyCondition
200response bodyKey was revoked
404error responseADMIN_API_KEY_NOT_FOUND, which also covers an expired key and a key created by another account

The operation records one Admin audit entry with action revoke_admin_api_key, target type admin_api_key, target ID equal to key_id, and no metadata.

100 requests per minute for each authenticated user, on the admin:user:modify bucket.