Authentication
How API keys, login tokens and fill links work, and how to keep them safe.
This page explains the three credentials the Tepez API accepts: API keys for your servers, login tokens for interactive tools, and signed links for the people who fill in your forms. It also shows how to list and revoke keys and how to keep them safe.
API keys
An API key is the credential for server-to-server integrations. Send it on every request in this header:
x-api-key: <apiKey>
The API reads the key only from this header. A key sent any other way, for example as a query
string parameter, is ignored, and the request fails with 401 Missing authentication.
What a key can do
A key acts as the user who created it, in that user's account, with all of that user's permissions. Every user of an account has the same permissions, so a key can read and change all the forms, entries, users and options sets of the account. Keys have no scopes, so there is no read-only key and no key limited to one form. Keys don't expire. A key works until you revoke it.
The token format
A key's token is 56 characters: the key's 24-character _id followed by a 32-character secret.
Tepez stores only a hash of the secret, so the token appears once, in the response that creates
it. A lost token can't be recovered. Create a new key and revoke the old one.
Create a key
Create a key with POST /api-keys, authenticated with a
login token (see Login tokens). The key always belongs to the user who sends
the request. To create a key for a dedicated integration user, sign in as that user.
A user who signs in with Google has no password for POST /auth/login. That user can create a key
in the API reference: sign in, open
POST /api-keys, and click Try it out, then
Execute. If neither way works for you,
ask support to create a key.
curl -X POST https://api.tepez.co.il/v1.0/api-keys \
-H "Authorization: $TEPEZ_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'{
"_id": "<apiKeyId>",
"account": "<accountId>",
"user": "<userId>",
"email": "you@example.com",
"createTime": "2026-09-30T14:18:09.057Z",
"modifyTime": "2026-09-30T14:18:09.057Z",
"token": "<apiKey>"
}Check that user and account are the ones you meant before you store the key. The new key works
at once: GET /me with it returns its user.
curl https://api.tepez.co.il/v1.0/me \
-H "x-api-key: $TEPEZ_API_KEY"{
"id": "<userId>",
"account": "<accountId>",
"email": "you@example.com",
"name": "Integration user",
"settings": { "locale": "he", "theme": "bs3" },
"hasPassword": true,
"lastLogin": "2026-09-30T14:18:08.423Z",
"createTime": "2026-08-16T12:47:45.105Z",
"modifyTime": "2026-08-16T12:47:45.105Z",
"changedAt": "2026-09-30T14:18:08.424Z"
}List your keys
GET /api-keys lists the keys of the user you
authenticate as. The response never includes a token. Use each key's _id and createTime to
tell the keys apart.
curl https://api.tepez.co.il/v1.0/api-keys \
-H "x-api-key: $TEPEZ_API_KEY"{
"data": [
{
"_id": "<apiKeyId>",
"account": "<accountId>",
"user": "<userId>",
"email": "you@example.com",
"createTime": "2026-08-16T12:49:41.769Z",
"modifyTime": "2026-08-16T12:49:41.769Z"
},
{
"_id": "<apiKeyId2>",
"account": "<accountId>",
"user": "<userId>",
"email": "you@example.com",
"createTime": "2026-09-30T14:18:09.057Z",
"modifyTime": "2026-09-30T14:18:09.057Z"
}
]
}Revoke a key
DELETE /api-keys/{apiKey} revokes a key. The
path takes the key's _id, not its token. A successful revoke answers 200 with an empty body.
You can revoke only the keys of the user you authenticate as. To revoke another user's key, sign
in as that user, or ask support.
curl -X DELETE https://api.tepez.co.il/v1.0/api-keys/<apiKeyId> \
-H "x-api-key: $TEPEZ_API_KEY"Passing the token instead of the _id fails:
{
"statusCode": 400,
"error": "Bad Request",
"message": "\"apiKey\" with value \"<apiKey>\" fails to match the required pattern: /^[0-9a-fA-F]{24}$/",
"validation": { "source": "params", "keys": ["apiKey"] }
}From the moment it's revoked, the key is refused. GET /me with it returns:
{
"statusCode": 401,
"error": "Unauthorized",
"message": "Invalid API key",
"attributes": { "error": "Invalid API key" }
}Keeping your key safe
A key can read and change everything in your account, so treat it like a password:
- Keep it in a secret manager, and load it into your server's environment at runtime.
- Never put it in browser code, a mobile app, or a code repository. Anyone who can read the code can use the key.
- Create one key per integration. Revoking one key then stops only that integration.
- Revoke keys you no longer use.
GET /api-keysshows which keys still exist. - If a key leaks, create a new key, switch your integration to it, and revoke the old one.
Keys work only from servers. The API's CORS policy doesn't allow the x-api-key header, so a
browser refuses to send a request that carries it.
Login tokens (JWT)
A login token authenticates as a user who signs in with an email and password. Use it for interactive tools and for creating API keys. For integrations, use an API key.
Get a token from POST /auth/login. The examples read the
password from the TEPEZ_PASSWORD environment variable, and the JavaScript and Python ones read the
email from TEPEZ_EMAIL, so the password stays out of your shell history and your code:
curl -X POST https://api.tepez.co.il/v1.0/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "you@example.com", "password": "'"$TEPEZ_PASSWORD"'"}'{
"token": "<token>",
"user": {
"id": "<userId>",
"account": "<accountId>",
"email": "you@example.com",
"name": "Integration user",
"settings": { "locale": "he", "theme": "bs3" },
"hasPassword": true,
"lastLogin": "2026-09-30T14:18:08.423Z",
"createTime": "2026-08-16T12:47:45.105Z",
"modifyTime": "2026-08-16T12:47:45.105Z",
"changedAt": "2026-09-30T14:18:08.424Z"
}
}Send the token in the Authorization header:
Authorization: <token>A token is valid for 3 days. After that the API answers 401, and you sign in again. A wrong email
or password returns 401 Wrong username/ password. A user who signs in with Google only can't get
a token this way.
Links for form fillers (bewit)
The people who fill in your forms don't need a Tepez user or any credential. When your system
creates a draft entry for someone, the entry carries a signed link that opens it directly, with
no sign-in. GET /entry/{entryId} returns it on a
saved entry:
{
"id": "<entryId>",
"status": "saved",
"bewit": "<bewit>",
"resumeUrl": "https://app.tepez.co.il/e/<entryId>/",
"resumeUrlBewit": "https://app.tepez.co.il/e/<entryId>/?b=<bewit>"
}resumeUrlBewitis the link to send to the person. It opens the entry so they can continue filling it and submit it.bewitis the signature on its own, andresumeUrlis the same page without it, which asks the visitor to sign in to your account.- The link works until the entry is submitted, and for at most 2 years.
- Anyone who has the link can see and change that draft. Send it only to the person it's for.
Accounts and users
- Each email address belongs to one user, and each user belongs to one account.
- A person who manages two Tepez accounts needs a separate user, with a separate email address, in each.
- A key works only in the account of the user who created it. To work with two accounts, create a key in each.
Troubleshooting
| Response | Cause and fix |
|---|---|
401 Missing authentication | No credential reached the API. Send the key in the x-api-key header, not as a query string parameter. |
401 Invalid API key | The key is mistyped, cut short, or was revoked. |
401 Wrong username/ password | The email or password sent to POST /auth/login is wrong, or the user has no password (signs in with Google only). Create the key in the API reference instead. |
400 "apiKey" … fails to match the required pattern | DELETE /api-keys/{apiKey} got the token. Pass the key's 24-character _id. |
403 You have insufficient permissions to perform the action. | The object belongs to an account other than the key's. |
| The browser blocks the request (CORS) | API keys can't be used from a browser. Call the API from your server. |
Errors explains the error format and lists more messages.
Every response carries an x-tepez-request-id header. Quote it when you contact us.
Question about this page? Email support@tepez.co.il