SignWith API authentication: API keys
Every request to the SignWith API carries an API key in the Authorization header. Keys belong to the user who created them, and they can be live or test, full access or read-only.
Send the key as a Bearer token
Put the key in the Authorization header of every request:
Authorization: Bearer sw_live_3xAmPl3K3y...
A request without a valid key gets 401 unauthenticated. There is no other way to authenticate with the REST API: OAuth tokens are only for the MCP server, not for /api/v1.
Create and revoke keys
Get your API keyCreate keys in SignWith under Settings → Developers, and revoke them there too. Each key belongs to the user who created it and acts with that user's permissions, so a key can only see the templates and signature requests its user can see.
Keep keys on your server. Anyone with a key can act as its user, so never put one in a web page, a mobile app or a public repository. To replace a key, create the new one, deploy it, then revoke the old one.
Live and test keys
The prefix tells you which environment a key acts on:
| Prefix | Environment | What happens |
|---|---|---|
sw_live_ | Live | Sends real signing emails and uses credits. |
sw_test_ | Test | Acts on your test account. Use it while you build; its data is kept apart from live data. |
Both use the same base URL, https://app.signwith.co/api/v1. To check which environment, user and account a key belongs to, call GET /me:
curl https://app.signwith.co/api/v1/me \
-H "Authorization: Bearer $SIGNWITH_API_KEY"const response = await fetch('https://app.signwith.co/api/v1/me', {
headers: {
Authorization: `Bearer ${process.env.SIGNWITH_API_KEY}`,
},
})
console.log(response.status, await response.json())import os
import requests
response = requests.get(
"https://app.signwith.co/api/v1/me",
headers={
"Authorization": f"Bearer {os.environ['SIGNWITH_API_KEY']}",
},
)
print(response.status_code, response.json())The response's environment is live or test, and api_key.permission is full or read.
Full-access and read-only keys
A full-access key can call every endpoint. A read-only key can call:
- any
GETendpoint, POST /documents/verify, which checks a PDF without changing anything,POST /feedback, which sends feedback to the SignWith team.
Every other write with a read-only key returns 403 read_only_api_key. Use read-only keys for dashboards, reporting and anything else that only needs to look. Each endpoint in the API reference says which kind of key it needs.
Key expiry
A key can have an expiry date, shown as api_key.expires_at in GET /me (null if it never expires). After that date every request returns 401 api_key_expired, and you need a new key.
Authentication errors
| HTTP | Code | What to do |
|---|---|---|
| 401 | unauthenticated | The key is missing, malformed or revoked, or its account was archived. Check the header format and the key. |
| 401 | api_key_expired | The key passed its expiry date. Create a new one. |
| 403 | read_only_api_key | A read-only key tried to change something. Use a full-access key. |
| 403 | forbidden | The key's user can't access this resource. |
All error codes are on the errors page.
Start building
The API and MCP server come with every account. 3 free documents a month, then pay per document.