Authentication
A bearer key, scoped to what it may do.
Authorization: Bearer mk_live_1a2b3c4d…
Keys are shown once, when issued, and stored only as their SHA-256 — the same way a signing token is, and for the same reason. A key that is lost is replaced, not recovered.
Scopes
A key's scopes are its capabilities. There is no "full access" scope, because the useful question about an integration is not whether it is trusted but what it needs.
| Scope | What it carries |
|---|---|
| signing:read | Read templates, documents, certificates and packets. |
| signing:write | Prepare, send and void documents. |
| signing:templates | Create, publish and revise templates. |
| signing:workflows | Start a workflow for a participant. |
| signing:subjects | Import reservations, set guest lists, build and start packets. |
| signing:webhooks | Manage endpoints. |
A booking integration wants
signing:subjects, not signing:write. The two
are different trust levels: one is "act on my behalf", the other is "decide who
my guests are".
Only from where it should come from
A key can be pinned to addresses or ranges when it is made — one per line
under Only from these addresses, up to twenty, IPv4 or IPv6. Presented
from anywhere else it is refused exactly as a wrong key is (401,
the same sentence), so a copy that leaks from a log or a laptop does nothing.
A key with no list works from anywhere. The list travels with the key: to change
it, make a new key and revoke the old one, the way scopes change.
The address checked is the one the request arrives from, as our edge sees it. An integration behind an egress with a fixed address pins to that; one whose address moves should not pin at all rather than pin to a range it does not control.
Connecting through OAuth
A product that serves many businesses does not want to ask each one to paste
a key. It sends the business to SignSealer once, the business agrees, and the
product is handed tokens — an access token that is a scoped key for an hour,
and a refresh token that gets the next one. This is OAuth 2.0 with the
authorization code flow and PKCE, and nothing else: no implicit flow, no
password grant, and S256 is the only challenge method accepted.
Register your product with partners@signsealer.com
(a name, a homepage, the exact redirect address or addresses, and the scopes
it will ask for); you get a client_id and, shown once, a
client_secret.
1. Send the browser to authorise.
GET https://api.signsealer.com/oauth/authorize
?response_type=code
&client_id=ss_client_…
&redirect_uri=https://your.product/callback
&scope=signing:read%20signing:write
&state=… # yours, returned untouched
&code_challenge=… # base64url(sha256(code_verifier))
&code_challenge_method=S256
The person signs in if they are not already, sees your product's registered
name, homepage and the scopes asked, and agrees or declines. The
redirect_uri must match one you registered exactly — not a prefix,
not a pattern — and a request whose client or redirect does not check out is
answered as a page, never as a redirect. Everything else that is wrong comes
back to your redirect as error= with state, the way
RFC 6749 says. Agreement comes back as
?code=…&state=…; the code lives sixty seconds and is good once.
2. Exchange the code, server to server.
POST https://api.signsealer.com/oauth/token
Authorization: Basic base64(client_id:client_secret)
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=…
&redirect_uri=https://your.product/callback
&code_verifier=…
{
"access_token": "mk_live_…",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "signing:read signing:write",
"refresh_token": "…"
}
The access token is a key like any other on this page — send it as
Authorization: Bearer, and every scope rule above applies. The
client may also be sent as client_id and client_secret
in the body. Refresh with grant_type=refresh_token&refresh_token=…;
each refresh token is good once and the answer carries the next. A refresh
token presented twice is treated as stolen: the connection is revoked, and the
reason is on the business's audit trail.
The scopes a business can grant are the ones you registered, narrowed to what
the person agreeing can do themselves. The business sees the connection under
Developers → Connected apps and can end it there at any time, with a
reason on its audit trail; every token under it stops working that minute, and
your next call answers 401.
Test and live
Keys are prefixed mk_test_ or mk_live_. The prefix
is the first thing in the key and the first thing in our logs, so a test key
used against live data is visible immediately rather than after the invoice.
Revoking
Revoking a key needs a reason, and the reason goes on the audit trail. A key revoked is a membership deactivated in the same statement — there is no window in which the key is "revoked but still working".
Ready to build? An API key takes a minute in the portal, and the free plan covers the first 25 agreements a month.
Get an API key