← All documentationContents ↓

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

MethodPathTierPurpose
POST/v1/signing-requestsstandardCreate a signing request from a source record and signer configuration.
GET/v1/signing-requestsstandardList signing requests visible to the caller.
GET/v1/signing-requests/{signingRequestSimplyId}standardGet a request with signers, targets, and event history.
POST/v1/signing-requests/{signingRequestSimplyId}/resendstandardReissue signer links for unsigned signers.
POST/v1/signing-requests/{signingRequestSimplyId}/voidstandardVoid an in-flight request and disable its signer links.

Lifecycle

A signing request moves through these statuses:

StatusMeaning
draftCreated but not yet ready to send.
readyPrepared and awaiting send.
sentSigner links have been issued.
viewedAt least one signer has opened their link.
partiallySignedSome, but not all, signers have signed.
completedAll signers have signed.
declinedA signer declined to sign.
expiredThe request passed its expiration before completion.
voidedThe 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

FieldTypeDescription
sourceDataCollectionSimplyIdstring, requiredPublic simplyId of the source collection.
sourceDataRecordSimplyIdstring, requiredPublic simplyId of the source record.
reviewFieldSimplyIdsstring[], requiredFields the signers review. At least one; the caller needs read access to each.
signersobject[], requiredAt least one signer. Each requires roleKey; optional name, email, nameFieldSimplyId, emailFieldSimplyId, signingOrder (≥ 1), internalTeamUserLinkSimplyId, linkedConstituentDataCollectionSimplyId, linkedConstituentDataRecordSimplyId.
signatureFieldSimplyIdsstring[] | nullSignature fields to complete; the caller needs update access to each.
fileTargetobject | nullTargets a file on the record: fileFieldSimplyId (required when fileTarget is present), optional fileSimplyId and sourceFileVersionNumber.
signingProfileSimplyIdstring | nullSigning profile to apply.
signingWizardSimplyIdstring | nullSigning wizard to apply.
consentTextobject | nullLocalized consent text (language code → string).
consentVersionstring | nullVersion label for the consent text.
expirationDaysinteger | nullDays until expiry, as an alternative to expiresAt.
expiresAtstring (date-time) | nullAbsolute expiry timestamp.
signingBaseUrlstring | nullBase URL used when composing signer links, for teams hosting signing on their own domain.
sendImmediatelybooleanWhether 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"
ParameterTypeDescription
statusstringFilter by request status (see Lifecycle).
sourceDataCollectionSimplyIdstringFilter to requests created from one collection.
sourceDataRecordSimplyIdstringFilter to requests created from one record.
signingProfileSimplyIdstringFilter by signing profile.
limitintegerPage size, 1–100. Default 25.
offsetintegerSkip 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 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

HTTPCodeMeaning
400VALIDATION_ERRORMissing 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.
403PERMISSION_DENIEDThe caller lacks the required data permission on the source collection or one of the referenced fields.
404NOT_FOUNDThe signing request, source collection, or source record does not exist or is not visible to the caller.
500INTERNAL_ERRORUnexpected 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.