Docs

Query and export entries

Filter a form's entries with query, keep responses small with fields, page through large results, and export entries to CSV, Excel or PDF.

This page shows how to read many entries at once. You will filter a form's entries with query, trim each item with fields, page through a large result, and export entries to a CSV, Excel or PDF file.

List a form's entries

GET /entry lists entries. It takes four parameters in the query string:

ParameterWhat it does
queryA JSON object that filters the entries. Always include the form. See Filter with query.
fieldsA JSON array of the properties to keep in each item. See Choose the fields.
limitThe page size, up to 2,000. Always send it. See Page through the results.
afterThe cursor of the next page. Take it from the Link header.

This lists a form's submitted entries, two per page:

curl -G -i https://api.tepez.co.il/v1.0/entry \
  -H "x-api-key: $TEPEZ_API_KEY" \
  --data-urlencode 'query={"form":"<formId>","status":2}' \
  --data-urlencode 'fields=["id","submitTime","data"]' \
  --data-urlencode 'limit=2'

The response, with the headers trimmed:

HTTP/1.1 200 OK
link: <https://api.tepez.co.il/v1.0/entry?after=<cursor>&query=…&fields=…&limit=2>; rel=next
{
  "data": [
    {
      "id": "<entryId>",
      "submitTime": "2026-09-30T19:45:59.995Z",
      "data": {
        "fullName": "Dana Levi",
        "email": "dana@example.com",
        "position": "dev",
        "address": { "city": "Haifa", "street": "Herzl 10" }
      }
    },
    {
      "id": "<entryId2>",
      "submitTime": "2026-09-30T19:46:10.168Z",
      "data": {
        "fullName": "Yossi Cohen",
        "email": "yossi.cohen@example.com",
        "position": "qa"
      }
    }
  ]
}

The link header means more entries match. The next section shows how to follow it.

Filter with query

query is a JSON object. Each key names a property of the entry, and takes either a value, which must match exactly, or an object of operators. The API accepts these keys:

KeyTypeOperators
formform id$eq $ne $in $nin
_identry id$eq $ne $in $nin
statusstatus number, 0 to 5$eq $ne $in $nin
changedAtdate$eq $ne $in $nin $gt $gte $lt $lte
modifyTimedate$eq $ne $in $nin $gt $gte $lt $lte
deletedboolean$eq $ne
  • status takes the number, not the label: 2, not "submitted". The numbers are listed in Statuses.
  • Note _id with an underscore. Entries in responses carry the same value as id.
  • deleted adds nothing on a plain list request (without deleteMarkers): such requests never return deleted entries. To learn which entries were deleted, use deleteMarkers=true, as in Poll for changes.
  • Other keys, such as submitTime or data.*, fail with 400, for example "query.submitTime" is not allowed. So does an operator the key doesn't take.

A few filters, each with form as the first key:

{ "form": "<formId>", "status": { "$in": [1, 2] } }

Drafts and submitted entries.

{ "form": "<formId>", "modifyTime": { "$gte": "2026-09-01T00:00:00.000Z", "$lt": "2026-10-01T00:00:00.000Z" } }

Entries whose data or status changed in September 2026, UTC.

{ "form": "<formId>", "_id": { "$in": ["<entryId>", "<entryId2>"] } }

Specific entries, for example the ones your system still waits for.

No filters on the entry's data

query can't filter on the values people filled in. A key such as data.position fails with 400 "query.data.position" is not allowed. Earlier versions of the API accepted such filters. They were removed in March 2025.

To find entries by a value, list them with a filter the API accepts, such as form, status and a date, and filter the results in your system. To look entries up by your own id, store the Tepez entry id next to your record when you create the entry.

Dates

Send dates as ISO 8601 strings, like the ones in responses:

  • "2026-09-30T19:46:00.000Z" is UTC.
  • "2026-09-30T22:46:00+03:00" is the same moment in Israel time.
  • "2026-09-30" is midnight UTC at the start of that day.

Other formats, such as 30/09/2026, fail with 400 "query.modifyTime.$gt" must be a valid date. Responses always give times in UTC.

changedAt or modifyTime

Every entry has two "last changed" times:

PropertyMoves when
modifyTimeThe entry's data or status changes.
changedAtAnything about the entry changes, including a PDF archived or an email sent after the submit.

Use changedAt to catch every change, for example when you sync entries to your system. Use modifyTime to find entries whose data changed. Get notified when a form is submitted has a complete polling recipe built on changedAt.

Choose the fields

fields is a JSON array of the properties to keep in each item. Leave it out to get whole entries, with their actions, emails and PDFs.

  • List id explicitly. fields drops every property you don't name, id included.
  • A dotted path keeps one value from inside the entry: ["id","data.fullName"] returns {"id": "<entryId>", "data": {"fullName": "Dana Levi"}}.
  • Send a JSON array. A comma list, such as fields=id,status, returns 200 with empty items.
  • Names that don't exist are ignored without an error.

Page through the results

  • Always send limit. Without it, the API returns every matching entry in one response, which is slow for a large form. limit goes up to 2,000 (see Limits).
  • Follow the Link header until a response has none. When more entries match, the response carries Link: <…>; rel=next, the full URL of the next page, with after set to an opaque cursor. Use the URL as it is.
  • Results come in the order the entries were created, oldest first. There is no sort parameter: GET /entry ignores it, and the order doesn't change.

This fetches every submitted entry of a form:

# The next page: the URL from the Link header of the previous response
curl -G -i https://api.tepez.co.il/v1.0/entry \
  -H "x-api-key: $TEPEZ_API_KEY" \
  --data-urlencode 'query={"form":"<formId>","status":2}' \
  --data-urlencode 'fields=["id","submitTime","data"]' \
  --data-urlencode 'limit=2' \
  --data-urlencode 'after=<cursor>'

The last page has no Link header:

HTTP/1.1 200 OK
{
  "data": [
    {
      "id": "<entryId5>",
      "submitTime": "2026-09-30T19:47:27.114Z",
      "data": { "fullName": "Avi Mor", "position": "dev" }
    }
  ]
}

Export entries to a file

POST /entry/export writes a form's entries to a file and returns a link to download it. It is the same export as the Export button in the management app.

  • format, in the query string: csv, xlsx or pdf.
  • query, in the body: the same filter as in GET /entry. It must include form.
  • fields, in the body, optional: the columns to include, in order. Leave it out to get the form's default columns.
curl -X POST "https://api.tepez.co.il/v1.0/entry/export?format=csv" \
  -H "x-api-key: $TEPEZ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": {"form": "<formId>", "status": 2},
    "fields": ["id", "submitTime", "root≡fullName", "root≡address≡city", "root≡position"]
  }'

On Windows, curl mangles the ≡ in an argument. Put the body in a UTF-8 file and send it with --data-binary @body.json instead of -d.

{
  "url": "https://<bucket>.s3.eu-west-1.amazonaws.com/<uuid>/Job%20application.csv?<presigned-query>"
}

Download the file from url. It needs no API key, and it stays valid for about 2 days. CSV and Excel files are stored compressed, so tell your HTTP client to decompress them: curl needs --compressed, while browsers, fetch and Python's requests decompress it on their own.

curl --compressed -o entries.csv "<url>"
Unique ID,Submitted,Full name,City,Position
<entryId>,09/30/2026 7:45 PM,Dana Levi,Haifa,dev
<entryId2>,09/30/2026 7:46 PM,Yossi Cohen,,qa
<entryId5>,09/30/2026 7:47 PM,Avi Mor,,dev

What each format holds:

formatThe file
csvOne row per entry, UTF-8 with a byte order mark, so Excel shows Hebrew correctly. The first row holds the column titles.
xlsxThe same rows as an Excel workbook.
pdfA ZIP file with one PDF per entry, rendered now from each entry's current data. fields doesn't apply.

To keep the archived PDFs and the uploaded files instead, see Download PDFs and files.

Column names

Each item of fields is a column's name:

  • Entry properties go by their name: id, idx, submitIdx, status, name, createTime, modifyTime, submitTime, form.id, form.name, resumeUrl, resumeUrlBewit, editUrl, cloneUrl, shortUrl.
  • A field's column is the name of every element on its path, from root down, joined with ≡ (U+2261): root≡fullName, root≡address≡city. Unlike data paths, the path includes every section and tab, so a file field cv inside tabs named steps is root≡steps≡cv.

A name that doesn't exist fails with 400 The following fields are not recognized …, listing it.

The export isn't paged: one file holds every matching entry. Deleted entries are never included.

Troubleshooting

ResponseCause and fix
400 "query.data.…" is not allowedquery can't filter on the entry's data. Filter by form, status and a date, then filter the results in your system.
400 "query.<key>" is not allowedThe key isn't one of the keys in Filter with query.
400 "query.status" must be one of [object, 0, 1, 2, 3, 4, 5]query takes the status number, not its label: "status":2, not "status":"submitted".
400 "query" must be of type objectquery isn't valid JSON. Quote the keys and the operators: {"form":"<formId>"}.
400 "query.modifyTime.$gt" must be a valid dateSend the date in ISO 8601, such as 2026-09-30T00:00:00.000Z.
400 "limit" must be less than or equal to 2000Lower limit, and follow the Link header for the rest.
200 with empty items ({"data":[{},{}]})fields was a comma list. Send a JSON array, and include "id".
The same entries come back in the same order despite sortThere is no sort. Entries always come oldest first. Sort them in your system.
Some entries are missing from a long listYour code stopped before the last page. Follow Link until a response has none.
400 Query must contain a form from the exportPut form in the export's query.
400 The following fields are not recognized … from the exportA column name is wrong. Check the path, including sections and tabs, and the ≡ separator.
The downloaded CSV is unreadable binaryYour client saved the compressed file. Download it again with curl --compressed.
The export link returns 403 AccessDeniedIt expired after about 2 days. Export again.

Errors explains the error format and lists more messages.

Every response from the API 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