REST API

Retries and idempotency

A network can drop an answer after the service did the work. These rules make a retry safe.

Create

Send an Idempotency-Key header with a create:

Idempotency-Key: crm-contract-1042
  • The first call creates the request and answers 201.
  • A retry with the same key answers 200 with the same request. Nothing new is created.
  • Keys are unique per organisation, not per API key. A retry after a key rotation still finds the first request. Two systems of one organisation that use the same key value get one request, so prefix the value with the name of your system.
  • The service does not compare the bodies. A retry with the same key and a different body gets the first request back, not an error.
  • After you delete a draft, the same key creates a new request.
  • An empty key, or one over 255 characters, is a 400 idempotency_key_invalid.

Send and cancel

Both are idempotent by state. A second send of a request that waits for signatures or is completed answers 200 with its current state; a send of a declined or expired request is 409 request_not_draft. A second cancel of a request that is cancelled already answers 200.

Replace a draft

PUT needs an If-Match header with the ETag of your last read. If the draft changed since then, the answer is 412 precondition_failed: read it again, then apply your change to the new version. A PUT without If-Match gets 428 precondition_required. If-Match: * replaces the draft whatever its version is.

Resend an invitation

A resend schedules an email, which goes out within seconds; the invitation_resent event of the request shows when it went out. Two calls while the first waits send one email. After the email, the signer gets no other invitation email for 3 minutes: a resend in that time gives 429 resend_too_soon, with the seconds to wait in Retry-After. The send is still at least once: if the worker fails after the email, its retry sends a second one.

If you retry a resend after a timeout and get resend_too_soon, the signer got an invitation email in the last 3 minutes: from your earlier call, or from the first invitation. Do not resend again. The events of the request show which: an invitation_resent or a signer_invited event of the signer.