Send for signature
Send the contract PDF to the dealer signer and the Spyne signers through DocuSign. The contract moves to Contract-Pending-User-Signature.
The call first checks that the contract belongs to the dealer group, is in Contract-Initiated, has a PDF location and has a signer email. It then fetches the PDF and creates a DocuSign envelope with two signing steps: the dealer signer first, then Spyne signers. Copies go to the console user who sent it and to any valid signatoryDetails.clientPOCs. The contract ID and dealer group ID are stored on the envelope so the webhook can find the contract later.
After the envelope is created, the call:
- sets the contract stage to
Contract-Pending-User-Signature, - records the envelope ID, sender and send date in the contract history,
- writes a stage log entry,
- moves the dealer group stage to
Contract-Pending-User-Signature.
For test accounts, the Spyne signer and copy recipients are replaced with test lists.
Send the bearer token of a signed-in Spyne Console user in Authorization: Bearer YOUR_TOKEN. The token is checked against the user validation endpoint on every call.
Before you call it
- The contract must be in
Contract-Initiated, so submit it first with Save or submit a contract. - The contract PDF must already be uploaded to the contract's file location. If the file is missing, the call returns
400. - The stored contract must have
signatoryDetails.email. - The call is synchronous. It waits for DocuSign to create the envelope and for the stage update. DocuSign sends the emails itself. The rate limit is not documented.
Request
- Authenticate: send the
Authorization: Bearer YOUR_TOKENandContent-Type: application/jsonheaders. - Name the contract: send
enterpriseIdandcontractId. - Keep the envelope ID: keep
data.docusignEnvelopeIdfor support and tracing.
Headers
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Required | Bearer YOUR_TOKEN |
Content-Type | string | Required | application/json |
Body
| Parameter | Type | Required | Description |
|---|---|---|---|
enterpriseId | string | Required | Dealer group ID. It must match the contract. |
contractId | string | Required | Contract ID from Save or submit a contract. |
Sample request
curl -X POST "https://api.spyne.ai/credit/v6/contracting/send-for-signature" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "enterpriseId": "ENTERPRISE_ID", "contractId": "CONTRACT_ID" }'import requests
res = requests.post(
"https://api.spyne.ai/credit/v6/contracting/send-for-signature",
json={"enterpriseId": "ENTERPRISE_ID", "contractId": "CONTRACT_ID"},
headers={"Authorization": "Bearer YOUR_TOKEN"},
)
print(res.status_code, res.json())const res = await fetch("https://api.spyne.ai/credit/v6/contracting/send-for-signature", {
method: "POST",
headers: { Authorization: "Bearer YOUR_TOKEN", "Content-Type": "application/json" },
body: JSON.stringify({ enterpriseId: "ENTERPRISE_ID", contractId: "CONTRACT_ID" }),
});
console.log(res.status, await res.json());Sample response
{
"message": "Contract sent for signature successfully. Customer will receive DocuSign email.",
"error": false,
"code": "SUCCESS",
"details": null,
"data": {
"success": true,
"contractId": "CONTRACT_ID",
"enterpriseId": "ENTERPRISE_ID",
"docusignEnvelopeId": "ENVELOPE_ID",
"status": "sent",
"stage": "Contract-Pending-User-Signature",
"sentTo": "[email protected]",
"sentBy": "USER_ID",
"sentDate": "2026-01-01T00:00:00.000Z"
}
}{
"message": "Contract must be in 'Contract-Initiated' stage. Current stage: Draft",
"error": true,
"code": "INVALID_STAGE",
"details": null,
"data": null
}{ "message": "Invalid Token", "error": true, "code": "ERROR_AUTH_401", "details": null, "data": null }{ "message": "Contract not found", "error": true, "code": "CONTRACT_NOT_FOUND", "details": null, "data": null }{
"message": "DocuSign send failed: <error message>",
"error": true,
"code": "SERVER_ERROR",
"details": null,
"data": null
}Response parameters
| Parameter | Type | Description |
|---|---|---|
data.success | boolean | true when the envelope was created. |
data.contractId | string | Contract ID. |
data.enterpriseId | string | Dealer group ID. |
data.docusignEnvelopeId | string | DocuSign envelope ID. |
data.status | string | Always sent. |
data.stage | string | New contract stage, Contract-Pending-User-Signature. |
data.sentTo | string | Dealer signer email. |
data.sentBy | string | User ID of the console user who sent it. |
data.sentDate | string | Send time (ISO 8601). |
Errors
| Status | Code | When it happens |
|---|---|---|
400 | (framework) | enterpriseId or contractId is missing. The framework rejects the request before the handler runs. The body is not documented in code. |
400 | ENTERPRISE_MISMATCH | The contract belongs to another dealer group. |
400 | INVALID_STAGE | The contract is not in Contract-Initiated. A second send of the same contract returns this. |
400 | PDF_NOT_GENERATED | The contract has no PDF location. |
400 | SIGNATORY_DETAILS_MISSING | The stored payload has no signatoryDetails. |
400 | SIGNATORY_EMAIL_MISSING | The stored payload has no signer email. |
400 | PDF_NOT_FOUND_IN_S3 | The PDF file was not uploaded. |
401 | ERROR_AUTH_401 | No Bearer token, or the token failed validation. |
404 | CONTRACT_NOT_FOUND | No contract has this ID. |
408 | ERROR_REQ_TIMEOUT_408 | The token validation call could not connect. |
500 | SERVER_ERROR | DocuSign rejected the envelope, or another error occurred. |
What happens next
The dealer signer gets a DocuSign email. When they sign, and again when all parties have signed, DocuSign calls Receive DocuSign events. To remind the signer later, the console calls POST /credit/v6/contracting/resend-for-signature with the same body.
Called before: Save or submit a contract. Called after: Receive DocuSign events, called by DocuSign.
Updated about 1 hour ago
