Compose and send a contract in one step
Publishes the template, builds a signing workflow from the given signers
(optionally gated so a stage only proceeds after a transaction succeeds),
and sends the contract request — atomically; by default the workflow is
ad-hoc (not saved as a reusable Contract Flow) unless save_as_flow is
true. Returns 404 if the template, project, or transaction is not found.
Returns 400 if signers don't cover every template signer role exactly
once (or duplicate a role), or if payment_gate.after_role doesn't match
a signer. Returns 422 if any signer uses your client signing profile and
none is configured.
| Time | Status | User Agent | |
|---|---|---|---|
Retrieving recent requests… | |||
Compose and send a contract in a single call. The endpoint builds a contract flow from the template and the signers you supply (optionally inserting a payment gate that holds signing until a linked transaction succeeds) and creates the contract request that delivers the contract to the signers. There is no separate publish step: the template and the new contract flow are usable as soon as they exist. All of these steps run in one transaction: if any step fails the whole operation is rolled back, so no orphaned contract flow is left behind. On success it returns the created contract request, including its participants and their signing status.
Authentication & access
- Requires a client API token:
Authorization: Bearer <token>. - API credentials need the
contracts.requests.writepermission. Dashboard users need the OWNER or OPERATIONS role, or a custom role that includes this permission. - Contract signing must be enabled for the client. If it is disabled the request returns
403.
Request body
| Field | Type | Notes |
|---|---|---|
template_version_id | string, required | ID of the contract template version to send. |
signers | array, required (min 1) | Ordered list of signers. Each entry's role must match a template signer role, and together the signers must cover every template signer role exactly once. |
payment_gate | object, optional | When set, signing is held until a linked transaction succeeds. payment_gate.after_role (1-255 characters) must match one of the signers' roles. |
save_as_flow | boolean, default false | Persist the ad-hoc setup as a reusable contract flow instead of an internal ad-hoc one. |
flow_name | string, optional (max 255) | Name for the saved contract flow when save_as_flow is true. Defaults to an auto-generated Ad-hoc: <template name> label. |
project_id | string, optional | ID of the project this contract belongs to. Must belong to your client and must not be archived. |
transaction_id | string, optional | ID of a payment transaction to link to this contract. One payment funds one live contract: a transaction already linked to another contract request is refused unless that request ended canceled, declined or expired. |
variables | object, optional | Template variable values applied to this contract. |
email_notifications | object, optional | Per-event email notification and attachment toggles, extra completion recipients and view-only (CC) recipients for the contract flow created by this send. See below. |
Each signer (signers[])
signers[])| Field | Type | Notes |
|---|---|---|
role | string, required (1-255) | Signer role name as defined in the template. |
source | enum, required | Who fills this signer. One of: client_signing_profile (auto-sign), user, business_customer, or external. |
user_id | string | Required when source is user. |
business_customer_id | string | Required when source is business_customer. |
external | object | Required when source is external; provides the external signer's name (1-255 characters) and email. |
field_values | object, optional | Pre-filled template field values for this signer. |
expire_after_hours | integer, optional (1-2160) | Hours this signer has to sign once it is their turn. Omit or null for no expiration. Not allowed on client_signing_profile signers. |
parallel_with_previous | boolean, default false | Sign at the same time as the previous signer instead of waiting for them. Signers that sign together must all carry the same expire_after_hours. Ignored on the first signer. |
Signers sign in the order given, except where parallel_with_previous groups them. A client_signing_profile signer is signed automatically (auto-sign); every other signer gets a signing link. When payment_gate is set, the gate is placed right after the signer named in after_role (after that signer's whole group when signing in parallel), and the signers after it wait until a linked transaction has succeeded.
Email notifications (email_notifications)
email_notifications)| Field | Type | Notes |
|---|---|---|
invitation | boolean, default true | Send the signing invitation email when a link signer's turn starts. |
completed | boolean, default true | Notify participants when the contract is fully signed. |
declined | boolean, default true | Notify participants when a signer declines. |
expired | boolean, default true | Notify participants when the contract expires before completion. |
completed_attach_document | boolean, default true | Attach the signed PDF to the completion email. |
completed_attach_audit_log | boolean, default false | Attach the signing audit log to the completion email. |
completed_extra_emails | array of emails, optional (max 10) | Extra addresses that also receive the completion notification. |
cc_emails | array of emails, optional (max 10) | View-only (CC) recipients. Each gets a read-only link to the contract when it is sent, plus the completed, declined and expired notifications per the toggles above. They cannot sign. Addresses that match a signer are skipped. |
cc_view_link_days | integer, default 30 (1-365) | Days the CC view links keep working after the contract is completed, declined or expired. While signing is in progress they always work; canceling the contract closes them at once. |
Signer preconditions
- If any signer uses the
client_signing_profilesource (auto-sign), a signing profile must already be configured for the client. If none exists the request returns422. The profile must also be able to sign for that role (a signature image when the role has a signature field, and values for the role's required fields); otherwise the request returns400listing what is missing. - Each
usersigner must reference a user under your client, and eachbusiness_customersigner must reference a business customer under your client. Verification status is not checked here: a subject in anykyc_status/kyb_status(or external attestation status) can be a signer. - Every signer needs a valid email address. A
business_customersigner without a contact email, or a stored signer email that is not a valid address, returns400.
Template preconditions
The referenced template version must be provisioned for signing, must not be archived, and must have at least one signer role and at least one fillable field; otherwise the request returns 400. Signers are matched against the template's roles as last stored, so after adding roles in the document builder call Refresh Contract Template before sending.
Response
Returns 200 with the created contract request. The payload includes the request id, the workflow_id and template_version_id that were used, overall status, the current_stage_index and current_participant_key, any linked transaction_id and project_id, applied variables and metadata, completion_extra_emails, cc_recipients (each with email, view_url and view_expires_at), and the full list of participants with each one's signing status. A signer's signer_url (and active_signing_url) is returned only while it is that signer's turn to sign. completed_document_url and audit_log_url are always null in this response.
If the signing service returns an error after the contract has been created (for example while auto-signing the first stage), the request is kept and returned in its current state instead of being rolled back. It moves on when the next signing event arrives; if nothing is pending (for example a failed auto-sign), call Reconcile Contract Request to retry.
Error responses
| Status | When |
|---|---|
400 | Duplicate signer role assignment; signers do not cover every template signer role exactly once; payment_gate.after_role does not match any signer; template is archived or not provisioned for signing; template has no signer roles or no fillable fields; expire_after_hours set on an auto-sign signer; signers signing in parallel have different expire_after_hours; the signing profile cannot auto-sign a role; a signer has no valid email address; project is archived; the transaction is already linked to another live or completed contract request |
403 | Contract signing is disabled for the client |
404 | Template version, signer user, signer business customer, project, or linked transaction not found under this client |
422 | Request body failed validation (e.g. signer source/subject mismatch, missing required external signer details, expire_after_hours out of range); auto-sign requested without a configured signing profile |
502 | The signing service returned an error or an invalid response |
503 | The signing service is temporarily unavailable or not configured |
Standard 401 (authentication), 403 (insufficient permission or role), and 429 (rate limit) responses apply to every endpoint and are documented in the Error reference.