instaSpace

Signature requests

Send a template for signature, poll its status, and download the signed document.

A signature request sends a published template to its signing parties and tracks it to completion.

Send for signature

curl -X POST https://api.instaspace.ai/api/v1/esign/submissions \
  -H "Authorization: Bearer isk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "templateId": "0b9f6f2e-…",
    "submitters": [
      { "role": "First Party", "name": "Dana Client", "email": "dana@client.com" },
      { "role": "Second Party", "name": "Sami Counsel", "email": "sami@yourfirm.com" }
    ],
    "values": { "client_name": "Client Co. LLC" },
    "message": "Please sign before Friday.",
    "sendEmail": true,
    "idempotencyKey": "crm-deal-4821"
  }'
  • submitters — exactly one recipient per role the template defines (up to 10).
  • values — optional. Keyed by variable key (flow templates) or field name (coordinate templates); see reading the template shape.
  • message — optional note carried in the signature email, so it only applies when sendEmail is true.
  • sendEmail — defaults to true. When false, signers are not emailed; share the signing links yourself.
  • idempotencyKey — optional, and you should always send one. Retrying a request with a key already used returns the original signature request instead of sending a duplicate round of emails, and doesn't count against your monthly allowance again. It is also how you recover a response lost in transit: replay the same call rather than guessing whether the first one landed.

The response is the signature request:

{
  "id": "7c1d34…",
  "templateId": "0b9f6f2e-…",
  "templateName": "Mutual NDA",
  "status": "pending",
  "submitters": [
    {
      "role": "First Party",
      "name": "Dana Client",
      "email": "dana@client.com",
      "status": "awaiting",
      "completedAt": null
    }
  ],
  "hasSignedDocument": false,
  "createdAt": "2026-08-06T12:00:00.000Z",
  "completedAt": null
}

Poll status

curl https://api.instaspace.ai/api/v1/esign/submissions/{id} \
  -H "Authorization: Bearer isk_live_..."

The request's status moves through pending → opened → completed, or ends as declined, expired, or voided. Each submitter carries their own status (awaiting, opened, completed, declined).

Stop polling on any of the four terminal statuses, not just completed. A signer can decline from the signing page, the workspace can void a request, and a request can expire — a poller that waits only for completed keeps asking forever about a request that has already finished.

hasSignedDocument turns true in the same operation that sets status: completed, so there is no window where a request reads completed but the document is not there yet.

Send a reminder

curl -X POST https://api.instaspace.ai/api/v1/esign/submissions/{id}/remind \
  -H "Authorization: Bearer isk_live_..."

Signing is sequential, so this reminds whichever signer's turn it currently is — the same target the in-app "Resend" action picks. There is no way to choose a different recipient; the request takes no body.

{ "reminded": true, "recipient": { "email": "dana@client.com" } }

When the request is already completed, declined, expired or voided (or every submitter has otherwise already acted), this still answers 200 rather than an error:

{ "reminded": false, "reason": "no_pending_signer" }

so an unattended integration can call this on a schedule and treat "nothing to do" as routine rather than a failure to handle specially.

Reminding the same signer again inside 15 minutes returns 429 with a Retry-After header instead of sending a second email:

{
  "statusCode": 429,
  "message": "A reminder was already sent to this signer recently",
  "code": "reminder_cooldown",
  "retryAfterSeconds": 612
}

List signature requests

curl "https://api.instaspace.ai/api/v1/esign/submissions?status=pending&limit=25" \
  -H "Authorization: Bearer isk_live_..."

Newest first. Optional status and templateId filter, limit (1–100, default 25) and offset page:

{ "submissions": [], "total": 0, "limit": 25, "offset": 0 }

This is how an unattended integration reconciles. If a send call times out you cannot know whether it took effect — replay it with the same idempotencyKey, which returns the original request instead of sending a second one, or find it here.

Check your remaining allowance

curl https://api.instaspace.ai/api/v1/esign/usage \
  -H "Authorization: Bearer isk_live_..."
{
  "signatureRequests": {
    "limit": 50,
    "used": 12,
    "remaining": 38,
    "periodStart": "2026-08-01T00:00:00.000Z"
  }
}

limit and remaining are the string "unlimited" on Enterprise. Reading usage is never metered — check it before a batch rather than discovering the ceiling as a failed send.

Download the signed document

Once hasSignedDocument is true — before that the endpoint answers 404:

curl -L -o signed.pdf \
  https://api.instaspace.ai/api/v1/esign/submissions/{id}/document \
  -H "Authorization: Bearer isk_live_..."

You get the executed PDF with the audit certificate appended — signer identities, IP addresses, timestamps and document hashes — in one file. The download is recorded in the workspace audit log with your API key's identity.

There are no outbound webhooks yet — poll the status endpoint for updates. A completed request also notifies the workspace inside instaSpace as usual.

On this page