Skip to content

Signing

Hosted and external signing session orchestration.

v1 · 2026-01-15

GET/signing/client-sessionsRequires authentication

Find a participant's client signing session by contract

For hosts that know the contract (and maybe the participant) but not the session id. Returns the participant's newest open session, else its newest session of any status. - **Signer token**: pinned to its own contract and participant; `participantId` may be omitted. Any other contract or participant returns `403`. - **Machine key** (`contracts:read`): when `participantId` is omitted and the contract has exactly one pending `integrator_managed` signer, that signer is used; otherwise `409 PARTICIPANT_REQUIRED`.

Parameters

NameInTypeRequired
contractIdquerystringYes
participantIdquerystringNo
X-SDK-PlatformheaderstringNo
X-SDK-VersionheaderstringNo

Responses

  • 200Session details
  • defaultStandardized API error
POST/signing/client-sessionsRequires authentication

Create client-side signing session (advanced/enterprise)

Parameters

NameInTypeRequired
Idempotency-KeyheaderstringNo

Request body

  • contractIdstringrequired
  • participantIdstringrequired
  • providerKeystringrequired
  • providerTypestring
  • channelstring
  • sessionTtlMinutesinteger

Responses

  • 201Session created
  • defaultStandardized API error
GET/signing/client-sessions/{sessionId}Requires authentication

Get client signing session (advanced/enterprise)

Callable with a machine key or with the signer token that the access route issued for **this** session (SigningKit). A signer token for any other session gets `403 AUTH_SIGNER_TOKEN_SESSION_MISMATCH`; once the session has ended, or its contract or participant can no longer sign, the token gets `410 SESSION_EXPIRED`. Signer tokens are limited to 60 requests/min each. SDK callers send `X-SDK-Platform` and `X-SDK-Version`; an SDK older than the organization minimum gets `426 SDK_OUTDATED`. Every response carries `X-Request-Id`. **Encrypted channel (SigningKit v2).** For signer tokens this route, `package`, `identity-session[/complete]`, `identity-checks`, `media`, `registration-request`, `complete`, `cancel` and `provider-submission` are sealed routes: after `POST .../handshake` they take and return sealed envelopes. Under the organization policy `required`, this route answers metadata only (`id`, `status`, `contractId`, `participantId`, `expiresAt`, `secureChannel`, `sdk.channelKeys`) before a handshake, and plain requests on the other sealed routes get `426 CHANNEL_REQUIRED`. Machine keys are never sealed.

Parameters

NameInTypeRequired
sessionIdpathstringYes
X-SDK-PlatformheaderstringNo
X-SDK-VersionheaderstringNo

Responses

  • 200Session details
  • defaultStandardized API error
POST/signing/client-sessions/{sessionId}/cancelRequires authentication

Cancel client signing session (advanced/enterprise)

Callable with a machine key or with the signer token that the access route issued for **this** session (SigningKit). A signer token for any other session gets `403 AUTH_SIGNER_TOKEN_SESSION_MISMATCH`; once the session has ended, or its contract or participant can no longer sign, the token gets `410 SESSION_EXPIRED`. Signer tokens are limited to 60 requests/min each. SDK callers send `X-SDK-Platform` and `X-SDK-Version`; an SDK older than the organization minimum gets `426 SDK_OUTDATED`. Every response carries `X-Request-Id`.

Parameters

NameInTypeRequired
sessionIdpathstringYes
X-SDK-PlatformheaderstringNo
X-SDK-VersionheaderstringNo
Idempotency-KeyheaderstringNo

Request body

  • reasonstring
  • stagestringJourney step the signer cancelled at (SigningKit); stored as `cancelStage` and published in the webhook.

Responses

  • 200Session cancelled
  • defaultStandardized API error
POST/signing/client-sessions/{sessionId}/completeRequires authentication

Submit signed artifact to complete client signing (advanced/enterprise)

Callable with a machine key or with the signer token that the access route issued for **this** session (SigningKit). A signer token for any other session gets `403 AUTH_SIGNER_TOKEN_SESSION_MISMATCH`; once the session has ended, or its contract or participant can no longer sign, the token gets `410 SESSION_EXPIRED`. Signer tokens are limited to 60 requests/min each. SDK callers send `X-SDK-Platform` and `X-SDK-Version`; an SDK older than the organization minimum gets `426 SDK_OUTDATED`. Every response carries `X-Request-Id`.

Parameters

NameInTypeRequired
sessionIdpathstringYes
X-SDK-PlatformheaderstringNo
X-SDK-VersionheaderstringNo
Idempotency-KeyheaderstringNo

Request body

  • sessionNoncestringrequired
  • inputHashEchostringrequired
  • identityCheckIdsarrayIdentity checks the device considers part of this completion (SigningKit). The server gates on its own records; while a required kind has no passed record the call answers `409 IDENTITY_REQUIRED`.
  • journeyIdstringSDK journey id, stored on the session for the debugger (SigningKit).
  • artifactobjectrequired
  • providerReceiptobjectWhen the session has a signing-provider registration (SigningKit v2), must carry `transactionId` and `tcspTransactionId` from the provider; the signed PDF's PAdES signature is then verified (against the configured certification-provider trust anchors when present).
  • registrationRefstringRequired when the session has a signing-provider registration (SigningKit v2); the `registrationRef` of the registration request the device used.

Responses

  • 200Completion accepted
  • 400`REQUEST_BODY_INVALID` — the body is not parseable JSON or multipart
  • 413`PAYLOAD_TOO_LARGE` — the request body exceeds the route limit
  • defaultStandardized API error
POST/signing/client-sessions/{sessionId}/eventsRequires authentication

Ship SDK telemetry events for the session (SigningKit)

Batch of up to 100 events / 512 KB validated against the SDK's `events.schema.json`. A batch is never refused for one bad event: the `202` response reports `accepted` and `dropped[]` (reasons `invalid`, `context_mismatch`, `budget_exceeded`, `write_failed`). `eventId` is idempotent. Signer tokens get 600 events per minute and every organization has a daily budget; both limits answer `429` with `Retry-After`. Events are redacted server-side (allow-listed attributes, 200-char strings, no base64, no tokens) and expire after the organization's telemetry retention.

Parameters

NameInTypeRequired
sessionIdpathstringYes
X-SDK-PlatformheaderstringNo
X-SDK-VersionheaderstringNo
Idempotency-KeyheaderstringNo

Request body

  • eventsarrayrequired

Responses

  • 202Batch accepted (`data.accepted`, `data.dropped[]`)
  • 400`REQUEST_BODY_INVALID` — the body is not parseable JSON or multipart
  • 413`PAYLOAD_TOO_LARGE` — the request body exceeds the route limit
  • defaultStandardized API error
POST/signing/client-sessions/{sessionId}/handshakeRequires authentication

Encrypted channel key agreement (SigningKit v2)

Signer token only (machine keys never use the channel). The SDK sends an ephemeral P-256 public key and a 32-byte nonce; the server answers its own ephemeral key, nonce and an Ed25519 signature over the transcript with the key published at `GET /api/public/sdk/keys`. Both sides derive per-direction AES-256-GCM keys with HKDF-SHA256. Afterwards the sealed routes take and return `application/vnd.platform.sealed+json` envelopes (`{ v, kid, seq, nonce, ct }`; bodyless and multipart requests carry the envelope in `X-Channel-Envelope`). Byte-level rules and known-answer vectors: the SigningKit API contract §14 and `test-vectors/channel-v1.json`. The organization's `sealedChannel` policy decides whether plain requests are still accepted (`required` gives `426 CHANNEL_REQUIRED`). 10 handshakes per token per minute. A new handshake replaces the keys.

Parameters

NameInTypeRequired
sessionIdpathstringYes
X-SDK-PlatformheaderstringNo
X-SDK-VersionheaderstringNo
Idempotency-KeyheaderstringNo

Request body

  • clientPubstringrequiredBase64 of the 65-byte uncompressed P-256 ephemeral public key.
  • clientNoncestringrequiredBase64 of 32 random bytes.
  • sdkobject

Responses

  • 201Handshake accepted (`data.handshake = { kid, serverPub, serverNonce, sig, expiresAt }`)
  • defaultStandardized API error
POST/signing/client-sessions/{sessionId}/identity-checksRequires authentication

Record an identity check for the session's signer (SigningKit)

Posted by the mobile SDK after each identity step (`otp`, `document`, `biometrics`), or by a machine key on the signer's behalf. The server assigns `attempt`, `receivedAt`, `integrity` and `ipAddress`, re-runs the document field rules (it may force `outcome: failed` with `serverDecision.code` `DOCUMENT_REJECTED` or `IDENTITY_MISMATCH`), encrypts the payload at rest and returns the participant's updated `identity` block. Records are append-only. Send `Idempotency-Key` (`<journeyId>:<step>:<attempt>`) so a retried post replays the first record.

Parameters

NameInTypeRequired
sessionIdpathstringYes
X-SDK-PlatformheaderstringNo
X-SDK-VersionheaderstringNo
Idempotency-KeyheaderstringNo

Request body

  • kindstringrequired
  • providerobjectrequired
  • referenceIdstringrequired
  • outcomestringrequired
  • sourcestring
  • recordedAtstringrequired
  • timezonestring
  • journeyIdstring
  • deviceobjectDevice snapshot (platform, osVersion, model, deviceId, appId, appVersion, sdkVersion, providerSdkVersions, locale, networkType, rooted, emulator).
  • locationobject
  • mediaarray
  • ruleResultsarray
  • errorobject
  • payloadobjectrequiredProvider result (≤ 256 KB). Encrypted at rest; only its SHA-256 (`integrity`) is stored in clear.

Responses

  • 201Identity check recorded (`data.identityCheck`)
  • 400`REQUEST_BODY_INVALID` — the body is not parseable JSON or multipart
  • 413`PAYLOAD_TOO_LARGE` — the request body exceeds the route limit
  • defaultStandardized API error
POST/signing/client-sessions/{sessionId}/identity-sessionRequires authentication

Start (or resume) the provider-run identity session (SigningKit v2)

Signer token only; a sealed route. The server creates the eKYC provider session server-to-server for the participant's person record and returns only what the provider's mobile SDK needs for this journey (`baseUrl`, `bundleKey`, `sessionToken`, `language`, `documentType`, `userReferenceId`) as `data.identitySession`. Idempotent per signing session: an open identity session is returned again (200); once the participant is verified the answer is 200 with `status: completed` and no hand-off, so the SDK skips the step. The device never receives the provider's server credentials and never sends identity data back.

Parameters

NameInTypeRequired
sessionIdpathstringYes
X-SDK-PlatformheaderstringNo
X-SDK-VersionheaderstringNo
Idempotency-KeyheaderstringNo

Request body

  • languagestring

Responses

  • 200Existing identity session (or already verified)
  • 201Identity session created (`data.identitySession`)
  • defaultStandardized API error
POST/signing/client-sessions/{sessionId}/identity-session/completeRequires authentication

Report that the device finished the provider flow (SigningKit v2)

Signer token only; a sealed route. `outcome` is what the provider's SDK reported (`approved`, `rejected`, `exited`, `error`) and decides nothing: the server fetches the result and the images from the provider, evaluates its rules (a document number different from the participant's registered one is a hard block) and records the identity checks. `exited` cancels the identity session. Answers `202` with `data.identitySession = { id, status, decision, rejection }`; the SDK then polls the session until `identity.status` is `completed` or `failed`.

Parameters

NameInTypeRequired
sessionIdpathstringYes
X-SDK-PlatformheaderstringNo
X-SDK-VersionheaderstringNo
Idempotency-KeyheaderstringNo

Request body

  • identitySessionIdstring
  • outcomestringrequired
  • deviceIDstring
  • providerCodestring
  • flowLogarray

Responses

  • 202Report accepted (`data.identitySession`)
  • defaultStandardized API error
POST/signing/client-sessions/{sessionId}/mediaRequires authentication

Upload identity media for the next identity check (SigningKit)

Multipart upload. Field names are the media kinds: `id_front`, `id_back`, `selfie` (JPEG/PNG/WebP, 2 MB each) and `liveness_frames` (repeated; up to 60 files, 100 KB each, 6 MB in total). Frames are rendered server-side into one animated WebP returned as `liveness_animation`. The response lists opaque `storageRef`s to reference from the identity check; media is stored encrypted and is never returned to the device. Signer tokens are limited to 20 uploads per minute (`429` with `Retry-After`).

Parameters

NameInTypeRequired
sessionIdpathstringYes
X-SDK-PlatformheaderstringNo
X-SDK-VersionheaderstringNo
Idempotency-KeyheaderstringNo

Responses

  • 201Stored media (`data.media[]`)
  • 400`REQUEST_BODY_INVALID` — the body is not parseable JSON or multipart
  • 413`PAYLOAD_TOO_LARGE` — the request body exceeds the route limit
  • defaultStandardized API error
GET/signing/client-sessions/{sessionId}/packageRequires authentication

Retrieve source signing package (advanced/enterprise)

Callable with a machine key or with the signer token that the access route issued for **this** session (SigningKit). A signer token for any other session gets `403 AUTH_SIGNER_TOKEN_SESSION_MISMATCH`; once the session has ended, or its contract or participant can no longer sign, the token gets `410 SESSION_EXPIRED`. Signer tokens are limited to 60 requests/min each. SDK callers send `X-SDK-Platform` and `X-SDK-Version`; an SDK older than the organization minimum gets `426 SDK_OUTDATED`. Every response carries `X-Request-Id`. When the participant has identity fields (SigningKit v2), the package waits for identity verification (`409 IDENTITY_SESSION_NOT_COMPLETED`) and then carries the document re-rendered with the verified values; `inputHash` is that render's hash.

Parameters

NameInTypeRequired
sessionIdpathstringYes
X-SDK-PlatformheaderstringNo
X-SDK-VersionheaderstringNo
modequerystringNo

Responses

  • 200Signing source package
  • defaultStandardized API error
POST/signing/client-sessions/{sessionId}/provider-submissionRequires authentication

Report the signed contract's filing with the certification provider (SigningKit v2)

Signer token only; a sealed route; the one write a completed session accepts. After `/complete` the session's `providerSubmission.status` is `pending`; the device reports `submitted` or `failed` (with the provider's code) after the registration SDK's contract submission. `submitted` is terminal and idempotent; a receipt that differs from the one accepted at completion is refused. Webhooks `contract.provider_submission.pending|completed|failed`.

Parameters

NameInTypeRequired
sessionIdpathstringYes
X-SDK-PlatformheaderstringNo
X-SDK-VersionheaderstringNo
Idempotency-KeyheaderstringNo

Request body

  • registrationRefstringrequired
  • transactionIdstringrequired
  • tcspTransactionIdstringrequired
  • submittedAtstringrequired
  • statusstringrequired
  • errorobject

Responses

  • 200Recorded (`data.providerSubmission = { status, attempts, submittedAt }`)
  • defaultStandardized API error
POST/signing/client-sessions/{sessionId}/registration-requestRequires authentication

Signing-provider registration request (SigningKit v2)

Signer token only; a sealed route; 5 per minute per token. Requires the organization's external signing provider to be enabled, the journey's app registered and active (`X-SDK-App-Id`, `X-SDK-App-Name`, read by the SDK from its host package), an approved identity session, an allowed ID type and the signer's mobile number. The server mints the `TransactionID` per attempt, builds the provider payload from the server-held identity profile and images, e-seals it (`signedRequestData`, CAdES-B-B over the canonical JSON) and returns `data.registrationRequest` with the registration SDK's 20 parameters (`registration`), the certification provider block (`tcsp`), the signing service block (`signing`, including the OTP `channelId`) and `signer.nationalId`. Credentials are for one journey, in memory only. `?purpose=submission` (completed session with an open provider submission) returns only `registrationRef`, `tcsp` and `expiresAt`. `501 SIGNING_PROVIDER_REGISTRATION_NOT_CONFIGURED` only when no e-seal certificate is active; `503 SIGNING_PROVIDER_CERT_EXPIRED` (with `Retry-After`) when it expired.

Parameters

NameInTypeRequired
sessionIdpathstringYes
X-SDK-PlatformheaderstringNo
X-SDK-VersionheaderstringNo
X-SDK-App-IdheaderstringNo
X-SDK-App-NameheaderstringNo
purposequerystringNo
Idempotency-KeyheaderstringNo

Responses

  • 201Registration request built (`data.registrationRequest`)
  • defaultStandardized API error
POST/signing/contracts/{contractId}/external/dispatchRequires authentication

Trigger external organization signing dispatch (advanced)

Parameters

NameInTypeRequired
contractIdpathstringYes
Idempotency-KeyheaderstringNo

Request body

  • forceDispatchboolean

Responses

  • 200Dispatch result
  • defaultStandardized API error
GET/signing/contracts/{contractId}/external/requestsRequires authentication

List external signing requests for contract (advanced)

Parameters

NameInTypeRequired
contractIdpathstringYes

Responses

  • 200Request list
  • defaultStandardized API error
POST/signing/contracts/{contractId}/participants/{participantId}/accessRequires authentication

Create signer access (hosted link, or client session + signer token)

Mints access for one signer participant (`action="sign"`). What you get depends on the participant's `executionChannel`: - **`platform_hosted`** — the hosted signing URL and link token (`signingUrl`, `token`). Unchanged; the request body is ignored. - **`integrator_managed`** (SigningKit / mobile SDK) — opens, or reuses the open, client signing session for the participant and returns `sessionId` + `signerToken`. Hand both to your app: the signer token authenticates the device on `/signing/client-sessions/{sessionId}`, `/package`, `/complete` and `/cancel` for **that session only** (`signerBearer`). It expires at `expiresAt` (default 120 min, max 24 h, never after the session). Once the session completes, is cancelled or fails the token stays valid for reads and telemetry only (the SDK replays `complete` and ships its final events after the fact); expiry revokes it. Calling again returns the same session with a fresh token. - any other channel returns `409 SIGNING_EXECUTION_CHANNEL_MISMATCH`. **Requires the `contracts:send` scope.** It previously accepted `contracts:read` OR `contracts:send`, so a read-only key could mint a signing link. The token this returns authenticates the participant and produces a binding signature — issuing it is not a read. A key without `contracts:send` receives `403 PERMISSION_DENIED`. A signer token cannot call this route.

Parameters

NameInTypeRequired
contractIdpathstringYes
participantIdpathstringYes
Idempotency-KeyheaderstringNo

Request body

  • providerKeystringClient signing provider for the session. Defaults to `generic_pdf_signer`.
  • sessionTtlMinutesinteger
  • tokenTtlMinutesintegerSigner token lifetime. Defaults to 120; never extends past the session's expiry.

Responses

  • 200Signer access. `data.access` is `HostedSignerAccess` for a `platform_hosted` participant, `ClientSignerAccess` for an `integrator_managed` one.
  • defaultStandardized API error
GET/signing/external/providersRequires authentication

List external signing providers

Responses

  • 200External provider list
  • defaultStandardized API error
GET/signing/external/requests/{requestId}Requires authentication

Get external signing request details (advanced)

Parameters

NameInTypeRequired
requestIdpathstringYes

Responses

  • 200Request details
  • defaultStandardized API error
POST/signing/external/requests/{requestId}/retryRequires authentication

Retry external signing request dispatch (advanced)

Parameters

NameInTypeRequired
requestIdpathstringYes
Idempotency-KeyheaderstringNo

Request body

  • forceDispatchboolean

Responses

  • 200Retry result
  • defaultStandardized API error
GET/signing/providersRequires authentication

List client signing providers from registry

Parameters

NameInTypeRequired
providerTypequerystringNo

Responses

  • 200Provider list
  • defaultStandardized API error
POST/signing/sdk-eventsRequires authentication

Ship pre-session SDK telemetry events (SigningKit)

Events emitted before the SDK has resolved its session (security gate, journey start) carry `sessionId: null` and are posted here with the contract and participant. They are attached to the participant's session once it exists (24 hour window). A signer token may only post about its own contract and participant; a machine key about its own contracts. Same limits and response shape as the session route.

Parameters

NameInTypeRequired
X-SDK-PlatformheaderstringNo
X-SDK-VersionheaderstringNo
Idempotency-KeyheaderstringNo

Request body

  • contractIdstringrequired
  • participantIdstring
  • eventsarrayrequired

Responses

  • 202Batch accepted (`data.accepted`, `data.dropped[]`)
  • defaultStandardized API error