Reference
API reference
Every endpoint the XOsign API exposes. If it is not here, it does not exist.
Machine-readable
This page and /docs/api/openapi.json are generated from the same OpenAPI 3.1 document, so they cannot disagree. Import the JSON into Postman or feed it to a client generator.
Endpoints
Retrieve the current account
https://xosign.ai/api/v1/accountReturns the account behind the API key, plus the key's mode and scopes. The cheapest way to verify a key works and to see what it is allowed to do. Requires no scope.
Responses
| Status | Returns | Description |
|---|---|---|
| 200 | Account | The account. |
| 401 | Error | The request carried no usable API key, so we could not tell who you are. Codes: missing_authorization, invalid_api_key. |
| 403 | Error | We know who you are, but this key or this plan is not allowed to do that. Codes: insufficient_scope, api_access_required. |
| 429 | Error | You sent more requests than your plan allows. Carries Retry-After. Codes: rate_limit_exceeded, ip_throttled. |
| 500 | Error | Something failed on our side. Nothing is wrong with your request. |
See the Account object below for its fields.
List documents
https://xosign.ai/api/v1/documentsYour documents, newest first, cursor-paginated. An account with no documents returns an empty list, never a 404. Templates are not included.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
limit | query | Optional | How many documents to return, 1–100.defaults to 20 · 1–100 |
starting_after | query | Optional | A cursor from a previous response's `next_cursor`. Returns the page after it. Cannot be combined with `ending_before`. |
ending_before | query | Optional | A cursor from a previous response. Returns the page before it. Cannot be combined with `starting_after`. |
status | query | Optional | Comma-separated statuses to include, e.g. `sent,completed`. Any unknown value rejects the whole request. One of: draft, sent, partially_signed, completed, voided, declined, expired, in_review. |
Responses
| Status | Returns | Description |
|---|---|---|
| 200 | DocumentList | A page of documents. |
| 400 | Error | Bad pagination or status filter. Codes: invalid_limit, invalid_cursor, conflicting_cursors, invalid_status. |
| 401 | Error | The request carried no usable API key, so we could not tell who you are. Codes: missing_authorization, invalid_api_key. |
| 403 | Error | We know who you are, but this key or this plan is not allowed to do that. Codes: insufficient_scope, api_access_required. |
| 429 | Error | You sent more requests than your plan allows. Carries Retry-After. Codes: rate_limit_exceeded, ip_throttled. |
| 500 | Error | Something failed on our side. Nothing is wrong with your request. |
See the DocumentList object below for its fields.
Create a draft document
https://xosign.ai/api/v1/documentsCreates a draft and its recipients in one call. Nothing is delivered until you call send.
Field placement is not supported through the API — `content` accepts only the small metadata bag described below, and unknown properties are dropped silently.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
Idempotency-Key | header | Optional | Optional but strongly recommended on writes. A client-chosen string of at most 255 characters. Retrying with the same key and the same body replays the original response instead of performing the write twice.max 255 characters |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Required | max 200 characters |
type | string | Optional | Defaults to `form`.one of 23 values · defaults to form |
primary_language | string | Optional | one of: en, es · defaults to en |
recipients | array | Required | 1–20 items |
content | DocumentContent | Optional |
Responses
| Status | Returns | Description |
|---|---|---|
| 201 | Document | The created draft. |
| 400 | Error | The body was rejected. `param` names the exact field. See /docs/api/errors for every code. |
| 401 | Error | The request carried no usable API key, so we could not tell who you are. Codes: missing_authorization, invalid_api_key. |
| 403 | Error | We know who you are, but this key or this plan is not allowed to do that. Codes: insufficient_scope, api_access_required. |
| 409 | Error | Idempotency conflict. Codes: idempotency_key_reused, idempotency_in_progress. |
| 429 | Error | You sent more requests than your plan allows. Carries Retry-After. Codes: rate_limit_exceeded, ip_throttled. |
| 500 | Error | Something failed on our side. Nothing is wrong with your request. |
See the Document object below for its fields.
Retrieve a document
https://xosign.ai/api/v1/documents/{id}Poll this to watch a document progress from `sent` to `completed`.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
id | path | Required | The document id. |
Responses
| Status | Returns | Description |
|---|---|---|
| 200 | Document | The document. |
| 401 | Error | The request carried no usable API key, so we could not tell who you are. Codes: missing_authorization, invalid_api_key. |
| 403 | Error | We know who you are, but this key or this plan is not allowed to do that. Codes: insufficient_scope, api_access_required. |
| 404 | Error | No such document is visible to your account. Also returned for a malformed id and for templates. Code: document_not_found. |
| 429 | Error | You sent more requests than your plan allows. Carries Retry-After. Codes: rate_limit_exceeded, ip_throttled. |
| 500 | Error | Something failed on our side. Nothing is wrong with your request. |
See the Document object below for its fields.
List imports
https://xosign.ai/api/v1/importsYour bulk imports, newest first, cursor-paginated. An account that has never imported returns an empty list, never a 404.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
limit | query | Optional | How many imports to return, 1–100.defaults to 20 · 1–100 |
starting_after | query | Optional | A cursor from a previous response's `next_cursor`. Returns the page after it. Cannot be combined with `ending_before`. |
ending_before | query | Optional | A cursor from a previous response. Returns the page before it. Cannot be combined with `starting_after`. |
status | query | Optional | Comma-separated statuses to include. Any unknown value rejects the whole request. One of: running, finished. |
Responses
| Status | Returns | Description |
|---|---|---|
| 200 | ImportList | A page of imports. |
| 400 | Error | Bad pagination or status filter. Codes: invalid_limit, invalid_cursor, conflicting_cursors, invalid_status. |
| 401 | Error | The request carried no usable API key, so we could not tell who you are. Codes: missing_authorization, invalid_api_key. |
| 403 | Error | We know who you are, but this key or this plan is not allowed to do that. Codes: insufficient_scope, api_access_required. |
| 429 | Error | You sent more requests than your plan allows. Carries Retry-After. Codes: rate_limit_exceeded, ip_throttled. |
| 500 | Error | Something failed on our side. Nothing is wrong with your request. |
See the ImportList object below for its fields.
Start an import
https://xosign.ai/api/v1/importsBrings documents into XOsign from DocuSign, Google Drive or Dropbox.
**DocuSign** (`source: docusign`) sweeps the connected account and files every completed envelope's documents, in the background. It returns immediately; poll the returned import to watch it. The account must already have connected DocuSign in Settings: that is an OAuth sign-in through a browser and cannot be done with a key.
**Google Drive and Dropbox** (`source: google_drive` or `dropbox`) import up to 25 files you name and answer when they are in — usually within seconds. Give your client at least 90 seconds before it times out; if it does time out, retry with the same `Idempotency-Key` to receive the answer. The answer carries every file's outcome in `items`, in the order you sent them, and one file failing never stops the rest. A file you have imported before comes back as the same document rather than a copy, so after a partial failure you can send the whole list again — with a new `Idempotency-Key`, or none, since the same key replays the earlier answer. For Drive, send a Google access token your own app minted; it is used for this request and kept nowhere. For Dropbox, send file links you already hold; nothing on our side connects to your Dropbox. Needs the Pro plan or above. A request naming N files spends N of your rate limit, and every file counts against your plan's import limits: files per day and storage per month. A file that comes back as a document you imported before uses no storage again, and a retry that replays an earlier answer spends one unit of your rate limit, not N.
Files land as they are and consume no pages. Set `unlock_xodoc` to also unlock each one as an XOdoc, which is what the unlock box does on an upload in the app; that conversion is charged by pages when it runs.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
Idempotency-Key | header | Optional | Optional but strongly recommended on writes. A client-chosen string of at most 255 characters. Retrying with the same key and the same body replays the original response instead of performing the write twice.max 255 characters |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
source | string | Required | `docusign` sweeps an account that is already connected in Settings (that sign-in is an OAuth redirect through a browser, so a key cannot make it) and runs in the background. `google_drive` and `dropbox` import the files you name, and answer when they are in.one of: docusign, google_drive, dropbox |
earliest | string | Optional | DocuSign only. Bring envelopes completed on or after this instant. Omit to sweep everything. |
access_token | string | Optional | Google Drive only, and required there. A Google OAuth access token minted by your own Google app with the `drive.file` or `drive.readonly` scope. It is used for this request only and never stored or logged. Google tokens last about an hour; a retry with a refreshed token counts as the same request for idempotency. |
files | array | Optional | Google Drive and Dropbox, and required there: the files to import, each up to 20 MB. PDFs are accepted; Google Docs, Sheets and Slides arrive as PDFs exported by Google, which caps an export at 10 MB. Other kinds of file, and folders, come back failed with `unsupported_type`. What a file is gets decided from its contents, never its name.1–25 items |
unlock_xodoc | boolean | Optional | Google Drive and Dropbox. Also unlock each file as an XOdoc — what ticking the unlock box does on an upload in the app. Each file reports what came of it in `unlock`, and the conversion is charged by pages when it runs, as the app charges it. Left false, files land as they are and consume nothing, and any of them can be unlocked from the document later.defaults to false |
Responses
| Status | Returns | Description |
|---|---|---|
| 201 | StartedImport | The import. A DocuSign migration has every count at zero and runs on; a Google Drive or Dropbox import is normally already finished and carries `items`. |
| 400 | Error | The body was rejected, and nothing was created. Codes: invalid_source, invalid_earliest, docusign_not_connected, invalid_files, invalid_file_url, invalid_file_id, invalid_access_token, invalid_unlock_xodoc, google_token_rejected. |
| 401 | Error | The request carried no usable API key, so we could not tell who you are. Codes: missing_authorization, invalid_api_key. |
| 403 | Error | We know who you are, but this key or this plan is not allowed to do that. Codes: insufficient_scope, api_access_required, cloud_import_requires_pro, cloud_import_unavailable, cloud_import_test_key, import_quota_exceeded. |
| 409 | Error | A migration is already running for this connection, or an idempotency conflict. A retry with the same key while a Google Drive or Dropbox import is still running gets idempotency_in_progress; retry a few seconds later to receive its answer. Codes: import_already_running, idempotency_key_reused, idempotency_in_progress. |
| 429 | Error | You sent more requests than your plan allows. Carries Retry-After. Codes: rate_limit_exceeded, ip_throttled. |
| 500 | Error | Something failed on our side. Nothing is wrong with your request. |
| 502 | Error | Nothing was started. Codes: import_not_started, google_unavailable. |
See the StartedImport object below for its fields.
Retrieve an import
https://xosign.ai/api/v1/imports/{id}Poll this while a migration runs. `remaining` reaching zero with `status: finished` is the end; `total_files` grows while a DocuSign sweep is still listing.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
id | path | Required | The import id. |
Responses
| Status | Returns | Description |
|---|---|---|
| 200 | Import | The import. |
| 401 | Error | The request carried no usable API key, so we could not tell who you are. Codes: missing_authorization, invalid_api_key. |
| 403 | Error | We know who you are, but this key or this plan is not allowed to do that. Codes: insufficient_scope, api_access_required. |
| 404 | Error | No import with that id. Code: import_not_found. |
| 429 | Error | You sent more requests than your plan allows. Carries Retry-After. Codes: rate_limit_exceeded, ip_throttled. |
| 500 | Error | Something failed on our side. Nothing is wrong with your request. |
See the Import object below for its fields.
List an import's files
https://xosign.ai/api/v1/imports/{id}/itemsEvery file inside one import, each with its own outcome, oldest first. For an import started from Google Drive or Dropbox that is the order you sent the files, and each carries its `index` in that request. A DocuSign migration or a browser drop lists its files here the same way, while it runs and after.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
id | path | Required | The import id. |
limit | query | Optional | How many files to return, 1–100.defaults to 20 · 1–100 |
starting_after | query | Optional | A cursor from a previous response's `next_cursor`. Returns the page after it. Cannot be combined with `ending_before`. |
ending_before | query | Optional | A cursor from a previous response. Returns the page before it. Cannot be combined with `starting_after`. |
Responses
| Status | Returns | Description |
|---|---|---|
| 200 | ImportItemList | A page of files. |
| 400 | Error | Bad pagination. Codes: invalid_limit, invalid_cursor, conflicting_cursors. |
| 401 | Error | The request carried no usable API key, so we could not tell who you are. Codes: missing_authorization, invalid_api_key. |
| 403 | Error | We know who you are, but this key or this plan is not allowed to do that. Codes: insufficient_scope, api_access_required. |
| 404 | Error | No import with that id. Code: import_not_found. |
| 429 | Error | You sent more requests than your plan allows. Carries Retry-After. Codes: rate_limit_exceeded, ip_throttled. |
| 500 | Error | Something failed on our side. Nothing is wrong with your request. |
See the ImportItemList object below for its fields.
Send a document for signature
https://xosign.ai/api/v1/documents/{id}/sendMoves a draft to `sent` and delivers a signature request to each recipient over its channel.
Takes no body — send options come from the `content` you supplied at creation. Only a draft or in-review document can be sent; sending an already-sent document returns `document_not_sendable`.
A test-mode key still transitions the document to `sent` but delivers no email or SMS.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
id | path | Required | The document id. |
Idempotency-Key | header | Optional | Optional but strongly recommended on writes. A client-chosen string of at most 255 characters. Retrying with the same key and the same body replays the original response instead of performing the write twice.max 255 characters |
Responses
| Status | Returns | Description |
|---|---|---|
| 200 | Document | The document, now `sent`. |
| 400 | Error | The document cannot be sent as it stands. Codes: document_not_sendable, no_recipients, no_signers, recipient_contact_required, approver_requires_sequential, pay_app_unsigned. |
| 401 | Error | The request carried no usable API key, so we could not tell who you are. Codes: missing_authorization, invalid_api_key. |
| 403 | Error | We know who you are, but this key or this plan is not allowed to do that. Codes: insufficient_scope, api_access_required. |
| 404 | Error | No such document. Code: document_not_found. |
| 409 | Error | Idempotency conflict. Codes: idempotency_key_reused, idempotency_in_progress. |
| 429 | Error | You sent more requests than your plan allows. Carries Retry-After. Codes: rate_limit_exceeded, ip_throttled. |
| 500 | Error | Something failed on our side. Nothing is wrong with your request. |
See the Document object below for its fields.
List a document's recipients
https://xosign.ai/api/v1/documents/{id}/recipientsPer-recipient progress: who was sent to, who opened it, who signed, who declined.
This needs its own `recipients:read` scope, separate from `documents:read`, so a key can list documents without reading signer contact details.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
id | path | Required | The document id. |
Responses
| Status | Returns | Description |
|---|---|---|
| 200 | RecipientList | The recipients, ordered by `sign_order`. A document with none returns an empty list. |
| 401 | Error | The request carried no usable API key, so we could not tell who you are. Codes: missing_authorization, invalid_api_key. |
| 403 | Error | We know who you are, but this key or this plan is not allowed to do that. Codes: insufficient_scope, api_access_required. |
| 404 | Error | No such document. Code: document_not_found. |
| 429 | Error | You sent more requests than your plan allows. Carries Retry-After. Codes: rate_limit_exceeded, ip_throttled. |
| 500 | Error | Something failed on our side. Nothing is wrong with your request. |
See the RecipientList object below for its fields.
Objects
The shapes returned by the endpoints above. Every field listed is always present — optional values arrive as null rather than being omitted, so you can read them without guarding for absence.
Document
A document in your account.
| Field | Type | Required | Description |
|---|---|---|---|
object | string | Required | one of: document |
id | string | Required | |
type | string | Required | The kind of document. Determines which workflows apply to it.one of 23 values |
status | string | Required | one of: draft, sent, partially_signed, completed, voided, declined, expired, in_review |
title | string | Required | |
description | string or null | Required | |
primary_language | string | Required | one of: en, es |
secondary_language | string or null | Required | |
recipient_count | integer | Required | How many recipients are on the document. |
sent_at | string or null | Required | |
completed_at | string or null | Required | Set when every signer has signed. |
voided_at | string or null | Required | |
voided_reason | string or null | Required | |
expires_at | string or null | Required | |
created_at | string | Required | |
updated_at | string | Required |
Recipient
A party on a document. Signing links and any authentication material are never exposed.
| Field | Type | Required | Description |
|---|---|---|---|
object | string | Required | one of: recipient |
id | string | Required | |
document_id | string | Required | |
display_name | string | Required | |
email | string or null | Required | |
phone | string or null | Required | |
party_role | string or null | Required | |
channel | string | Required | one of: email, sms, in_person |
sign_order | integer | Required | |
auth_level | string | Required | one of: l0_email_link, l1_email_sms_otp, l0_account_session |
status | string | Required | |
sent_at | string or null | Required | |
viewed_at | string or null | Required | |
signed_at | string or null | Required | |
declined_at | string or null | Required | |
declined_reason | string or null | Required |
Account
The account the calling API key belongs to.
| Field | Type | Required | Description |
|---|---|---|---|
object | string | Required | one of: account |
id | string | Required | |
display_name | string | Required | |
tier | string | Required | The account's current plan. Determines your rate limits. |
created_at | string | Required | |
mode | string | Required | Echoes which kind of key made this request.one of: live, test |
scopes | array | Required | The scopes granted to the key that made this request. |
Errors
Every endpoint can return the shared error envelope. The full catalogue of types and codes is on the errors page.
{
"error": {
"type": "not_found",
"code": "document_not_found",
"message": "No document with that id.",
"doc_url": "https://xosign.ai/docs/api/errors#not_found",
"request_id": "req_b07b069f0a83492877e3fa31"
}
}