Create a vault
POST /vaults
Create a vault — a key that is generated and held across multiple parties
so that no single party (including XKOVA) can sign alone. The tier and
controls are fixed at creation. Key generation runs asynchronously: the
vault is returned in creating and becomes active shortly after (poll
GET /vaults/{vaultId} or listen for the webhook).
Authorizations
Section titled “Authorizations ”Request Body required
Section titled “Request Body required ”object
Where the vault’s keys live and who must authorize a signature.
hosted — XKOVA-operated, gated by your end users’ tokens (embedded wallets).
self — you hold a required share; XKOVA cannot sign without you.
customer_tee — keys run in your own trusted execution environment.
Optional policy to attach (configured with XKOVA)
Hosted tier: bind the vault to one end-user subject
Example
{ "tier": "self", "name": "treasury"}Responses
Section titled “ Responses ”Vault accepted; key generation in progress.
object
Where the vault’s keys live and who must authorize a signature.
hosted — XKOVA-operated, gated by your end users’ tokens (embedded wallets).
self — you hold a required share; XKOVA cannot sign without you.
customer_tee — keys run in your own trusted execution environment.
creating → active; resharing during a rotation (reshare_pending if one needs attention); frozen if halted
Increments each time the vault’s shares are rotated; the public key is unchanged
object
Compressed public key, hex
The request body or parameters failed validation.
Failures return a single human-readable error message; the HTTP status
carries the category (400 validation, 401 auth, 403 refused, 404 missing,
409 conflict, 429 rate limit). When a signing request is refused for a
specific reason, the message names it — for example the amount exceeds a
spend limit, the policy denied the recipient, or the intent signature did
not verify.
object
Stable machine slug (invalid_request, unauthorized, forbidden, not_found, conflict, rate_limited); a refused sign names the reason in the message
Example
{ "error": "amount must be a base-10 integer", "code": "invalid_request"}Missing, malformed, or invalid request signature.
Failures return a single human-readable error message; the HTTP status
carries the category (400 validation, 401 auth, 403 refused, 404 missing,
409 conflict, 429 rate limit). When a signing request is refused for a
specific reason, the message names it — for example the amount exceeds a
spend limit, the policy denied the recipient, or the intent signature did
not verify.
object
Stable machine slug (invalid_request, unauthorized, forbidden, not_found, conflict, rate_limited); a refused sign names the reason in the message
Example
{ "error": "request signature did not verify", "code": "unauthorized"}A quota or rate limit was reached. Retry later.
Failures return a single human-readable error message; the HTTP status
carries the category (400 validation, 401 auth, 403 refused, 404 missing,
409 conflict, 429 rate limit). When a signing request is refused for a
specific reason, the message names it — for example the amount exceeds a
spend limit, the policy denied the recipient, or the intent signature did
not verify.
object
Stable machine slug (invalid_request, unauthorized, forbidden, not_found, conflict, rate_limited); a refused sign names the reason in the message
Example
{ "error": "vault quota reached for this org", "code": "rate_limited"}