Security API

The authenticated half of identity: MFA enrolment, passkeys, recovery codes, the session list, and the security event log. An API key authenticates but is refused — a key is a credential, not a person.

Updated

On this page

16 operations, generated from openapi/signclad.v1.yaml. Try them in the interactive reference, browse every endpoint group, or read the guides for the prose version.

GET /security/events

List security events Extension

The person's own security log: sign-ins, failures, lockouts, MFA changes, passkeys, sessions, password and email changes. Cursor-paginated, newest first. Every route under /security requires a person. An API key authenticates and is then refused 403: a key has no TOTP secret, no sessions, and no security log of its own. These routes are also the one place exempt from the MFA-enrolment requirement — the only way to enrol must not itself require enrolment.

Base URL
https://api.signclad.com/api/v1
Authentication
API key or OAuth 2.1 access token

Query parameters

Name Type Required Description
type string Optional One event type from the catalog below.
limit integer Optional
cursor string Optional Opaque cursor from a previous response's next_cursor.

Responses

Status Description
200 A page of events.
401 Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.…
403 Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, an unenrolled second factor, or a signer acting out of turn. meta.error always says which.…
422 Validation failed. errors maps a field name to a message string, or to an object keyed by an error code or by a per-item key. Values are never arrays.
429 Rate limited. The message contains the literal 429 Too Many Requests for compatibility with clients that match on it.…

Example request

curl -X GET https://api.signclad.com/api/v1/security/events \
  -H "X-Api-Key: $SIGNCLAD_API_KEY"

GET /security/mfa

Get MFA status Extension

What second factors this person has, whether their role requires one, and how long they have to enrol. Also lists their passkeys and whether a TOTP enrolment is waiting to be confirmed.

Base URL
https://api.signclad.com/api/v1
Authentication
API key or OAuth 2.1 access token

Responses

Status Description
200 The status.
401 Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.…
403 Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, an unenrolled second factor, or a signer acting out of turn. meta.error always says which.…

Example request

curl -X GET https://api.signclad.com/api/v1/security/mfa \
  -H "X-Api-Key: $SIGNCLAD_API_KEY"

POST /security/mfa/totp/setup

Start authenticator enrolment Extension

Returns the shared secret in three forms — raw base32, an otpauth:// URI, and a rendered QR code as inline SVG markup — plus the parameters an authenticator needs. Nothing is enrolled until confirm succeeds.

Base URL
https://api.signclad.com/api/v1
Authentication
API key or OAuth 2.1 access token

Responses

Status Description
200 The enrolment material.
401 Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.…
403 Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, an unenrolled second factor, or a signer acting out of turn. meta.error always says which.…
422 errors.totp reads An authenticator app is already set up. Remove it before adding another.

Example request

curl -X POST https://api.signclad.com/api/v1/security/mfa/totp/setup \
  -H "X-Api-Key: $SIGNCLAD_API_KEY"

POST /security/mfa/totp/confirm

Confirm authenticator enrolment Extension

Proves the authenticator works and completes enrolment. recovery_codes is returned only when this enrolment generated the person's first set — otherwise it is null and the existing codes still stand.

Base URL
https://api.signclad.com/api/v1
Authentication
API key or OAuth 2.1 access token

Request body

application/json

Property Type Required Description
code string Required

Responses

Status Description
200 Enrolled.
401 Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.…
403 Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, an unenrolled second factor, or a signer acting out of turn. meta.error always says which.…
422 errors.code reads That code is not valid.; errors.totp reads Start the setup again: there is no enrolment waiting to be confirmed.

Example request

curl -X POST https://api.signclad.com/api/v1/security/mfa/totp/confirm \
  -H "X-Api-Key: $SIGNCLAD_API_KEY"

DELETE /security/mfa/totp

Remove the authenticator Extension

Takes a password in the body — unusual on a DELETE, and required whenever the account has a password at all. Refused when the person's role requires a second factor and this is their last one.

Base URL
https://api.signclad.com/api/v1
Authentication
API key or OAuth 2.1 access token

Request body

application/json

Property Type Required Description
password string or null Optional Required in practice whenever the account has a password.

Responses

Status Description
200 Removed.
401 Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.…
403 Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, an unenrolled second factor, or a signer acting out of turn. meta.error always says which.…
422 errors.password reads The current password is incorrect.; errors.totp reads Your role requires two-factor authentication. Add another factor before removing this one.

Example request

curl -X DELETE https://api.signclad.com/api/v1/security/mfa/totp \
  -H "X-Api-Key: $SIGNCLAD_API_KEY"

GET /security/mfa/passkeys

List passkeys Extension

This person's registered passkeys, newest first.

Base URL
https://api.signclad.com/api/v1
Authentication
API key or OAuth 2.1 access token

Responses

Status Description
200 The passkeys.
401 Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.…
403 Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, an unenrolled second factor, or a signer acting out of turn. meta.error always says which.…

Example request

curl -X GET https://api.signclad.com/api/v1/security/mfa/passkeys \
  -H "X-Api-Key: $SIGNCLAD_API_KEY"

POST /security/mfa/passkeys/register/options

Get passkey creation options Extension

Returns the WebAuthn PublicKeyCredentialCreationOptions to hand to navigator.credentials.create(), unwrapped at the top level. The object is passed through from the WebAuthn library with null values omitted, so optional members are absent rather than null and the exact key set follows that library rather than this document.

Base URL
https://api.signclad.com/api/v1
Authentication
API key or OAuth 2.1 access token

Responses

Status Description
200 The creation options, verbatim.
401 Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.…
403 Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, an unenrolled second factor, or a signer acting out of turn. meta.error always says which.…
422 errors.passkeys reads You have reached the maximum number of passkeys.

Example request

curl -X POST https://api.signclad.com/api/v1/security/mfa/passkeys/register/options \
  -H "X-Api-Key: $SIGNCLAD_API_KEY"

POST /security/mfa/passkeys/register/verify

Finish registering a passkey Extension

Verifies the attestation from navigator.credentials.create() and stores the passkey. recovery_codes comes back only when this was the person's first second factor.

Base URL
https://api.signclad.com/api/v1
Authentication
API key or OAuth 2.1 access token

Request body

application/json

Property Type Required Description
credential object Required The credential the browser returned, forwarded verbatim.
name string Required

Responses

Status Description
201 Registered.
401 Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.…
403 Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, an unenrolled second factor, or a signer acting out of turn. meta.error always says which.…
422 errors.credential reads The sign-in attempt expired. Start again. or That passkey could not be verified.

Example request

curl -X POST https://api.signclad.com/api/v1/security/mfa/passkeys/register/verify \
  -H "X-Api-Key: $SIGNCLAD_API_KEY"

PATCH /security/mfa/passkeys/{passkey}

Rename a passkey Extension

Only the name can change. Ownership is checked before validation, so a passkey belonging to somebody else is 404 even when the body is also invalid.

Base URL
https://api.signclad.com/api/v1
Authentication
API key or OAuth 2.1 access token

Path parameters

Name Type Description
passkey string The passkey's id.

Request body

application/json

Property Type Required Description
name string Required

Responses

Status Description
200 Renamed. No mfa block here.
401 Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.…
403 Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, an unenrolled second factor, or a signer acting out of turn. meta.error always says which.…
404 No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative.
422 Validation failed. errors maps a field name to a message string, or to an object keyed by an error code or by a per-item key. Values are never arrays.

Example request

curl -X PATCH https://api.signclad.com/api/v1/security/mfa/passkeys/{passkey} \
  -H "X-Api-Key: $SIGNCLAD_API_KEY"

DELETE /security/mfa/passkeys/{passkey}

Remove a passkey Extension

No password re-authentication here, unlike removing an authenticator. Refused when the person's role requires a second factor and this is their last one.

Base URL
https://api.signclad.com/api/v1
Authentication
API key or OAuth 2.1 access token

Path parameters

Name Type Description
passkey string The passkey's id.

Responses

Status Description
200 Removed.
401 Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.…
403 Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, an unenrolled second factor, or a signer acting out of turn. meta.error always says which.…
404 No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative.
422 errors.passkey reads Your role requires two-factor authentication. Add another factor before removing this one.

Example request

curl -X DELETE https://api.signclad.com/api/v1/security/mfa/passkeys/{passkey} \
  -H "X-Api-Key: $SIGNCLAD_API_KEY"

GET /security/mfa/recovery_codes

Count remaining recovery codes Extension

How many codes are left, and how many a fresh set contains. The codes themselves are never returned here.

Base URL
https://api.signclad.com/api/v1
Authentication
API key or OAuth 2.1 access token

Responses

Status Description
200 The counts.
401 Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.…
403 Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, an unenrolled second factor, or a signer acting out of turn. meta.error always says which.…

Example request

curl -X GET https://api.signclad.com/api/v1/security/mfa/recovery_codes \
  -H "X-Api-Key: $SIGNCLAD_API_KEY"

POST /security/mfa/recovery_codes

Generate a new set of recovery codes Extension

Replaces any existing codes and returns the new ones — the only time they are shown. Takes password when the account has one.

Base URL
https://api.signclad.com/api/v1
Authentication
API key or OAuth 2.1 access token

Request body

application/json

Property Type Required Description
password string or null Optional

Responses

Status Description
201 The new codes.
401 Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.…
403 Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, an unenrolled second factor, or a signer acting out of turn. meta.error always says which.…
422 errors.password reads The current password is incorrect.

Example request

curl -X POST https://api.signclad.com/api/v1/security/mfa/recovery_codes \
  -H "X-Api-Key: $SIGNCLAD_API_KEY"

PUT /security/password

Change the password Extension

Revokes every other session and reports how many; the current session survives. current_password is required whenever the account has one — a Google-only account has none. The new password is checked against a breach corpus, so a long password can still be refused.

Base URL
https://api.signclad.com/api/v1
Authentication
API key or OAuth 2.1 access token

Request body

application/json

Property Type Required Description
password string Required At least 12 characters and at most 72 bytes, checked against a breach corpus. A long password that appears in a known breach is refused with a 422, so length alone is not a guarantee the value will be accepted.
current_password string or null Optional

Responses

Status Description
200 Changed.
401 Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.…
403 Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, an unenrolled second factor, or a signer acting out of turn. meta.error always says which.…
422 errors.current_password reads The current password is incorrect.

Example request

curl -X PUT https://api.signclad.com/api/v1/security/password \
  -H "X-Api-Key: $SIGNCLAD_API_KEY"

GET /security/sessions

List active sessions Extension

Every signed-in session for this person, with the current one flagged, and the session policy.

Base URL
https://api.signclad.com/api/v1
Authentication
API key or OAuth 2.1 access token

Responses

Status Description
200 The sessions.
401 Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.…
403 Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, an unenrolled second factor, or a signer acting out of turn. meta.error always says which.…

Example request

curl -X GET https://api.signclad.com/api/v1/security/sessions \
  -H "X-Api-Key: $SIGNCLAD_API_KEY"

POST /security/sessions/revoke_others

Sign out every other session Extension

Keeps this session and revokes the rest. revoked is a count, as it is on DELETE /security/sessions/{session}.

Base URL
https://api.signclad.com/api/v1
Authentication
API key or OAuth 2.1 access token

Responses

Status Description
200 How many were revoked.
401 Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.…
403 Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, an unenrolled second factor, or a signer acting out of turn. meta.error always says which.…

Example request

curl -X POST https://api.signclad.com/api/v1/security/sessions/revoke_others \
  -H "X-Api-Key: $SIGNCLAD_API_KEY"

DELETE /security/sessions/{session}

Revoke one session Extension

Revoking the current session is allowed, and was_current says whether that is what happened. revoked counts what was revoked, the same as on revoke_others.

Base URL
https://api.signclad.com/api/v1
Authentication
API key or OAuth 2.1 access token

Path parameters

Name Type Description
session string The session's id.

Responses

Status Description
200 Revoked.
401 Missing or invalid credentials. Unauthenticated requests are rate limited at 50 per minute.…
403 Authenticated, but not allowed to do this: an insufficient role, a credential type the route refuses, an unenrolled second factor, or a signer acting out of turn. meta.error always says which.…
404 No such record for this workspace. Signclad never answers 404 for a record that exists: a 404 is authoritative.

Example request

curl -X DELETE https://api.signclad.com/api/v1/security/sessions/{session} \
  -H "X-Api-Key: $SIGNCLAD_API_KEY"