Credentials

Mint a service credential

Mint a credential and its first secret, bound to the caller's workspace.

The raw key is returned exactly once, in this response, and can never be read again. Only its SHA-256 hash is stored, alongside the prefix and last four characters used to recognise it in a list. If the response is lost, the only remedy is to rotate or to mint a new credential. Write the key field to your secret store before doing anything else with it.

The key format is isk_ followed by 40 base62 characters, 44 characters in total. The isk_ prefix is there so a leaked key is greppable. Present it as Authorization: Bearer isk_....

scopes is the grant and is required: at least one, from the ten-value vocabulary, deduplicated and returned in vocabulary order. A caller can never grant a scope it does not itself hold. This is enforced, not advisory: a request for a wider grant is refused with 403 scope_escalation, and the error names the offending scopes. A workspace admin or owner holds all ten, so the rule is invisible to them; a service credential minting another credential is bounded by its own grant, which means an agent trusted to manage credentials still cannot mint one broader than itself.

expiresAt, when given, must be in the future. A workspace holds at most 10 credentials; exceeding that answers 409 limit_exceeded.

Accepts an Idempotency-Key. A retry with the same key replays the original response verbatim, including the one-time key, instead of minting a second credential.

post/credentials

Request

  • Base URL: https://inkseal.net/api/v1
  • URL: https://inkseal.net/api/v1/credentials
  • Auth: HTTP bearer

Headers

Idempotency-Keystring

Makes this mutation retry-safe. 1 to 255 printable ASCII characters (0x20 to 0x7e), trimmed before use. The key is scoped to the workspace and the credential that sent it. Reusing it with a different method, path, or payload answers 422 idempotency_key_reuse. A completed attempt replays its stored status and body with an Idempotent-Replay: true response header; 5xx, 429, and non-JSON answers leave the key retryable. A concurrent request holding the 90 second lease answers 409 idempotency_in_progress. Records are retained 24 hours.

Request body

namestring required

A human label. Trimmed; must not be blank after trimming.

agentIdentitystring required

Who or what will act under this credential. Recorded on the audit rows it writes.

scopesCredentialScope[] required

The grant. At least one scope is required: a credential that can do nothing still authenticates, which makes it a confusing dead end. Every scope requested must be one the caller already holds, or the request is refused with 403 scope_escalation.

expiresAtstring date-time

Optional expiry. Must be in the future. Omit for a credential that does not expire on its own.

Example request

{
  "name": "Contract intake agent",
  "agentIdentity": "intake-bot@ops.example.com",
  "scopes": [
    "documents:write",
    "envelopes:write",
    "envelopes:send"
  ],
  "expiresAt": "2027-01-01T00:00:00.000Z",
  "limits": {
    "maxCreditsPerDay": 25,
    "maxSendsPerHour": 5
  }
}

Response

The credential, plus the only copy of its raw key that will ever exist. Store data.key now; it is not recoverable.

Example response

{
  "data": {
    "id": "V1StGXR8_Z5jdHi6B-myT",
    "name": "Contract intake agent",
    "agentIdentity": "intake-bot@ops.example.com",
    "scopes": [
      "documents:write",
      "envelopes:write",
      "envelopes:send"
    ],
    "isActive": true,
    "createdAt": "2026-08-01T11:02:44.000Z",
    "lastUsedAt": "2026-08-21T07:41:12.338Z",
    "secrets": [
      {
        "prefix": "isk_REDA",
        "lastFour": "CTED",
        "createdAt": "2026-08-01T11:02:44.000Z",
        "lastUsedAt": "2026-08-21T07:41:12.338Z"
      }
    ],
    "limits": {
      "maxCreditsPerDay": 25,
      "maxSendsPerHour": 5
    },
    "key": "isk_REDACTEDREDACTEDREDACTEDREDACTEDREDACTED"
  }
}

Changes

No recorded changes to this operation across all 1 revision of this API.