Docs

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-keys shows 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.

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>"
}
  • resumeUrlBewit is the link to send to the person. It opens the entry so they can continue filling it and submit it.
  • bewit is the signature on its own, and resumeUrl is 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

ResponseCause and fix
401 Missing authenticationNo credential reached the API. Send the key in the x-api-key header, not as a query string parameter.
401 Invalid API keyThe key is mistyped, cut short, or was revoked.
401 Wrong username/ passwordThe 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 patternDELETE /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.

Email support with the request id

Question about this page? Email support@tepez.co.il

On this page