Build on the whole business — not just the books.
The BrioSync Public API is a tenant-scoped REST API across the ERP: tickets, projects, timesheets, people, quotes, orders, invoices, suppliers, purchase orders, bills, journals, deals and more. JSON and XML, Bearer API keys, signed webhooks, a live OpenAPI spec — and Ask Brio, the AI assistant that answers and writes code, right on this page.
Quick start
Up and running in three steps:
- Get your API key — a company admin generates keys in Settings → Integrations inside BrioSync. The key is shown once; store it in a secret manager.
- Make your first request — send the key in the
Authorization: Bearerheader. - Start building — every object below works the same way.
# List your 50 most recent tickets curl "https://us-central1-deliveryapp-a06ac.cloudfunctions.net/apiGateway/v1/tickets" \ -H "Authorization: Bearer bsk_live_your_key_here" \ -H "Content-Type: application/json"
import requests BASE = "https://us-central1-deliveryapp-a06ac.cloudfunctions.net/apiGateway/v1" HEADERS = {"Authorization": "Bearer bsk_live_your_key_here"} r = requests.get(f"{BASE}/tickets", headers=HEADERS, params={"limit": 50}) r.raise_for_status() for t in r.json()["data"]: print(t["id"], t.get("title"))
const BASE = "https://us-central1-deliveryapp-a06ac.cloudfunctions.net/apiGateway/v1"; const res = await fetch(`${BASE}/tickets?limit=50`, { headers: { Authorization: "Bearer bsk_live_your_key_here" } }); const { data } = await res.json(); data.forEach(t => console.log(t.id, t.title));
🔐 Authentication
Bearer API keys, hashed at rest, shown once, revocable — with per-key object and read/write scoping.
Learn more →📄 Pagination
Offset pagination with limit/offset, plus updatedSince and field-equality filters on any object.
🪝 Webhooks
HMAC-SHA256-signed deliveries on ticket, invoice and deal creation, with automatic retries.
Learn more →✦ Ask Brio
Stuck? The AI docs assistant answers questions and writes snippets against this exact API — bottom-right of this page.
Ask a question →Authentication
Every request is authenticated with an API key in the Authorization header:
Authorization: Bearer bsk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
How keys work:
- Keys are generated by a company admin in Settings → Integrations and belong to your tenant — the API only ever returns data carrying your company's ID. Cross-tenant reads are impossible by construction.
- The plaintext key is returned once at creation. BrioSync stores only a SHA-256 hash plus a display prefix — we cannot recover a lost key; revoke and re-issue instead.
- Every key records
lastUsedAt, and creation/revocation is written to your tenant's audit log.
Key scopes
Scoping happens at key level, twice over:
| Scope type | Options | Behaviour |
|---|---|---|
| Access scope | read or read + write | Read-only keys get 403 on any POST/PATCH. Grant write only to keys that need it. |
| Object scope | All objects (*) or an explicit subset | A key scoped to tickets, invoices gets 403 when it touches anything else — least-privilege per integration. |
Recommended pattern: one key per integration, named after it, scoped to exactly the objects it touches.
Requests & formats
The API is plain REST over HTTPS. Three verbs:
| Pattern | Meaning |
|---|---|
GET/v1/<object> | List records (paginated, filterable) |
GET/v1/<object>/<id> | Fetch one record |
POST/v1/<object> | Create (writable objects, write-scoped key) |
PATCH/v1/<object>/<id> | Update allow-listed fields (writable objects) |
JSON by default, XML on request
Responses are JSON unless you ask for XML — built for enterprise stacks that still speak XML (Oracle SOA/OIC, SAP PI/PO, BI Publisher, PL/SQL UTL_HTTP):
- Send
Accept: application/xmlto receive XML responses. - Send
Content-Type: application/xmlto submit an XML request body onPOST/PATCH.
# Same endpoint, XML in and out — no separate SOAP stack needed curl "https://us-central1-deliveryapp-a06ac.cloudfunctions.net/apiGateway/v1/tickets" \ -H "Authorization: Bearer bsk_live_your_key_here" \ -H "Accept: application/xml"
Pagination & filtering
List endpoints use offset pagination and return a consistent envelope:
{
"object": "tickets",
"count": 50, // records in this page
"total": 1240, // records matching the query
"limit": 50,
"offset": 0,
"hasMore": true,
"data": [ { "id": "…" } ]
}| Parameter | Type | Behaviour |
|---|---|---|
limit | integer | Page size. Default 50, maximum 100. |
offset | integer | Records to skip. Walk pages until hasMore is false. |
updatedSince | ISO 8601 date-time | Only records created/updated at or after this instant — the building block for incremental syncs. |
| any field name | string | Any other query parameter becomes a case-insensitive equality filter on that field, e.g. ?status=Delayed or ?stage=Backlog&priority=high. |
# Incremental sync: everything that changed since last night, high priority only curl "https://…/apiGateway/v1/tickets?updatedSince=2026-07-01T00:00:00Z&priority=high&limit=100" \ -H "Authorization: Bearer bsk_live_your_key_here"
Errors
Standard HTTP status codes with a JSON body: { "error": "human-readable message" }. Error messages tell you exactly what to fix — including which fields or objects are allowed.
| Status | When |
|---|---|
400 | Bad request — e.g. no valid fields in a create/update body, or PATCH without an id. The message lists the allowed fields. |
401 | Missing, invalid or revoked API key. |
403 | Key lacks write scope, or the object is outside the key's object scope. |
404 | Unknown object, record not found, or record belongs to another tenant (indistinguishable by design). |
405 | Verb other than GET / POST / PATCH. |
500 | Something went wrong on our side — safe to retry with backoff. |
Fair use & limits
List responses are capped at 100 records per page. Beyond that, the API runs under fair-use limits sized for typical sync and automation workloads; sustained high-volume patterns (and dedicated allowances) are scoped with your quote. Design integrations to be incremental — updatedSince beats re-pulling full datasets, for you and for us.
Objects
16 objects are readable today, spanning the suites — with create/update (WRITE) enabled on the intake objects integrations most commonly push into. The writable surface expands release by release; the live OpenAPI spec is always the source of truth.
| Object | Suite | Endpoints |
|---|---|---|
ticketsWRITE | ITSM / Service desk | List, get, create, update |
leadsWRITE | CRM & CX | Create, update (intake object) |
contactsWRITE | CRM & CX | List, get, create, update |
dealsWRITE | CRM & CX | List, get, create, update |
customersREAD | CRM & CX | List, get |
projectsREAD | PSA / Delivery | List, get |
tasksREAD | PSA / Delivery | List, get |
timesheetsREAD | PSA / Delivery | List, get |
peopleREAD | HR | List, get |
quotesREAD | Quote-to-Cash | List, get |
ordersREAD | Quote-to-Cash | List, get |
productsREAD | Quote-to-Cash | List, get |
invoicesREAD | Finance — AR | List, get |
billsREAD | Finance — AP | List, get |
journalsREAD | Finance — GL | List, get |
suppliersREAD | Procurement | List, get |
purchaseordersREAD | Procurement | List, get |
Reading data
Single records return a data envelope:
# GET /v1/invoices/inv_8f2k… { "data": { "id": "inv_8f2k…", "companyId": "…", // always your tenant /* full record fields */ } }
A 404 means the record doesn't exist or isn't yours — the API never confirms the existence of another tenant's data.
Writing data
Writable objects accept POST (create) and PATCH (update) with an allow-listed field set — unknown fields are ignored, so a misconfigured client can't corrupt records. Requires a write-scoped key.
| Object | Accepted fields | Defaults applied |
|---|---|---|
tickets | title, description, type, priority, client, externalTicketId | status: On-track, stage: Backlog, type: Incident, priority: normal |
leads | name, email, phone, company, source, notes, value | status: new |
contacts | name, email, phone, title, customerId | — |
deals | title, value, stage, accountId, source | stage: new |
# Create a ticket from your monitoring tool curl -X POST "https://…/apiGateway/v1/tickets" \ -H "Authorization: Bearer bsk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{ "title": "Checkout latency above SLO", "description": "p95 > 1200ms for 15 min (alert #4812)", "type": "Incident", "priority": "high", "externalTicketId": "PD-4812" }' # → 201 { "id": "…", "object": "tickets", "data": { … } }
# Push website leads into the CRM requests.post(f"{BASE}/leads", headers=HEADERS, json={ "name": "Fatima Al Mansouri", "email": "fatima@example.ae", "company": "Example Contracting LLC", "source": "website-form", }) # Move a deal stage requests.patch(f"{BASE}/deals/deal_123", headers=HEADERS, json={"stage": "negotiation"})
# Same create, from an XML-speaking stack (Oracle OIC, SAP PI/PO…) curl -X POST "https://…/apiGateway/v1/tickets" \ -H "Authorization: Bearer bsk_live_your_key_here" \ -H "Content-Type: application/xml" \ -H "Accept: application/xml" \ -d '<ticket> <title>Checkout latency above SLO</title> <priority>high</priority> </ticket>'
Every API-created record is stamped source: "api", so you can always tell integration-created data apart inside BrioSync.
Webhooks
Push, not poll: register HTTPS endpoints in Settings → Integrations and BrioSync delivers events as they happen.
| Event | Fires when |
|---|---|
ticket.created | A ticket is created — by a user, the customer portal, or the API |
invoice.created | An invoice is raised |
deal.created | A deal enters the pipeline |
Verify every delivery
Each delivery is signed with HMAC-SHA256 over the raw body, using your webhook's secret, in the X-BrioSync-Signature header. Reject anything that doesn't verify:
// Node.js — verify a BrioSync webhook const crypto = require("crypto"); function verify(rawBody, signatureHeader, secret) { const expected = crypto.createHmac("sha256", secret) .update(rawBody).digest("hex"); return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signatureHeader || "")); }
Failed deliveries are retried automatically (a scheduled retry sweep runs every few minutes), and delivery health is monitored — inside BrioSync, the AI can diagnose a failing endpoint and tell you what's wrong in plain language.
2xx quickly and process asynchronously — slow endpoints are what retries are for, but you'll get cleaner ordering by acknowledging immediately.OpenAPI spec
The gateway publishes a live OpenAPI 3.0 document generated from the actual resource map — it can't drift from reality. No auth required:
GET https://us-central1-deliveryapp-a06ac.cloudfunctions.net/apiGateway/openapi.json
Import it into Postman, Insomnia, Oracle OIC, or any client generator to get typed clients and a ready-made collection for every object and verb above.
AI-built integrations
Don't write the integration. Describe it.
Inside BrioSync, tell the AI integration assistant what you want in plain language — "push our website leads into BrioSync", "create a ticket when our monitoring fires", "sync new invoices to our warehouse nightly" — and it produces a concrete plan plus ready-to-run code, grounded in this exact API surface so it never invents an endpoint.
The same AI watches your live integrations: it monitors webhook delivery health on a schedule, diagnoses failures, and explains the fix. And right here on this page, Ask Brio answers your API questions and writes snippets — try it from the button below.
Static connector marketplaces list what someone else built. BrioSync's approach: if it has an API, Brio can wire it — and the integration request form puts anything bespoke on our radar.
Base URL
| Environment | URL |
|---|---|
| Production | https://us-central1-deliveryapp-a06ac.cloudfunctions.net/apiGateway/v1 |
All requests use HTTPS. The API accepts and returns JSON by default, XML by content negotiation. Sandbox tenants (via the guided sandbox) can use the API with their own keys — same surface, isolated data.
Need help?
- Ask Brio — the AI docs assistant on this page answers API questions instantly (bottom-right).
- Docs & product help — documentation and help & support.
- Integration requests — need a connector we haven't wired yet? Tell us here.
- Everything else — hello@briosync.com with subject "API"; an engineer (usually the founder) answers.