Skip to content
Browse developers

Authentication and API keys

How to obtain a key, what its permissions cover, and how to record which person a call acts for.

Last updated

One header authenticates every request:

Authorization: Bearer cs_prod_...

That is the whole scheme. There is no token exchange, no signed request, and no second header to get right.

Obtaining a key

Keys are created in the application, at Settings > Developer > API keys, by an owner or an administrator of an account on the Business plan. Minting a key is a privilege escalation, so it is something a person does in a signed-in session; a key cannot create another key.

A key looks like cs_prod_ or cs_test_ followed by 32 characters, 40 in total. We store only a SHA-256 hash of it, and the plaintext is returned exactly once, in the response to the request that created it. Copy it into your configuration then. If it is lost, create a replacement and revoke the old one.

The management screen also shows each key's last four characters beside its prefix, so you can match a listed key against the one in a configuration file before revoking it.

The prefix reflects which CecurSign deployment minted the key, not a mode you choose. A cs_prod_ key was created on our production deployment and works against production data.

What a key may do

A key carries one or both of two permissions, READ and WRITE, chosen when it is created. Every route an integration can reach declares which one it needs, so a READ key can list envelopes, fetch documents and pull GET /v1/openapi.json, and a WRITE key can additionally create, send and void.

Grant the narrower of the two wherever the work allows it. A reporting job that never sends anything should hold a READ key, so that a leaked credential cannot post an engagement letter to your clients.

A key may also be given an expiry date at creation, and can be revoked at any time from the same screen. Revocation takes effect immediately.

Naming the person a call acts for

An API key is a machine, and some of what the API does is attributable to a person: the audit trail of an envelope, and the certificate of completion issued when it finishes. X-Acting-User closes that gap.

X-Acting-User: jane@example.com

The value is either a CecurSign user id or the email address of a user in the same account, matched without regard to case. It is verified against a live, active user before your request runs, and the audit trail and the certificate then name that person alongside the integration.

Two things worth being precise about:

  • It is attribution, not authorisation. Naming Jane records that the act carried Jane's authority. It does not borrow her department visibility or her role.
  • It is ignored on a session request. A signed-in person's own identity always wins, so a shared HTTP client can send the header unconditionally without affecting requests made by staff in the browser.

POST /v1/envelopes always requires it, because an envelope must record its author and that name appears on the email carrying the document. Beyond that, a key can be created with require the key to name who it is acting for switched on, which makes the header mandatory on every write that key performs. That is the right setting for an integration that acts on behalf of named staff: the audit record is append-only, so attribution that is missing at the time cannot be added afterwards.

When authentication fails

No credential at all is a 401:

{
  "statusCode": 401,
  "message": "Authentication required. Please provide a valid session cookie, API key, or Auth0 token.",
  "error": "Unauthorized",
  "timestamp": "2026-08-26T09:41:12.884Z",
  "path": "/v1/envelopes"
}

A key we do not accept is also a 401, with "Invalid or expired API key". Malformed, expired and revoked keys are deliberately indistinguishable from one another.

A key without the permission the route needs is a 403: "This API key does not have WRITE permission." Create a key with the right permission rather than retrying.

A route that requires a person answers a key with 403 and "This route requires a user session". Account administration is done by people, in the application.

A missing or unrecognised acting user is a 400 carrying a machine-readable code, either ACTING_USER_REQUIRED or ACTING_USER_NOT_PROVISIONED. The second echoes back the value you sent, because the first question is always which one. Provision the person in CecurSign, or omit the header and let the act be recorded against the integration itself.

The full shape of an error body, and every code you can branch on, is in Errors.

Keeping a key safe

Treat it as you would a database password. Keep it in your server's configuration or secret store, never in a browser, a mobile application, or anything a customer can read. Use a separate key per integration, so that revoking one does not silently stop another. Rotate by creating the new key, deploying it, then revoking the old one, which keeps the changeover free of downtime.