API Endpoint Reference

Every endpoint, its filters and search parameters, and the fields each resource returns: customers, contacts, jobs, invoices, payments, reservations, texts, events and webhook subscriptions.

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 takes limit (1–200, default 50) and starting_after (pass the previous next_cursor).
  • Single: GET /v1/{resource}/{id}, one record by its numeric id, or 404.

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_since take a Unix timestamp or an ISO 8601 date/time. Sending one to a resource without a ✓ returns 400 (appointments, for example, don't record when they were created).
  • Search is exact, not fuzzy. email matches case-insensitively. phone compares digits only (formatting and a leading +1 are 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, email and phone also 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; 0 usually 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 0 is not "epoch 1970". On the flag-style fields (voided, closed, approved, confirmtime), 0 means "hasn't happened". Test > 0; don't format 0 as a date.
  • Estimates and invoices share one endpoint. Filter on isestimate (1 = estimate). There's no separate /estimates route.
  • 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_after returned 400. That resource doesn't record a creation time; use the table above, or remember the highest id you've seen instead.