Add a signer to a customer's wallets
Adds a new signer to the customer’s wallet infrastructure. An add to a live (already-active) roster typically needs one admin approval — see Multi-signer wallets. The synchronous response returns a verificationUrl whose audience is given by urlAudience: a passkey signer gets their own enrollment link (urlAudience: "signer", also delivered via the wallet_signer.invited webhook) — deliver it to the signer. For a passkey signer added to a live roster this "signer" link is the FIRST of two steps, not full self-service: once the signer enrolls their passkey the add parks a roster-add ceremony for a customer admin’s co-stamp, and that admin link arrives ONLY on the wallet_ceremony.awaiting_admin_approval webhook (carrying the ceremony’s ceremonyId), never in this response. An api_key signer that parks for admin approval instead returns the admin co-stamp link inline (urlAudience: "admin", also delivered via the wallet_ceremony.awaiting_admin_approval webhook) — deliver it to an admin; a synchronously-admitted api_key signer returns null/null. A parked api_key add whose activity is still resolving at the custody provider ALSO returns null/null, but with awaitingProvider: true set — that flag is what distinguishes “nothing to do, fully admitted” from “nothing to do yet, still resolving” until the admin link becomes available (poll reissue-admin-approval, which mints it once the provider settles). If the admin webhook is lost, recover the admin link with POST /wallet-signers/{signerId}/reissue-admin-approval. When an api_key add parks on a roster that carries an ACTIVE api_key admin, the response ADDS machineApproval (a token + approvalMaterial) alongside that admin link and webhook: stamp the material with an ACTIVE api_key admin key and POST { method: "api_key", credential } to /v2/verifications/{token}/complete (credential is { signedBody, stamp, organizationId } as a nested JSON object; a JSON string of the same is deprecated and will be rejected in a future release) to activate the signer without opening the link — the same stamp-and-approve step every machine governance ceremony uses. Conduit never emails anyone — your platform delivers the link. Route by urlAudience, never assume the URL is the signer’s.
The same signing-mode roster rules as the claim apply to later adds: api_key signers are only valid under a programmatic signing mode, and api_key admins only under programmatic unattended — otherwise 422 SIGNING_MODE_ROSTER_INVALID. An api_key signer must include publicKey (compressed P-256: 33 bytes / 66 hex chars, 02/03 prefix); a key already on an active signer returns 409 API_KEY_PUBLIC_KEY_IN_USE. See Programmatic payout signing.
Authorizations
Headers
Caller-generated unique key that lets the server safely replay this request. The original response is returned for 30 days on any retry with the same key from the same organization. Required on every state-changing money-moving or resource-creating POST.
1 - 128^[A-Za-z0-9_.:-]{1,128}$"01J7B3K2X9M8N5P6Q7R8S9T0V1"
Path Parameters
"cus_1A2b3C4d5E6f7G8h9I0jKl"
Body
Email address of the signer to add
^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$"signer@example.com"
Display name of the signer
"Jane Doe"
admin = root-quorum member + signing-quorum member; signer = signing-quorum only
admin, signer How this signer will stamp. api_key requires publicKey.
passkey, api_key Machine-signer P-256 compressed public key (33 bytes, 02/03 prefix + 64 hex chars, optional 0x prefix). Required when credentialType=api_key.
^(?:0x)?(?:02|03)[0-9a-fA-F]{64}$"02a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
Response
Unique wallet signer identifier
^wsg_[0-9A-Za-z]{22}$Signer's email address
"signer@example.com"
Signer's display name
"Jane Doe"
admin = root-quorum member + signing-quorum member; signer = signing-quorum only
admin, signer How this signer stamps requests
passkey, api_key Number of passkeys enrolled for this signer
0 <= x <= 90071992547409910
Current signer status
pending_activation, activating, active, pending_removal, removed, error Timestamp when the signer was created
"2026-01-15T09:30:00.000Z"
Timestamp when the signer was last updated
"2026-01-15T09:30:00.000Z"
Synchronous URL for this add, or null when none applies. Read urlAudience to know who it is for before delivering it — a passkey add returns the signer's enrollment link, an api_key add pending approval returns a customer admin's co-stamp link. On a live roster a "signer" link is the FIRST of two links, not full self-service: after the signer enrolls their passkey the add parks a roster-add ceremony for an admin co-stamp, whose link arrives only on the wallet_ceremony.awaiting_admin_approval webhook (carrying the ceremony's ceremonyId).
"https://app.conduit.financial/verify/mtQzSU2hdy0DuZ6za2IHIoVDgXzshrFtN38kMULRDFw"
Audience of verificationUrl: signer = the new signer's credential-enrollment link (deliver to the signer) — on a live roster this is only the first of two links, the second being an admin co-stamp delivered on the wallet_ceremony.awaiting_admin_approval webhook; admin = a customer admin's approval link (deliver to an admin; also delivered via the wallet_ceremony.awaiting_admin_approval webhook); null when there is no URL.
signer, admin True only while the parked activity is still resolving at the custody provider — verificationUrl/urlAudience are null here too, but unlike a synchronously-admitted add there is a ceremonyId to track and nothing yet for any human to approve. Absent on every other outcome.
true Additional material for a machine (api_key) add that parks for approval on a roster carrying an ACTIVE api_key admin. It is handed back ALONGSIDE verificationUrl (urlAudience: "admin") and the wallet_ceremony.awaiting_admin_approval webhook, which are always present — approve either way. Stamp approvalMaterial with an ACTIVE api_key admin's P-256 key and POST { method: "api_key", credential } to /v2/verifications/{token}/complete (credential is { signedBody, stamp, organizationId } as a nested JSON object; a JSON string of the same is deprecated and will be rejected in a future release) to activate the signer — the same stamp-and-approve step every machine governance ceremony uses. Absent when the roster has no api_key admin to stamp.