Sign
Send a PDF for e-signature and get a sealed document with an audit trail.
For new product integrations, use the RakeSign API.
It adds team documents, scoped integration keys, template management, and revision-bound delegation.
POST /v1/sign remains available with its existing contract.
See migration guidance before changing an existing integration.
POST /v1/sign creates a signature envelope for one PDF. Each signer verifies their email with a one-time code. Each signer signs by typing their name. When the last signer completes, CloudRaker adds a signature certificate and a tamper-evident cryptographic seal. The sealed document comes back as a new file.
How it works
- You send a file and one or more signers (
name+email). You can add cc parties (name+email) who only receive the result. - CloudRaker creates the envelope and emails each signer their own signing link. The call returns
202withstatus: "needs_input". Signing is never synchronous. - The run stays at
needs_inputwhile signatures come in. PollGET /v1/runs/:id, watch the envelope, or subscribe a webhook. - When all signers complete, CloudRaker seals the document. The run reaches
processedwithoutput.fileandoutput.auditUrl. Each cc party receives the sealed PDF by email.
Sign runs are exempt from the run TTL. An envelope must outlive the 7-day maximum, so CloudRaker never purges an open envelope. The expiresAt field is still present on the run body. For a sign run, the API does not enforce it. The envelope has its own expiry, visible on GET /v1/runs/:id/envelope.
Quickstart
The TypeScript and Python samples use plain HTTP, so they run with no installed packages. This endpoint is also a top-level method on both SDKs as of 0.3.0: client.sign(…). That page has a full worked example.
Example response
envelopeUrl appears on every sign response, the 202 and each GET /v1/runs/:id. It points at the envelope, the sender’s view of who has signed. A signing link is a bearer capability that belongs to one signer. CloudRaker emails the link to that signer and never returns it to you.
When every signer completes, GET /v1/runs/:id reaches processed. Then output carries:
Configuration
Placing the signatures
page (the default) appends an Electronic Signatures page and puts every stamp on it. Nothing needs preparing in the document.
tags puts each signer’s stamp on a literal [Signature N] in the document text. signers[0] signs [Signature 1], signers[1] signs [Signature 2], and so on, matched by position, never by name or email. Every signer needs a marker. Only signers count. cc parties never map to a marker. If one is missing the run fails before anyone is invited, with error.code: "signature_tags_missing".
A marker sets where a stamp goes, not how big it is. The stamp is anchored on the marker and takes the free space around it: above and to the right by default, below or to the left when that side is blocked. A full-size stamp is about 210 x 86pt, so leave roughly that much clear of other text and form fields on one side of the marker. A marker with less room gets a smaller stamp, down to a floor of about 120 x 49pt.
All the signature stamps in a document are drawn at one size, the smallest that any of them fits. Two signatures on a page match, instead of one printing larger than the other.
A marker with less room than the floor still prints, at the floor, over whatever is beneath it. You can see that before you send, so it is your call.
Two things a send does refuse, because neither leaves you anything to decide. A signature marker too close to a page edge to hold a stamp at all, where there is nowhere to draw it. And two signature markers so close together that both stamps cannot fit however they are arranged, where neither signature would be readable. Both refusals name the markers and the page.
Signature stamps step around each other: a stamp shrinks or takes a different corner rather than print across one already placed. What a stamp cannot step around is an initials or date, which are measured against the text beside them and print wider than their own marker. A date is the easiest to miss, because it is written in full. Give each marker its own line, or check overlaps_field before you send.
[Initials N] and [Date N] are written as text at the marker, not as a stamp. They shrink to clear whatever is to their right, so leave space on that side. Below a readable floor they stop shrinking and print over their neighbour instead. A date needs more room than its marker suggests, because it is written as YYYY-MM-DD.
GET /v1/signing/inspect/document/{id} shows where every stamp will print, before you send. POST /v1/signing/inspect does the same for a PDF you have not stored yet, posted as multipart with a file field. Each marker comes back with the box its output will take and a status:
overlapsSignature is true on a signature that prints over another signature. Placement has already tried every size and corner for both, so no layout keeps them apart and the send is refused. An initials or date that prints into a signature is only overlaps_field. That is a warning: a date is written in full, and placement does not step around it.
Markers are not case-sensitive, and each one has a short form: [S1], [I1] and [D1] mean the same as [Signature 1], [Initials 1] and [Date 1]. The space after the full word is optional, so [Signature1] works too. The short forms take no space, so [S 1] is text, not a marker. A marker numbered below 1 is refused when you send.
Both placements append the audit pages, so tags gives you in-place signatures and the trail.
Language
language sets the language of everything the recipients see. It applies to every signer and every cc party of the envelope. Only the sender chooses it. en (the default) is English. fr is French.
The setting changes:
- the invitation and verification-code emails,
- the signing page,
- the signature certificate pages in the sealed PDF.
The API surface stays in English. Run bodies, envelope fields, the audit trail JSON, and [Signature N] markers do not change.
Track the envelope
Four sub-routes hang off the run id.
GET /v1/runs/:id/envelope
The sender’s view: envelope status, the signer roster with per-signer state, and the event trail. When the request carries cc, the envelope also lists each cc party, labeled CC. A cc party has no signer state: no link, no verification, no resend.
The envelope never contains signing links. A signing link is a bearer capability that only its signer holds. To get a signer moving again, re-send their invitation.
POST /v1/runs/:id/signers/:signerId/resend
Emails a pending signer a new signing link. Their previous link stops working immediately. Returns 409 if that signer already signed or if the envelope is no longer pending.
POST /v1/runs/:id/void
Cancels a pending envelope. Every signing link dies at once, and the run terminates as failed. The body accepts an optional { "reason": "…" }. Returns 409 when the envelope is finalizing or completed.
GET /v1/runs/:id/audit
Returns the audit trail as JSON: creation, invitations, email verifications, signatures, and the seal. It is available before the envelope completes. The sealed PDF carries the same document as an attachment.
Sync vs async
Sign is always asynchronous. POST /v1/sign answers 202 for any ?wait= value, because a sign run cannot reach a terminal status inside the window. With the default wait, the call holds until the envelope exists and reports status: "needs_input". With ?wait=0, the call returns immediately with status: "queued". Poll GET /v1/runs/:id?wait=…, watch the envelope, or subscribe run.completed on a webhook endpoint.
Save as a config
Sign is the one capability with no config library and no action reference in its request body. POST /v1/sign and {"sign": …} pipeline steps always run the built-in signing action. They take their whole configuration inline. Send message and placement on every call.
There is no /v1/sign/configs. POST /v1/actions accepts "capability": "sign", so you can create and list a saved sign action. But today no /v1 request path consumes one. The API rejects a saved sign action as another verb’s action with 400 invalid_request. The same applies to a bare {"action": …} pipeline step. Only the sign path keeps the run exempt from the TTL purge.