Developers
SubMark API
A small, read-mostly REST API for connecting SubMark to other software: three reads and one write, authenticated with a key your company admin creates in SubMark.
It is deliberately narrow. If what you need is not here, say so — that is how we pick what to add next.
Base URL
Authentication
Send your key in the X-API-Key header on every request. An
Authorization: Bearer <key> header is accepted as an
alternative; pick one and stay with it.
There is no OAuth flow and no login endpoint. A key does not expire; it works until someone revokes it.
Getting a key
A company admin creates one in SubMark under Settings → Integrations, in the API key card. The key is shown once, on creation — store it somewhere safe before you close the page. We keep only a hash of it, so we cannot show it to you again, and nobody at SubMark can read it back to you.
Create a separate key per integration and name it for that integration. Any key can be revoked at any time, which stops whatever is using it on the next request.
What a key can reach
A key authenticates a company, not a person — so it cannot be narrowed to one role's permissions the way a signed-in user is. Because of that, the reads below return no financial fields: no bid amounts, no change order values, no deal values. Everything a key can see is listed on this page, and nothing else in SubMark is reachable with one.
Connection check
GET /api/zapier/me returns
{ "company": "...", "tenant_id": 123 }. Use it to confirm
a key works and to show whoever is setting up the integration which SubMark account they
just connected.
Reads
Each read returns up to 100 records, newest first, ordered by descending
id. Deleted records are excluded.
There is no cursor and no since parameter. Poll
on whatever interval suits you and de-duplicate on id, keeping the
highest id you have already handled. A company that creates more than 100 of something
between two polls will not see the overflow, so poll often enough that it cannot happen.
| Endpoint | Fields returned |
|---|---|
| GET /api/zapier/triggers/new-deals | id, name, company, contact_name, contact_phone, contact_email, stage, source, expected_close_date, created_at |
| GET /api/zapier/triggers/new-projects | id, name, gc_company, gc_contact, gc_phone, status, created_at |
| GET /api/zapier/triggers/new-change-orders | id, project_id, project_name, co_number, title, status, category, created_at |
Writes
POST /api/zapier/actions/deals creates a deal — a lead — on your
pipeline. It is the "website form becomes a lead" path. Send JSON.
| Field | Notes |
|---|---|
| name | Required. Everything else is optional. |
| company | Free text. |
| contact_name | Free text. |
| contact_phone | Free text. |
| contact_email | Free text. |
| estimated_value | Number. Write-only — no read endpoint returns it. |
| probability | Whole number, 0–100. |
| expected_close_date | YYYY-MM-DD. |
| source | Free text. Defaults to "Zapier" if you send nothing. |
| notes | Free text. |
Those ten fields are the whole list, and anything else you send is ignored.
You will still get a 201, so an extra field looks like it worked
and is in fact dropped. The stage, the city and state, and the person the deal is assigned
to are not settable through the API.
The new deal lands in your first pipeline stage, is recorded as created by whoever made the key, and is not assigned to anyone — assign it in SubMark. Nobody is notified, so treat the pipeline, not an inbox, as where these arrive.
Responses
| Status | Meaning |
|---|---|
| 200 / 201 | Success. Reads return a JSON array; the write returns the new deal. |
| 400 | The body failed validation. The response names the field. |
| 401 | Missing, malformed, invalid or revoked key. |
| 429 | Rate limited. Back off and retry. |
| 500 | Our side. Retrying is safe for the reads. |
Rate limit
1200 requests per minute, counted per key. Ordinary integration polling is nowhere near that. The limit is per key rather than per network, so two companies polling from the same service do not take each other's budget.
Zapier
There is no SubMark app in Zapier's directory yet. We would rather say so here than have you search for one. Until there is, any tool that can send an HTTP request with a custom header can use these endpoints — including Zapier's own Webhooks action.
What the API does not cover
Draws and pay applications, T&M tags, daily logs, job costing, purchase orders, crew scheduling, the time clock, lien waiver tracking and the sub portal are not exposed. Neither is anything that moves money or changes a record that already exists — the API reads, and the one thing it writes is a new lead.
If you need one of those, email sales@submark.io and tell us which one and what you are connecting it to. That is the list we build from.