API Endpoint Reference
This is the field-level reference. If you haven't yet, read The Suprata API first for authentication, paging, rate limits and error codes. Reading needs a read-scoped key; the write endpoints are covered in Writing data.
Identity & discovery
These need no scope beyond a valid key.
| Method & path | Returns |
|---|---|
GET /v1/me |
The account this key belongs to (tenant.id, tenant.name), the key's scopes, label/prefix, and its per-minute rate_limit. Call it first to confirm auth. |
GET /v1 |
A discovery index: every endpoint this key can reach. |
GET /v1/openapi.json |
The full OpenAPI 3.0 spec, for Swagger UI or SDK generators. |
GET /v1/event_types |
Every event you can subscribe a webhook to or filter the event feed on. |
How every resource works
Each resource below has two read endpoints:
- List:
GET /v1/{resource}, cursor-paginated, newest first. Always takeslimit(1–200, default 50) andstarting_after(pass the previousnext_cursor). - Single:
GET /v1/{resource}/{id}, one record by its numericid, or404.
On top of that, each resource takes the filters in this table. They combine (all must match), and they work with paging.
| Resource | account_id |
created_after |
updated_since |
Search | Other |
|---|---|---|---|---|---|
accounts |
✓ dateadded |
✓ lastupdate |
email, phone, q |
||
contacts |
✓ | ✓ dateadded |
email, phone |
||
jobs |
✓ | ✓ creationdate |
business_unit |
||
invoices |
✓ | ✓ timestamp |
✓ lastupdate |
business_unit |
|
appointments |
✓ | business_unit |
|||
reservations |
✓ | ✓ created_at |
✓ updated_at |
business_unit |
|
contracts |
✓ | ✓ timestamp |
business_unit |
||
permits |
✓ | ✓ created_at |
|||
pricelist |
✓ lastupdate |
||||
payments |
✓ | ✓ timestamp |
business_unit |
||
sms |
✓ | ✓ timestamp |
direction |
created_after/updated_sincetake a Unix timestamp or an ISO 8601 date/time. Sending one to a resource without a ✓ returns400(appointments, for example, don't record when they were created).- Search is exact, not fuzzy.
emailmatches case-insensitively.phonecompares digits only (formatting and a leading+1are ignored; the last 10 digits are compared) and needs at least 7 digits.q(customers only) is a "contains" search on name, organization and email, at least 2 characters. - On customers,
emailandphonealso match the customer's contacts. Searching for the person who called finds their account even when they're the second contact on it.
# Who is this caller?
curl "https://your-account.suprata.com/api/v1/accounts?phone=%2B1%20(786)%20555-0199" \
-H "Authorization: Bearer sk_live_your_key"
# Everything that changed since my last sync
curl "https://your-account.suprata.com/api/v1/accounts?updated_since=2026-10-06T14:00:00Z" \
-H "Authorization: Bearer sk_live_your_key"
A note on dates. Some fields are calendar dates (
YYYY-MM-DD), some are Unix timestamps (an integer number of seconds;0usually means "not set"), and the reservation tables use full datetimes. Each table below flags which is which where it matters.
Customers: GET /v1/accounts
Your customer accounts. (In the app these are "Accounts"; each can have several contacts.)
| Field | Type | Notes |
|---|---|---|
id |
integer | Primary key. Use this everywhere (/accounts/{id}, account_id=, starting_after). |
accounttype |
integer | 1 = an individual; anything else = a business. |
organizationname |
string | Company name (businesses). |
fname, lname |
string | The primary contact's name (kept in step automatically). |
email, priphone, altphone |
string | Billing contact details. Phones are stored as digits. |
address1, address2, city, state, zip, country |
string | Billing address. country is a two-letter code. |
balance |
decimal | Current account balance. |
accountmanager |
integer | The staff user id who owns the account. |
dateadded, lastupdate |
integer | Unix timestamps. lastupdate moves on every save. |
⚠️ Don't confuse id with accountid. id is the primary key you query on. The column literally named accountid is an external reference (e.g. a QuickBooks handle), not the key.
Contacts: GET /v1/contacts
The individual people attached to customers.
| Field | Type | Notes |
|---|---|---|
id |
integer | Primary key. |
account_id |
integer | The customer this contact belongs to. (A contact on several customers shows the oldest.) |
fname, lname |
string | Contact name. |
coname |
string | Company, if the contact carries one. |
email, priphone, altphone |
string | Contact details. |
address1, address2, city, state, zip, country |
string | Location. |
active |
integer | 0 = deactivated in the app. |
dateadded |
integer | Unix timestamp. |
Use GET /v1/contacts?account_id=1042 to list one customer's contacts.
Jobs / work orders: GET /v1/jobs
| Field | Type | Notes |
|---|---|---|
id |
integer | Primary key. |
jobidentificationnumber |
string | The human-facing job number. |
accountid |
integer | The customer (accounts.id). |
jobtype |
integer | A job type id (GET /v1/job_types). |
status |
integer | A job status id (GET /v1/job_statuses). |
businessunit |
integer | A business unit id (GET /v1/business_units). |
startdate |
date | Scheduled date (YYYY-MM-DD). |
starttime |
time | Scheduled time of day (HH:MM:SS). |
summary |
string | Job description. |
instore |
integer | 1 = at the customer's location, 2 = in the shop. |
createdby |
integer | Staff user id (-1 = created through the API or an automation). |
creationdate, closetime, conversiontime |
integer | Unix timestamps (closetime > 0 means the job is closed). |
Invoices & estimates: GET /v1/invoices
A safe projection: the numbers and dates, not internal sync columns.
| Field | Type | Notes |
|---|---|---|
id |
integer | Primary key. |
uniqueid |
string | The invoice number printed on the document (what your customer sees). |
accountid |
integer | The customer (accounts.id). |
jobid |
integer | Linked job, if any. |
reservationid |
integer | Linked reservation, if any. |
isestimate |
integer | 1 = an estimate, 0 = an invoice. |
subtotal, tax, total |
decimal | Money. total is the document total. |
amtpaid, amtdue, amtrefunded |
decimal | amtdue is the outstanding balance. |
invoicedate, duedate |
date | YYYY-MM-DD. |
notes |
string | Free-text notes. |
approved, voided, closed |
integer | Unix timestamps that double as flags: 0 = no, > 0 = when it happened. So voided > 0 means voided; closed > 0 means paid & closed. |
timestamp, lastupdate |
integer | Created / last changed (Unix). |
businessunit |
integer | The business unit that owns it (when you use business units). |
Appointments: GET /v1/appointments
| Field | Type | Notes |
|---|---|---|
id |
integer | Primary key. |
jobid |
integer | The job this appointment belongs to (reach the customer via the job, or filter with account_id). |
servicelocationid |
integer | Where the work happens. |
startdate, enddate |
date | YYYY-MM-DD. |
starttime, endtime |
time | HH:MM:SS. |
status |
integer | 0 Unscheduled · 1 Scheduled · 2 Confirmed · 3 Completed · 4 Cancelled · 5 On Hold · 6 Working · 7 Dispatched. |
notes |
string | |
author |
integer | Creating staff user id. |
confirmtime, dispatchtime |
integer | Unix timestamps (flags: > 0 = confirmed / dispatched). |
Reservations: GET /v1/reservations
Marina/asset bookings. These tables use full datetimes (YYYY-MM-DD HH:MM:SS), not Unix integers.
| Field | Type | Notes |
|---|---|---|
id |
integer | Primary key. |
reservation_number |
integer | The human-facing reservation number. |
customer_id |
integer | The customer (accounts.id). |
reservation_type_id |
integer | The reservation type. |
status |
string | One of draft, reserved, checked_in, active, ready_for_checkout, completed, canceled, no_show. |
start_ts, end_ts |
datetime | Booking window. |
checkin_ts, checkout_ts |
datetime | Null until they happen. |
master_invoice_id |
integer | The reservation's invoice (populated at settlement/checkout). |
notes, title |
string | |
created_at, updated_at |
datetime |
Service agreements: GET /v1/contracts
| Field | Type | Notes |
|---|---|---|
id |
integer | Primary key. |
contractname, nickname |
string | Agreement name. |
accountid |
integer | The customer. |
contractstatus |
integer | 1 = open, 0 = closed. |
contractdate |
date | |
autoclosedatetime |
date | Scheduled auto-close date. |
issubscription |
integer | 1 = a recurring subscription. |
timestamp |
integer | Created (Unix). |
Passes & permits: GET /v1/permits
| Field | Type | Notes |
|---|---|---|
id |
integer | Primary key. |
account_id |
integer | The customer the permit belongs to. |
status |
string | pending_payment, pending_approval, active, declined, expired, used, void. |
start_date, end_date |
date | Validity window. |
created_at |
integer | Unix timestamp. |
Price list items: GET /v1/pricelist
| Field | Type | Notes |
|---|---|---|
id |
integer | Primary key. |
producttitle |
string | Item name. |
shortdesc |
string | Description. |
sku |
string | The item's SKU. |
mfgsku, vendorsku |
string | Manufacturer / vendor SKUs. |
category |
string | Item category. |
baseprice, msrp |
decimal | Pricing. |
active |
integer | 1 = sellable. |
lastupdate |
integer | Last changed (Unix). |
Payments: GET /v1/payments
A deliberately narrow projection: card and token columns are never exposed. This list holds every payment row, including scheduled future payments and failed attempts; for "money actually received", use the payment.made event.
| Field | Type | Notes |
|---|---|---|
id |
integer | Primary key. |
invoiceid |
integer | The invoice paid (filter with account_id to get one customer's). |
paidamt |
decimal | Payment amount. |
paymenttype, paymethod |
string | How it was paid / which processor. |
paystatus |
integer | Settlement status. |
amtrefunded, voided, balanceapplied |
decimal | Refunded / voided / account credit used. |
nonmonetary |
integer | 1 = a non-cash adjustment. |
lastfour |
string | Last four digits of the card, if any. |
description |
string | |
timestamp |
integer | Recorded (Unix). |
Text messages: GET /v1/sms
Both directions of your texting conversations. direction=inbound for messages you received, outbound for ones you sent.
| Field | Type | Notes |
|---|---|---|
id |
integer | Primary key. |
phonenumber |
string | The other party's number (digits). |
body |
string | The message. |
incoming |
integer | 1 = received, 0 = sent. |
accountid |
integer | The customer it's filed under (-1 = not matched to one). |
mediaurl |
string | Picture/media link for MMS. |
status |
string | Delivery status for sent messages. |
timestamp |
integer | Unix timestamp. |
Lookups: GET /v1/job_types, /v1/job_statuses, /v1/business_units
The ids the job endpoints take. Each row is id, name, active, plus isdefault (job types, business units) or closesjob (statuses).
The event feed: GET /v1/events
Everything a webhook would have told you, readable by polling. Newest first, kept for about 14 days.
| Parameter | Meaning |
|---|---|
type |
An event key, or several comma-separated (job.status_changed,job.created). Unknown keys return 400. |
created_after |
Only events after this time (Unix or ISO 8601). |
limit, starting_after |
Paging (1–100, default 25). |
Each item is the same envelope a webhook delivers (id, event, created, entity, data), with the same projections as the endpoints above, so payment card columns never appear here either. GET /v1/events/{id} returns one.
Use the feed when a change has no record of its own: "a job's status changed" isn't a new job, but it is a new event with its own id.
Webhook subscriptions: /v1/webhooks
Subscribe a URL to events through the API. This is what Zapier does when you turn a Zap on. Needs a read & write key.
| Method & path | Does |
|---|---|
POST /v1/webhooks |
Body {"url": "https://…", "events": ["account.created"], "name": "optional"}. Returns 201 with the subscription and its signing secret (shown once). The URL must be public http(s); private and internal addresses are refused. |
GET /v1/webhooks |
The subscriptions this key made. |
GET /v1/webhooks/{id} |
One of them. |
DELETE /v1/webhooks/{id} |
Unsubscribe. Only works on this key's own subscriptions (404 otherwise). |
Subscriptions made in the app's Webhooks screen, or by another key, are invisible here. Revoking a key switches its subscriptions off. A key may hold 100 active subscriptions.
Common stumbling blocks
- Resolving names. The API returns ids (
accountid,jobid), not names. Fetch the related record (GET /v1/accounts/{accountid}) to get the display name, and cache it. - Timestamp
0is not "epoch 1970". On the flag-style fields (voided,closed,approved,confirmtime),0means "hasn't happened". Test> 0; don't format0as a date. - Estimates and invoices share one endpoint. Filter on
isestimate(1= estimate). There's no separate/estimatesroute. - A phone search found nothing. Check you sent at least 7 digits, and remember the comparison is on the last 10 digits, so an extension typed into the phone field will stop it matching.
created_afterreturned 400. That resource doesn't record a creation time; use the table above, or remember the highestidyou've seen instead.