API Reference: Signing Requests
Create and manage e-signature requests anchored to a data record: configure signers and review fields, track the signing lifecycle, reissue signer links, and void in-flight requests.
Overview
A Signing Request asks one or more people to review and sign information anchored to a source data record. When you create a request, you choose the record, the fields the signers should review, the signature fields to be completed, and the signers themselves (by role). Simply360 then tracks each signer's progress — sent, viewed, signed, declined — and rolls the individual signer states up into one request status.
Requests can optionally target a file field on the record (for example, a generated agreement document), reference a signing profile or signing wizard, carry localized consent text, and expire automatically.
Authentication and Tier
All five operations are standard tier and callable with a team API key:
curl -s "https://api.simply360.app/v1/signing-requests" \
-H "Authorization: Bearer s360_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Access is governed by data permissions on the source collection: reads require read access; create, resend, and void require update access. OAuth-authenticated callers additionally need the records:read scope for reads and records:write for writes. Requests outside the caller's permitted collections return 403 PERMISSION_DENIED. See Authentication.
Endpoints
| Method | Path | Tier | Purpose |
|---|---|---|---|
POST | /v1/signing-requests | standard | Create a signing request from a source record and signer configuration. |
GET | /v1/signing-requests | standard | List signing requests visible to the caller. |
GET | /v1/signing-requests/{signingRequestSimplyId} | standard | Get a request with signers, targets, and event history. |
POST | /v1/signing-requests/{signingRequestSimplyId}/resend | standard | Reissue signer links for unsigned signers. |
POST | /v1/signing-requests/{signingRequestSimplyId}/void | standard | Void an in-flight request and disable its signer links. |
Lifecycle
A signing request moves through these statuses:
| Status | Meaning |
|---|---|
draft | Created but not yet ready to send. |
ready | Prepared and awaiting send. |
sent | Signer links have been issued. |
viewed | At least one signer has opened their link. |
partiallySigned | Some, but not all, signers have signed. |
completed | All signers have signed. |
declined | A signer declined to sign. |
expired | The request passed its expiration before completion. |
voided | The request was voided by the team. |
completed, declined, expired, and voided are terminal. Expiration is applied lazily on read: fetching a request whose expiry has passed updates its status to expired, so reads never report a stale in-flight status.
Create a Signing Request
The example below asks two signers to review three fields on a membership record and complete its signature field. signers[].roleKey identifies each signer role; each signer's name and email can be given literally (name / email) or resolved from fields on the source record (nameFieldSimplyId / emailFieldSimplyId).
TypeScript SDK
const request = await s360.signingRequests.create({
sourceDataCollectionSimplyId: 'DCL1-2345-6789',
sourceDataRecordSimplyId: 'WXYZ-5678-IJKL',
reviewFieldSimplyIds: ['FLD1-1111-AAAA', 'FLD2-2222-BBBB', 'FLD3-3333-CCCC'],
signatureFieldSimplyIds: ['FLD9-9999-SIGN'],
signers: [
{ roleKey: 'member', nameFieldSimplyId: 'FLD1-1111-AAAA', emailFieldSimplyId: 'FLD2-2222-BBBB', signingOrder: 1 },
{ roleKey: 'guardian', name: 'Alex Rivera', email: 'alex@example.com', signingOrder: 2 },
],
expirationDays: 14,
});
console.log(`Request ${request.data.signingRequestSimplyId}: ${request.data.status}`);
cURL
curl -s -X POST "https://api.simply360.app/v1/signing-requests" \
-H "Authorization: Bearer s360_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"sourceDataCollectionSimplyId": "DCL1-2345-6789",
"sourceDataRecordSimplyId": "WXYZ-5678-IJKL",
"reviewFieldSimplyIds": ["FLD1-1111-AAAA", "FLD2-2222-BBBB", "FLD3-3333-CCCC"],
"signatureFieldSimplyIds": ["FLD9-9999-SIGN"],
"signers": [
{ "roleKey": "member", "nameFieldSimplyId": "FLD1-1111-AAAA", "emailFieldSimplyId": "FLD2-2222-BBBB", "signingOrder": 1 },
{ "roleKey": "guardian", "name": "Alex Rivera", "email": "alex@example.com", "signingOrder": 2 }
],
"expirationDays": 14
}'
The response is 201 with the created request summary, including the request status and one entry per signer (role, name, email, order, and per-signer status).
Request Body
| Field | Type | Description |
|---|---|---|
sourceDataCollectionSimplyId | string, required | Public simplyId of the source collection. |
sourceDataRecordSimplyId | string, required | Public simplyId of the source record. |
reviewFieldSimplyIds | string[], required | Fields the signers review. At least one; the caller needs read access to each. |
signers | object[], required | At least one signer. Each requires roleKey; optional name, email, nameFieldSimplyId, emailFieldSimplyId, signingOrder (≥ 1), internalTeamUserLinkSimplyId, linkedConstituentDataCollectionSimplyId, linkedConstituentDataRecordSimplyId. |
signatureFieldSimplyIds | string[] | null | Signature fields to complete; the caller needs update access to each. |
fileTarget | object | null | Targets a file on the record: fileFieldSimplyId (required when fileTarget is present), optional fileSimplyId and sourceFileVersionNumber. |
signingProfileSimplyId | string | null | Signing profile to apply. |
signingWizardSimplyId | string | null | Signing wizard to apply. |
consentText | object | null | Localized consent text (language code → string). |
consentVersion | string | null | Version label for the consent text. |
expirationDays | integer | null | Days until expiry, as an alternative to expiresAt. |
expiresAt | string (date-time) | null | Absolute expiry timestamp. |
signingBaseUrl | string | null | Base URL used when composing signer links, for teams hosting signing on their own domain. |
sendImmediately | boolean | Whether to issue signer links right away. Defaults to true. |
List Signing Requests
const inFlight = await s360.signingRequests.list({
sourceDataCollectionSimplyId: 'DCL1-2345-6789',
status: 'sent',
limit: 50,
});
curl -s "https://api.simply360.app/v1/signing-requests?status=sent&sourceDataCollectionSimplyId=DCL1-2345-6789&limit=50" \
-H "Authorization: Bearer s360_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
| Parameter | Type | Description |
|---|---|---|
status | string | Filter by request status (see Lifecycle). |
sourceDataCollectionSimplyId | string | Filter to requests created from one collection. |
sourceDataRecordSimplyId | string | Filter to requests created from one record. |
signingProfileSimplyId | string | Filter by signing profile. |
limit | integer | Page size, 1–100. Default 25. |
offset | integer | Skip count for pagination. Default 0. |
Get a Signing Request
The detail read returns the request with its signer list, its targets (the signature and file fields being completed), and its event history — a per-signer audit trail of sends, views, signatures, and declines.
const detail = await s360.signingRequests.get('SREQ-1234-ABCD');
console.log(detail.data.status);
for (const signer of detail.data.signers) {
console.log(`${signer.roleKey}: ${signer.status} (signed ${signer.signedAt ?? 'not yet'})`);
}
curl -s "https://api.simply360.app/v1/signing-requests/SREQ-1234-ABCD" \
-H "Authorization: Bearer s360_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Resend Signer Links
Resend marks selected unsigned signers as sent again and returns fresh signer link metadata for delivery by the caller. Omit signingRequestSignerSimplyIds to target all unsigned signers, or pass specific signer simplyIds.
const resent = await s360.signingRequests.resend('SREQ-1234-ABCD', {
signingRequestSignerSimplyIds: ['SGNR-0001-AAAA'],
});
console.log(resent.data.resentSignerSimplyIds);
curl -s -X POST "https://api.simply360.app/v1/signing-requests/SREQ-1234-ABCD/resend" \
-H "Authorization: Bearer s360_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "signingRequestSignerSimplyIds": ["SGNR-0001-AAAA"] }'
The body is optional; signingBaseUrl may also be supplied to control the domain of the reissued links. Signers who already signed cannot be resent.
Void a Signing Request
Voiding cancels an in-flight request and disables its signer links, so outstanding signer URLs stop working. An optional reason is recorded with the void.
await s360.signingRequests.void('SREQ-1234-ABCD', { reason: 'Superseded by revised agreement' });
curl -s -X POST "https://api.simply360.app/v1/signing-requests/SREQ-1234-ABCD/void" \
-H "Authorization: Bearer s360_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "reason": "Superseded by revised agreement" }'
{
"data": {
"signingRequestSimplyId": "SREQ-1234-ABCD",
"status": "voided"
}
}
Errors
| HTTP | Code | Meaning |
|---|---|---|
| 400 | VALIDATION_ERROR | Missing or malformed input — for example, no signers, no review fields, or a fileTarget without fileFieldSimplyId. Also returned for terminal-state conflicts such as resending an already-completed request. |
| 403 | PERMISSION_DENIED | The caller lacks the required data permission on the source collection or one of the referenced fields. |
| 404 | NOT_FOUND | The signing request, source collection, or source record does not exist or is not visible to the caller. |
| 500 | INTERNAL_ERROR | Unexpected failure. |
See Error Handling for the error envelope format.
Usage Notes
- Signing requests were added to the public API on 2026-06-29; see the API Changelog.
- The same operations are available as hosted MCP tools (
create_signing_request,get_signing_request,list_signing_requests,resend_signing_request,void_signing_request) backed by the same permission checks — see MCP Server. - All identifiers on this surface are public simplyIds; numeric database IDs are rejected.
- List reads are automatically scoped to collections the caller can read; you never see requests from collections outside your data permissions.