EverStamp API

Everything the dashboard can do, your own software can do too. One API key acts for one organisation with the rights of an administrator. Evidence never travels through this API: a dossier stays on the phone that made it, the register records that it exists, and anyone verifies on everstamp.app/verify without us.

Get started

  1. 1In the dashboard, open Settings, Integrations and create an API key. It is shown once; store it as a secret on your server.
  2. 2Call the API with the key as a bearer token. JSON in, JSON out, UTF-8, ISO 8601 times. Every id is a ulid.
  3. 3Prepare an order: it appears in the app of the field worker you assign it to. When the dossier is registered, your webhook hears it.
curl https://api.everstamp.app/v1/orders -H "Authorization: Bearer $EVERSTAMP_KEY"

Authentication

An API key from the dashboard (Settings, Integrations): `esk_` followed by 32 characters. Send it as `Authorization: Bearer esk_...`. It acts for one organisation with the rights of an administrator.

Revoke a key the moment it leaks; a revoked key stays revoked. Keys act with the rights of an administrator, so keep them server-side, never in an app or a browser. One key per piece of software makes the audit log readable: every order an integration prepares carries the key name.

Concepts

Order. What the office (or your software) prepares for a member: a name, an address, a checklist, optionally a project, labels, a due date and a note. Every phone linked to that member sees it; picking it up creates the dossier on the phone. The status is never a claim by the app: claimed means the register saw the pickup, registered means the dossier row is in the register.

Dossier. A series of captures made on one phone, sealed with a qualified timestamp and registered. The photos stay on the phone until the maker shares them; the API sees who, when, the root hash and whether the register has stamped the period. Verification of a shared dossier happens on everstamp.app/verify, without this API.

Checklist. Steps with a minimum number of captures each, strict or free. The library ships 22 checklists per industry; your own are versioned and a version never changes, so an old dossier always reads against the checklist it was made with.

Project and labels. Grouping and filtering. Context, never part of the evidence.

Errors and limits

Errors are JSON with a stable error code and a human message. Codes you will meet: api-key (401), invalid-body (400), unknown-member, unknown-template, unknown-project (422), order-claimed (409: the order was picked up, the dossier exists), rate-limit (429, with Retry-After).

Lists return at most 500 orders and 100 dossiers per page; page dossiers with before. Calls are idempotent where it matters: withdrawing twice is fine, a phone picking up twice with the same dossier is fine. The API is versioned in the path (/v1); fields are only ever added, never renamed or removed within a version.

Orders

What the office prepares and a field worker picks up in the app. The status comes from the register: prepared, claimed (picked up), registered, cancelled.

GET/v1/ordersList orders
Query parameters
statusquerycomma-separated: prepared, claimed, registered, cancelled
projectqueryonly orders of this project (ulid)
archivedquery1 to include archived orders
Responses
200 OK
format *"everstamp/3"always "everstamp/3"
orders *array of object
id *stringulid
organisation *stringorganisation id (ulid); implied by your key
title *stringname of the dossier as the app shows it
addressstringaddress, on the stamp bar
notestringa note for the field worker
template *object
name *stringmachine name: lower case, digits and dashes; fixed after publishing
version *integerassigned by the API; a version never changes
member *stringthe member the order is for (member id from GET /v1/members); every phone of that member sees it
memberName *stringthat member's name
duestring (date-time)wanted by (ISO 8601)
createdAt *string (date-time)when it was created (ISO 8601)
createdBystringwho created it, as free text
status *"prepared" | "claimed" | "registered" | "cancelled"prepared, claimed (at least one phone picked it up), registered (every pickup is in the register) or cancelled; always from the register, never from a message by the app
claimedAtstring (date-time)first pickup
claimedBystringdevice of the first pickup (sha-256 of the key id)
dossierstringdossier id (ulid)
registeredAtstring (date-time)when the first dossier was registered
stampedAtstring (date-time)qualified timestamp of that dossier
rootstringroot hash of that dossier
cancelledAtstring (date-time)withdrawn on
cancelReasonstringwhy it was withdrawn
projectstringproject id (ulid)
projectNamestringfilled in from the project when omitted
tagsarray of stringlabels of the organisation; context to filter and count, never evidence
stampBarobject
fields *array of "time" | "address" | "position" | "dossier" | "project" | "step" | "operator" | "organisation" | "note"lines on the bar, in order: time, address, position, dossier, project, step, operator, organisation, note
position"bottom" | "top"bottom or top
theme"dark" | "light"dark bar with light text, or light
size"small" | "medium" | "large"small, medium or large
namestringa name for this layout
claimsarray of object
device *stringthe phone (sha-256 of its key id)
memberstringthe member that phone belonged to at the time
memberNamestringtheir name
dossier *stringdossier id (ulid)
claimedAt *string (date-time)picked up on
registeredAtstring (date-time)registered on
stampedAtstring (date-time)qualified timestamp of the dossier
rootstringroot hash of the dossier
archivedAtstring (date-time)archived on the dashboard: out of view, not deleted
400 bad filter
401 missing or unknown key
curl -X GET https://api.everstamp.app/v1/orders \
  -H "Authorization: Bearer $EVERSTAMP_KEY"

Opdrachten

POST/v1/ordersPrepare an order

The order appears in the app of the member you assign it to. `member` is a member id from GET /v1/members; the API fills in `memberName`. `template` is {name, version}: a built-in checklist from the library or one of your own.

Request body
title *stringname of the dossier as the app shows it
addressstringaddress, on the stamp bar
notestringa note for the field worker
template *object
name *stringmachine name: lower case, digits and dashes; fixed after publishing
version *integerassigned by the API; a version never changes
member *stringthe member the order is for (member id from GET /v1/members); every phone of that member sees it
duestring (date-time)wanted by (ISO 8601)
stampBarobject
fields *array of "time" | "address" | "position" | "dossier" | "project" | "step" | "operator" | "organisation" | "note"lines on the bar, in order: time, address, position, dossier, project, step, operator, organisation, note
position"bottom" | "top"bottom or top
theme"dark" | "light"dark bar with light text, or light
size"small" | "medium" | "large"small, medium or large
namestringa name for this layout
projectstringproject id (ulid)
projectNamestringfilled in from the project when omitted
tagsarray of stringlabels of the organisation; context to filter and count, never evidence
Responses
201 prepared
order *object
id *stringulid
organisation *stringorganisation id (ulid); implied by your key
title *stringname of the dossier as the app shows it
addressstringaddress, on the stamp bar
notestringa note for the field worker
template *object
name *stringmachine name: lower case, digits and dashes; fixed after publishing
version *integerassigned by the API; a version never changes
member *stringthe member the order is for (member id from GET /v1/members); every phone of that member sees it
memberName *stringthat member's name
duestring (date-time)wanted by (ISO 8601)
createdAt *string (date-time)when it was created (ISO 8601)
createdBystringwho created it, as free text
status *"prepared" | "claimed" | "registered" | "cancelled"prepared, claimed (at least one phone picked it up), registered (every pickup is in the register) or cancelled; always from the register, never from a message by the app
claimedAtstring (date-time)first pickup
claimedBystringdevice of the first pickup (sha-256 of the key id)
dossierstringdossier id (ulid)
registeredAtstring (date-time)when the first dossier was registered
stampedAtstring (date-time)qualified timestamp of that dossier
rootstringroot hash of that dossier
cancelledAtstring (date-time)withdrawn on
cancelReasonstringwhy it was withdrawn
projectstringproject id (ulid)
projectNamestringfilled in from the project when omitted
tagsarray of stringlabels of the organisation; context to filter and count, never evidence
stampBarobject
fields *array of "time" | "address" | "position" | "dossier" | "project" | "step" | "operator" | "organisation" | "note"lines on the bar, in order: time, address, position, dossier, project, step, operator, organisation, note
position"bottom" | "top"bottom or top
theme"dark" | "light"dark bar with light text, or light
size"small" | "medium" | "large"small, medium or large
namestringa name for this layout
claimsarray of object
device *stringthe phone (sha-256 of its key id)
memberstringthe member that phone belonged to at the time
memberNamestringtheir name
dossier *stringdossier id (ulid)
claimedAt *string (date-time)picked up on
registeredAtstring (date-time)registered on
stampedAtstring (date-time)qualified timestamp of the dossier
rootstringroot hash of the dossier
archivedAtstring (date-time)archived on the dashboard: out of view, not deleted
400 invalid body
422 unknown member, checklist or project
curl -X POST https://api.everstamp.app/v1/orders \
  -H "Authorization: Bearer $EVERSTAMP_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title":"Kloosterweg 14, meter cupboard","template":{"name":"meter-cupboard","version":1},"member":"01K4BQ4A1PZQ6D2E8F0G3H5J7K"}'
GET/v1/orders/{id}One order
Query parameters
id *paththe id (ulid)
Responses
200 OK
order *object
id *stringulid
organisation *stringorganisation id (ulid); implied by your key
title *stringname of the dossier as the app shows it
addressstringaddress, on the stamp bar
notestringa note for the field worker
template *object
name *stringmachine name: lower case, digits and dashes; fixed after publishing
version *integerassigned by the API; a version never changes
member *stringthe member the order is for (member id from GET /v1/members); every phone of that member sees it
memberName *stringthat member's name
duestring (date-time)wanted by (ISO 8601)
createdAt *string (date-time)when it was created (ISO 8601)
createdBystringwho created it, as free text
status *"prepared" | "claimed" | "registered" | "cancelled"prepared, claimed (at least one phone picked it up), registered (every pickup is in the register) or cancelled; always from the register, never from a message by the app
claimedAtstring (date-time)first pickup
claimedBystringdevice of the first pickup (sha-256 of the key id)
dossierstringdossier id (ulid)
registeredAtstring (date-time)when the first dossier was registered
stampedAtstring (date-time)qualified timestamp of that dossier
rootstringroot hash of that dossier
cancelledAtstring (date-time)withdrawn on
cancelReasonstringwhy it was withdrawn
projectstringproject id (ulid)
projectNamestringfilled in from the project when omitted
tagsarray of stringlabels of the organisation; context to filter and count, never evidence
stampBarobject
fields *array of "time" | "address" | "position" | "dossier" | "project" | "step" | "operator" | "organisation" | "note"lines on the bar, in order: time, address, position, dossier, project, step, operator, organisation, note
position"bottom" | "top"bottom or top
theme"dark" | "light"dark bar with light text, or light
size"small" | "medium" | "large"small, medium or large
namestringa name for this layout
claimsarray of object
device *stringthe phone (sha-256 of its key id)
memberstringthe member that phone belonged to at the time
memberNamestringtheir name
dossier *stringdossier id (ulid)
claimedAt *string (date-time)picked up on
registeredAtstring (date-time)registered on
stampedAtstring (date-time)qualified timestamp of the dossier
rootstringroot hash of the dossier
archivedAtstring (date-time)archived on the dashboard: out of view, not deleted
404 no such order in this organisation
curl -X GET https://api.everstamp.app/v1/orders/01K4C0Z9Y8X7W6V5T4S3R2Q1P0 \
  -H "Authorization: Bearer $EVERSTAMP_KEY"
POST/v1/orders/{id}Change a prepared order

Only while the order is prepared; once a phone picked it up the dossier exists and the order is fixed (409 order-claimed). Send only the fields you change. `clearProject: true` removes the project, `tags: []` removes the labels.

Query parameters
id *paththe id (ulid)
Request body
titlestringname of the dossier as the app shows it
addressstringaddress, on the stamp bar
notestringa note for the field worker
templateobject
name *stringmachine name: lower case, digits and dashes; fixed after publishing
version *integerassigned by the API; a version never changes
memberstringthe member the order is for (member id from GET /v1/members); every phone of that member sees it
duestring (date-time)wanted by (ISO 8601)
stampBarobject
fields *array of "time" | "address" | "position" | "dossier" | "project" | "step" | "operator" | "organisation" | "note"lines on the bar, in order: time, address, position, dossier, project, step, operator, organisation, note
position"bottom" | "top"bottom or top
theme"dark" | "light"dark bar with light text, or light
size"small" | "medium" | "large"small, medium or large
namestringa name for this layout
clearStampBarbooleantrue removes the order's own stamp-bar layout
clearProjectbooleantrue removes the order from its project
projectstringproject id (ulid)
projectNamestringfilled in from the project when omitted
tagsarray of stringlabels of the organisation; context to filter and count, never evidence
Responses
200 OK
order *object
id *stringulid
organisation *stringorganisation id (ulid); implied by your key
title *stringname of the dossier as the app shows it
addressstringaddress, on the stamp bar
notestringa note for the field worker
template *object
name *stringmachine name: lower case, digits and dashes; fixed after publishing
version *integerassigned by the API; a version never changes
member *stringthe member the order is for (member id from GET /v1/members); every phone of that member sees it
memberName *stringthat member's name
duestring (date-time)wanted by (ISO 8601)
createdAt *string (date-time)when it was created (ISO 8601)
createdBystringwho created it, as free text
status *"prepared" | "claimed" | "registered" | "cancelled"prepared, claimed (at least one phone picked it up), registered (every pickup is in the register) or cancelled; always from the register, never from a message by the app
claimedAtstring (date-time)first pickup
claimedBystringdevice of the first pickup (sha-256 of the key id)
dossierstringdossier id (ulid)
registeredAtstring (date-time)when the first dossier was registered
stampedAtstring (date-time)qualified timestamp of that dossier
rootstringroot hash of that dossier
cancelledAtstring (date-time)withdrawn on
cancelReasonstringwhy it was withdrawn
projectstringproject id (ulid)
projectNamestringfilled in from the project when omitted
tagsarray of stringlabels of the organisation; context to filter and count, never evidence
stampBarobject
fields *array of "time" | "address" | "position" | "dossier" | "project" | "step" | "operator" | "organisation" | "note"lines on the bar, in order: time, address, position, dossier, project, step, operator, organisation, note
position"bottom" | "top"bottom or top
theme"dark" | "light"dark bar with light text, or light
size"small" | "medium" | "large"small, medium or large
namestringa name for this layout
claimsarray of object
device *stringthe phone (sha-256 of its key id)
memberstringthe member that phone belonged to at the time
memberNamestringtheir name
dossier *stringdossier id (ulid)
claimedAt *string (date-time)picked up on
registeredAtstring (date-time)registered on
stampedAtstring (date-time)qualified timestamp of the dossier
rootstringroot hash of the dossier
archivedAtstring (date-time)archived on the dashboard: out of view, not deleted
404 no such order
409 order-claimed or order-cancelled
curl -X POST https://api.everstamp.app/v1/orders/01K4C0Z9Y8X7W6V5T4S3R2Q1P0 \
  -H "Authorization: Bearer $EVERSTAMP_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title":"Kloosterweg 14, meter cupboard"}'
POST/v1/orders/{id}/cancelWithdraw a prepared order
Query parameters
id *paththe id (ulid)
Request body
reasonstringwhy (optional)
Responses
200 OK
id *stringulid
cancelledAt *string (date-time)withdrawn on
409 already picked up
curl -X POST https://api.everstamp.app/v1/orders/01K4C0Z9Y8X7W6V5T4S3R2Q1P0/cancel \
  -H "Authorization: Bearer $EVERSTAMP_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Projects

A name or address that orders and dossiers belong to. Context, never evidence.

GET/v1/projectsList projects
Query parameters
archivedquery1 to include archived projects
Responses
200 OK
format *"everstamp/3"always "everstamp/3"
projects *array of object
id *stringulid
organisation *stringorganisation id (ulid); implied by your key
name *stringname or address
addressstringaddress, when the name is not one
notestringnote
tagsarray of stringlabels of the organisation; context to filter and count, never evidence
createdAt *string (date-time)when it was created (ISO 8601)
createdBystringwho created it, as free text
archivedAtstring (date-time)archived on the dashboard: out of view, not deleted
ordersinteger
dossiersintegerthe dossiers, newest first
curl -X GET https://api.everstamp.app/v1/projects \
  -H "Authorization: Bearer $EVERSTAMP_KEY"

Projecten

POST/v1/projectsCreate a project
Request body
name *stringname or address
addressstringaddress, when the name is not one
notestringnote
tagsarray of stringlabels of the organisation; context to filter and count, never evidence
Responses
201 created
project *objectproject id (ulid)
id *stringulid
organisation *stringorganisation id (ulid); implied by your key
name *stringname or address
addressstringaddress, when the name is not one
notestringnote
tagsarray of stringlabels of the organisation; context to filter and count, never evidence
createdAt *string (date-time)when it was created (ISO 8601)
createdBystringwho created it, as free text
archivedAtstring (date-time)archived on the dashboard: out of view, not deleted
ordersinteger
dossiersintegerthe dossiers, newest first
400 invalid body
curl -X POST https://api.everstamp.app/v1/projects \
  -H "Authorization: Bearer $EVERSTAMP_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Renovation West"}'

Checklists

The steps a dossier follows: built in from the library, or your own. A published version never changes.

GET/v1/templatesList checklists

Your own checklists (every version, retired ones marked) followed by the built-in library.

Responses
200 OK
format *"everstamp/3"always "everstamp/3"
templates *array of object
name *stringmachine name: lower case, digits and dashes; fixed after publishing
version *integerassigned by the API; a version never changes
organisationstringorganisation id (ulid); implied by your key
createdAtstring (date-time)when it was created (ISO 8601)
retiredbooleantrue when retired: still readable for old dossiers, not offered for new ones
mode *"strict" | "free"strict (the app only closes a dossier when every step has its minimum) or free (the steps are a guide)
industriesarray of "construction" | "automotive" | "property" | "claims" | "logistics" | "maintenance" | "general"industries this built-in checklist belongs to
title *objecttitle per language, for example {"en": "Handover", "nl": "Oplevering"}
subtitle *objectsubtitle per language
steps *array of object
id *stringstep id: lower case, digits and dashes; unique within the checklist
title *objecttitle per language
required *integerminimum number of captures in this step; 0 is optional
shotsarray of object
id *stringshot id
title *objecttitle per language
curl -X GET https://api.everstamp.app/v1/templates \
  -H "Authorization: Bearer $EVERSTAMP_KEY"
POST/v1/templatesPublish a checklist version

Publishing is always a new version; the API assigns the number. Texts are per language (at least one). `mode` is strict (the app only closes a dossier when every step has its minimum) or free.

Request body
template *object
name *stringmachine name: lower case, digits and dashes; fixed after publishing
mode *"strict" | "free"strict (the app only closes a dossier when every step has its minimum) or free (the steps are a guide)
industriesarray of "construction" | "automotive" | "property" | "claims" | "logistics" | "maintenance" | "general"industries this built-in checklist belongs to
title *objecttitle per language, for example {"en": "Handover", "nl": "Oplevering"}
subtitle *objectsubtitle per language
steps *array of object
id *stringstep id: lower case, digits and dashes; unique within the checklist
title *objecttitle per language
required *integerminimum number of captures in this step; 0 is optional
shotsarray of object
id *stringshot id
title *objecttitle per language
Responses
201 published
template *object
name *stringmachine name: lower case, digits and dashes; fixed after publishing
version *integerassigned by the API; a version never changes
organisationstringorganisation id (ulid); implied by your key
createdAtstring (date-time)when it was created (ISO 8601)
retiredbooleantrue when retired: still readable for old dossiers, not offered for new ones
mode *"strict" | "free"strict (the app only closes a dossier when every step has its minimum) or free (the steps are a guide)
industriesarray of "construction" | "automotive" | "property" | "claims" | "logistics" | "maintenance" | "general"industries this built-in checklist belongs to
title *objecttitle per language, for example {"en": "Handover", "nl": "Oplevering"}
subtitle *objectsubtitle per language
steps *array of object
id *stringstep id: lower case, digits and dashes; unique within the checklist
title *objecttitle per language
required *integerminimum number of captures in this step; 0 is optional
shotsarray of object
id *stringshot id
title *objecttitle per language
400 invalid checklist
409 name of a built-in checklist
curl -X POST https://api.everstamp.app/v1/templates \
  -H "Authorization: Bearer $EVERSTAMP_KEY" \
  -H "Content-Type: application/json" \
  -d '{"template":{"name":"meter-cupboard","version":1}}'

Dossiers

Every dossier the phones of the organisation registered: who, when, and whether the register has stamped the period yet.

GET/v1/dossiersList registered dossiers

Newest first, 100 per page; pass the `registeredAt` of the last one as `before` for the next page. Each entry says whether the register has stamped the period (`closed`), the order it came from, its project, labels and predecessor.

Query parameters
beforequerypaging: dossiers registered before this moment (ISO 8601)
projectqueryonly dossiers of this project (ulid)
Responses
200 OK
format *"everstamp/3"always "everstamp/3"
dossiers *array of objectthe dossiers, newest first
dossier *stringdossier id (ulid)
root *stringroot hash over all captures (sha-256, hex)
device *stringthe phone (sha-256 of its key id)
memberstringthe member the phone belonged to at registration
memberNamestringtheir name
stampedAt *string (date-time)qualified timestamp of the dossier
registeredAt *string (date-time)when the register recorded it
period *stringthe register period (hour or day) the row is in
closed *booleantrue when the register has stamped that period: the proof exists
orderstring
projectstringproject id (ulid)
tagsarray of stringlabels of the organisation; context to filter and count, never evidence
predecessorstringroot hash of the previous dossier when this is a follow-up
titlestringname of the dossier: from the registration, else the order title
templateobject
name *stringmachine name: lower case, digits and dashes; fixed after publishing
version *integerassigned by the API; a version never changes
more *booleantrue when there is another page
curl -X GET https://api.everstamp.app/v1/dossiers \
  -H "Authorization: Bearer $EVERSTAMP_KEY"

People and devices

Members of the organisation and the phones linked to them.

GET/v1/membersList members
Responses
200 OK
format *"everstamp/3"
members *array of object
id *stringmember id (ulid); use it as `member` when preparing an order
organisation_idstring
email *string
name *string
role *"owner" | "admin" | "worker" | "reader"
invited_atstring (date-time)
accepted_atstring | null
active *boolean
curl -X GET https://api.everstamp.app/v1/members \
  -H "Authorization: Bearer $EVERSTAMP_KEY"

Mensen en toestellen

GET/v1/devicesLinked phones and open device codes
Responses
200 OK
format *"everstamp/3"always "everstamp/3"
enrolments *array of object
device *stringthe phone (sha-256 of its key id)
organisation *stringorganisation id (ulid); implied by your key
member *stringmember id
invitation *stringthe device code that linked it
enrolledAt *string (date-time)linked on
revokedAtstring (date-time)unlinked on
invitations *array of object
id *stringulid
organisation *stringorganisation id (ulid); implied by your key
organisationName *stringorganisation name
member *stringmember the code is for
memberName *stringtheir name
createdAt *string (date-time)when it was created (ISO 8601)
expiresAt *string (date-time)valid until
usedAtstring (date-time)used on
usedBystringthe phone that used it
cancelledAtstring (date-time)withdrawn on
curl -X GET https://api.everstamp.app/v1/devices \
  -H "Authorization: Bearer $EVERSTAMP_KEY"

Webhooks

Add a webhook in the dashboard (Settings, Integrations) with an https URL and the events you want. Every delivery is a POST with the Standard Webhooks headers webhook-id, webhook-timestamp and webhook-signature (v1, plus base64 of HMAC-SHA256 over id.timestamp.body with your secret, shown once). Answer any 2xx within five seconds; otherwise we retry after 1, 5, 30 minutes, 2 and 12 hours, and switch the webhook off after eight failures in a row. The same webhook-id is reused on retries, so you can deduplicate.

0
1
2
3
Body
{ "format": "everstamp/3", "event": "dossier.registered", "at": "2026-09-05T14:53:10Z", "organisation": "01M1...", "data": { "dossier": { ... }, "order": { ... } } }
Verify the signature
import { createHmac, timingSafeEqual } from 'node:crypto';

const secret = Buffer.from(process.env.WEBHOOK_SECRET.replace('whsec_', ''), 'base64');
const id = req.headers['webhook-id'], ts = req.headers['webhook-timestamp'];
const expected = 'v1,' + createHmac('sha256', secret).update(`${id}.${ts}.${rawBody}`).digest('base64');
const ok = timingSafeEqual(Buffer.from(expected), Buffer.from(req.headers['webhook-signature']));
if (!ok || Math.abs(Date.now() / 1000 - Number(ts)) > 300) return res.status(401).end();

Recipes: Zapier, Make, n8n

No code needed for the two things most companies want: hear it when a dossier is registered, and prepare an order from something that already exists (a form, a planning tool, a CRM). The webhook URL these tools give you is unguessable, which is the shared secret for a no-code receiver; verify the signature only if the tool lets you run code.

Zapier

  1. 1. Registered dossier to a sheet or a chat. Trigger: Webhooks by Zapier, Catch Hook. Copy the URL into the dashboard (Settings, Integrations, add webhook, event dossier.registered). Register a test dossier in the app so Zapier sees a sample. Map data__dossier__title, data__dossier__memberName, data__dossier__stampedAt to a Google Sheets row, a Slack message or a Teams post.
  2. 2. Form to order. Trigger: your form (Typeform, Google Forms, Jotform). Action: Webhooks by Zapier, Custom Request, POST https://api.everstamp.app/v1/orders, header Authorization: Bearer esk_..., data: {"title": ..., "address": ..., "template": {"name": "meter-cupboard", "version": 1}, "member": "<member id>"}. Find member ids once with GET /v1/members.

Make

  1. 1. Registered dossier. Module Webhooks, Custom webhook; paste its address in the dashboard as a webhook for dossier.registered; run once to let Make learn the structure; then any module (Google Sheets, Gmail, Notion).
  2. 2. Prepare orders from a planning. Module HTTP, Make a request: POST https://api.everstamp.app/v1/orders, header Authorization with your key, body type JSON, the same body as above. Add a router on status from GET /v1/orders?status=claimed,registered to move your own records along.

n8n

  1. 1. Registered dossier. Webhook node (POST, respond immediately) as the trigger; its production URL goes in the dashboard. Optional Code node with the Node snippet above to verify webhook-signature. Then Google Sheets, Slack or Postgres.
  2. 2. Orders from a database. Schedule trigger, Postgres or MySQL node selecting the jobs of tomorrow, HTTP Request node POST https://api.everstamp.app/v1/orders with Header Auth (Authorization, Bearer esk_...) and a JSON body per item. Store the returned order.id next to your job to follow its status.
Importable n8n workflow (JSON)
{
  "name": "EverStamp: dossier registered",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "everstamp",
        "responseMode": "onReceived"
      },
      "name": "EverStamp webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "const d = $json.body.data.dossier;\nreturn [{ json: { title: d.title, who: d.memberName, stampedAt: d.stampedAt, root: d.root, project: d.project } }];"
      },
      "name": "Pick fields",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        260,
        0
      ]
    }
  ],
  "connections": {
    "EverStamp webhook": {
      "main": [
        [
          {
            "node": "Pick fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

OpenAPI

The machine-readable description of this API, generated from the same contract the app and the register are built on: openapi.json. Import it in Postman, Bruno, Insomnia or a code generator; it is the file to hand to a code assistant. Contract fingerprint 9ba699b271609634, model efc262326adc0638.

Changelog

  • 2026-09-05 Projects, labels, several pickups per order, delete and archive, checklist library with strict and free mode, stamp-bar layout, plan and usage, dossier title and checklist in the dossier list, api.everstamp.app with this reference and openapi.json.
  • 2026-09-04 First release: orders, checklists, dossiers, members, devices, webhooks.

Questions or a missing endpoint: privacy@everstamp.app · EverStamp is built by Digital Sandbox B.V., Netherlands.