pending, the user acts (signs or denies) in the signing UI, and the status transitions to signed, denied, or expired.
When to use signing
Signing is appropriate when you need non-repudiable user approval — situations where “the user clicked a button” is not strong enough evidence. Examples:- Approving a high-value transaction
- Consenting to a legal document or contract
- Authorizing an irreversible data change
- Confirming a sensitive account action
Full flow
1
Create a signature request
Call your server, which calls
POST /api/signing/request using your app credentials plus the target identity and the payload to be signed.identityId is the Ave identity UUID (the sub from the user’s id_token). payload is the string the user will see and sign — keep it human-readable. The identity must have a signing key set up, or the request will fail.2
Present the signing UI to the user
Show the Ave signing interface to the user. They will see the payload and choose to sign or deny.Alternatively, use
openAveSigningPopup for a popup window, or build a custom polling UX without the embed library.3
Poll for request status
If you need to track status independently of the embed callback (for example in a server polling loop or when the user is on a separate device), poll the status endpoint:
4
Verify the signature before taking action
After receiving a
signed status, verify the signature server-side before executing any side effects.Create request body
string
required
Your app’s client ID.
string
required
Your app’s client secret. This call must be server-side only.
string
required
UUID of the Ave identity that will sign the request. This is the
sub claim from the user’s id_token.string
required
The string the user will see and sign. Maximum 10,000 characters. Keep it human-readable and descriptive — the user should understand what they are approving.
object
Optional arbitrary JSON metadata. Not shown to the user directly but attached to the request record.
number
default:"300"
How long the request stays open before automatically expiring. Minimum 60, maximum 3600 (1 hour).
Create request response
string
UUID identifying this signing request. Pass this to the status endpoint and the embed UI.
string
ISO 8601 timestamp when the request expires.
string
The Ed25519 public key for this identity, in base64. Store it if you want to verify signatures locally.
Request states
The server transitions
pending requests to expired automatically when the status endpoint is queried after the expiry time.
Verification
POST /api/signing/verify validates a message/signature/publicKey tuple:
Practical lifecycle
1
Create and persist locally
Create the request via your server and immediately save it to your own database with
pending status. Record requestId, expiresAt, and publicKey.2
Surface the UI with a countdown
Start a visible countdown for the user aligned with
expiresInSeconds. Users expect to understand how long they have.3
Poll or use embed callback
Use the embed callback for interactive flows where the user is on the same device. Use server-side polling for flows where the user might be on a different device (for example, a QR-code-triggered signing).
4
Transition local state
On
signed, denied, or expired, transition your local record and update the UI. Do not execute side effects until after signature verification.5
Verify then act
After confirming
signed, call the verify endpoint (or verify locally with Ed25519). Only then execute the approved action.Edge cases
Identity has no signing key
Identity has no signing key
If the target identity has not set up a signing key, the create request call returns an error. Handle this by prompting the user to add a signing key in their Ave account before requesting a signature.
Request expires before user acts
Request expires before user acts
The status endpoint will return
expired. Clear the request from your UI and offer the user a way to restart the flow.User denies the request
User denies the request
denied is a valid terminal state. Treat it as the user explicitly rejecting the action. Do not retry automatically.Status request for wrong app
Status request for wrong app
If you query the status for a
requestId that does not belong to your clientId, you will receive a 403. Store requestId server-side in your own session and never expose it to untrusted clients.