Signers API reference
Individual people on a signature request.
Get a signer
/api/v1/signers/{id}- Read-only keys can call this
Returns one signer with their status, signing link, field values and — once they've signed —
their signed documents. Use it when you track signers individually (e.g. from a signer.*
webhook or by storing signer IDs against your own users).
Path parameters
idintegerRequiredSigner ID.
Request sample
curl https://app.signwith.co/api/v1/signers/9121 \
-H "Authorization: Bearer $SIGNWITH_API_KEY"const response = await fetch('https://app.signwith.co/api/v1/signers/9121', {
headers: {
Authorization: `Bearer ${process.env.SIGNWITH_API_KEY}`,
},
})
console.log(response.status, await response.json())import os
import requests
response = requests.get(
"https://app.signwith.co/api/v1/signers/9121",
headers={
"Authorization": f"Bearer {os.environ['SIGNWITH_API_KEY']}",
},
)
print(response.status_code, response.json())Errors
| 401 | The API key is missing, invalid or expired, or its account has been archived. (unauthenticated, api_key_expired) |
| 403 | The key is read-only, or its user can't access this resource. (read_only_api_key, forbidden) |
| 404 | The resource doesn't exist or belongs to another account. (not_found) |
| 429 | Rate limit exceeded (rate_limited, with Retry-After); more than 20 POST /feedback
messages in an hour (rate_limited, with Retry-After: seconds until the next clock hour); or — for
POST /signature_requests/{id}/remind — signers were reminded less than an hour ago
(remind_too_soon, with Retry-After). (rate_limited, remind_too_soon) |
| 500 | Something went wrong on SignWith's side. It's safe to retry with the same Idempotency-Key. (internal_error) |
Codes listed are the examples the spec gives; see all error codes.
Update a signer
/api/v1/signers/{id}- Needs a full-access key
Corrects a signer's details or prefills more of their fields before they sign — for example
when a customer gave the wrong email address. Only the parameters you send are changed;
prefill values are merged with existing ones.
Set resend: true to email the signing link again (only if the signer was already invited; at most
once every 10 minutes per signer, otherwise 429 remind_too_soon with Retry-After).
Signers who have signed or declined can't be changed (422 signer_finished), nor can signers
of a canceled, expired or declined request (422 not_open). The signer must keep an email
or a phone, emails must be valid, and prefill must be an object (all 422 invalid_parameter).
PUT is accepted as an alias.
Path parameters
idintegerRequiredSigner ID.
Request body
namestring or nullemailstring or nullemail addressphonestring or nullexternal_idstring or nullmetadataobjectReplaces the signer's metadata.
prefillobjectField values to set, keyed by field name. Merged with existing prefilled values.
resendbooleanEmail the signing link again after updating (only if the signer was already invited).
Defaultfalse
Request sample
curl -X PATCH https://app.signwith.co/api/v1/signers/9121 \
-H "Authorization: Bearer $SIGNWITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"prefill": {
"Landlord name": "Ada Lovelace"
},
"resend": true
}'const response = await fetch('https://app.signwith.co/api/v1/signers/9121', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.SIGNWITH_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: '[email protected]',
prefill: {
'Landlord name': 'Ada Lovelace',
},
resend: true,
}),
})
console.log(response.status, await response.json())import os
import requests
response = requests.patch(
"https://app.signwith.co/api/v1/signers/9121",
headers={
"Authorization": f"Bearer {os.environ['SIGNWITH_API_KEY']}",
},
json={
"email": "[email protected]",
"prefill": {
"Landlord name": "Ada Lovelace",
},
"resend": True,
},
)
print(response.status_code, response.json())Response 200
The updated signer. Returns a signer object.
{
"object": "signer",
"id": 9121,
"signature_request_id": 4812,
"role": "Landlord",
"name": "Ada Lovelace",
"email": "[email protected]",
"phone": null,
"external_id": null,
"metadata": {},
"status": "sent",
"signing_url": "https://app.signwith.co/s/q8LkT2mZpV4r",
"sent_at": "2026-09-27T09:44:53Z",
"viewed_at": null,
"signed_at": null,
"declined_at": null,
"created_at": "2026-09-27T09:00:01Z",
"updated_at": "2026-09-27T11:02:17Z",
"values": [
{
"field": "Landlord name",
"value": "Ada Lovelace"
}
]
}Errors
| 400 | The request body is not valid JSON. (invalid_json) |
| 401 | The API key is missing, invalid or expired, or its account has been archived. (unauthenticated, api_key_expired) |
| 403 | The key is read-only, or its user can't access this resource. (read_only_api_key, forbidden) |
| 404 | The resource doesn't exist or belongs to another account. (not_found) |
| 422 | The request is valid JSON but can't be processed. See error.code; the codes each endpoint
can return are described in the endpoint's description and in the error table above. (missing_parameter, invalid_parameter, invalid_request, missing_documents, too_many_documents, document_too_large, invalid_document, invalid_file_type, pdf_encrypted, missing_signers, invalid_signer, already_completed, not_open, nothing_to_remind, invalid_field, template_has_no_fields, template_archived, signer_finished, idempotency_key_reused, invalid_discount_code, already_purchased, billing_details_required) |
| 429 | Rate limit exceeded (rate_limited, with Retry-After); more than 20 POST /feedback
messages in an hour (rate_limited, with Retry-After: seconds until the next clock hour); or — for
POST /signature_requests/{id}/remind — signers were reminded less than an hour ago
(remind_too_soon, with Retry-After). (rate_limited, remind_too_soon) |
| 500 | Something went wrong on SignWith's side. It's safe to retry with the same Idempotency-Key. (internal_error) |
Codes listed are the examples the spec gives; see all error codes.
The signer object
A person asked to sign in a signature request.
objectstringRequiredAlwayssigneridintegerRequiredsignature_request_idintegerRequiredrolestring or nullRequiredThe template role this signer fills.
namestring or nullRequiredemailstring or nullRequiredemail addressphonestring or nullRequiredexternal_idstring or nullRequiredYour own ID for this signer.
metadataobjectRequiredArbitrary key/value data you attached to the signer.
statusstringRequiredwaiting— an earlier signer in a sequential request has to sign first;ready— it's their turn but they weren't emailed (e.g.send_email: false, or the email is still queued), so sharesigning_urlyourself;sent— invited;viewed— opened the document;signed— finished signing;declined— declined to sign.One ofwaiting,ready,sent,viewed,signed,declinedsigning_urlstring or nullRequiredThe signer's private signing link. Anyone with it can sign as this signer, so only share it with them.
nullonce they've signed, or when the request is canceled, declined or expired, or its template is archived.URLsent_atstring (date-time) or nullRequiredviewed_atstring (date-time) or nullRequiredsigned_atstring (date-time) or nullRequireddeclined_atstring (date-time) or nullRequiredcreated_atstring (date-time)Requiredupdated_atstring (date-time)Requiredvaluesarray of objectsRequiredField values filled so far (prefilled or entered by the signer).
2 child fields
fieldstringRequiredField name (or a generated name such as
Text Field 2for unnamed fields).valuestring or number or boolean or array of anys or nullRequiredThe value entered or prefilled.
documentsarray of objectsThe signer's signed documents. Present only once they've signed.
2 child fields
namestringRequiredFile name without extension.
urlstringRequiredDownload link for the signed PDF.
URL
{
"object": "signer",
"id": 9120,
"signature_request_id": 4812,
"role": "Tenant",
"name": "Grace Hopper",
"email": "[email protected]",
"phone": null,
"external_id": "cust_8841",
"metadata": {
"crm_deal_id": "D-2291"
},
"status": "signed",
"signing_url": null,
"sent_at": "2026-09-27T09:00:02Z",
"viewed_at": "2026-09-27T09:41:18Z",
"signed_at": "2026-09-27T09:44:51Z",
"declined_at": null,
"created_at": "2026-09-27T09:00:01Z",
"updated_at": "2026-09-27T09:44:51Z",
"values": [
{
"field": "Tenant name",
"value": "Grace Hopper"
},
{
"field": "Monthly rent",
"value": "2150"
},
{
"field": "Tenant signature",
"value": "https://app.signwith.co/file/eyJfcmFpbHMiOnsiZGF0YSI6NTUxfX0/signature.png"
}
],
"documents": [
{
"name": "Lease agreement",
"url": "https://app.signwith.co/file/eyJfcmFpbHMiOnsiZGF0YSI6NTUyfX0/lease-agreement.pdf"
}
]
}Base URL, pagination and idempotency work the same on every endpoint: see making requests. Every error code is on errors.
Start building
The API and MCP server come with every account. 3 free documents a month, then pay per document.