API & Webhooks

A plain REST API and signed outbound webhooks for connecting Orbinly to your own tools — or to no-code platforms like Zapier and Make without writing any code at all.

Available on the Starter plan and above. Generate a key from Settings → Developer in your dashboard.

Authentication

Every request is authenticated with a bearer token in the Authorization header. A key represents your whole agency — every resource it touches is automatically scoped to that agency. Keys are shown once, at creation, and can be revoked and regenerated anytime.

Authorization: Bearer ob_live_xxxxxxxxxxxxxxxxxxxxxxxx

Pagination & errors

List endpoints accept ?limit= (max 100, default 50) and ?offset=, and return results newest-first — that ordering makes them usable as Zapier/Make polling triggers out of the box, with no extra "since" parameter needed.

{ "data": [ ... ], "total": 142 }

Errors return a matching HTTP status with a plain message:

{ "error": "client_id not found for this agency" }

Clients

The companies or individuals an agency works with.

GET/api/v1/clientsList clients, newest first
POST/api/v1/clientsCreate a client
GET/api/v1/clients/:idRetrieve a client
PATCH/api/v1/clients/:idUpdate a client

Fields

iduuid
namestring
emailstring
companystring | null
phonestring | null
avatar_urlstring | null
addressstring | null
portal_access_enabledboolean
created_attimestamp
updated_attimestamp

Create a client

curl https://orbinly.com/api/v1/clients \
  -H "Authorization: Bearer ob_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Inc.",
    "email": "hello@acme.com",
    "company": "Acme Inc."
  }'

Projects

A project belongs to one client.

GET/api/v1/projectsList projects — filter with ?client_id=
POST/api/v1/projectsCreate a project
GET/api/v1/projects/:idRetrieve a project
PATCH/api/v1/projects/:idUpdate a project

Fields

iduuid
client_iduuid
namestring
descriptionstring | null
status"active" | "paused" | "completed" | "archived"
colorstring | nullhex, e.g. #4f46e5
due_datetimestamp | null
completed_attimestamp | null
created_attimestamp
updated_attimestamp

Create a project

curl https://orbinly.com/api/v1/projects \
  -H "Authorization: Bearer ob_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Website redesign",
    "client_id": "3c1a...-uuid",
    "status": "active"
  }'

Tasks

A task belongs to one project. Internal-only tasks are never exposed through the API.

GET/api/v1/tasksList tasks — filter with ?project_id=
POST/api/v1/tasksCreate a task
GET/api/v1/tasks/:idRetrieve a task
PATCH/api/v1/tasks/:idUpdate a task

Fields

iduuid
project_iduuid
parent_iduuid | null
titlestring
descriptionstring | null
status"todo" | "in_progress" | "in_review" | "done" | "canceled"
priority"low" | "medium" | "high" | "urgent"
positionnumber
due_datetimestamp | null
completed_attimestamp | null
created_attimestamp
updated_attimestamp

Create a task

curl https://orbinly.com/api/v1/tasks \
  -H "Authorization: Bearer ob_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Design homepage hero",
    "project_id": "9b2e...-uuid",
    "priority": "high"
  }'

Invoices

Invoices always belong to a client, and optionally a project. Line items are required on create.

GET/api/v1/invoicesList invoices — filter with ?client_id= or ?status=
POST/api/v1/invoicesCreate an invoice (starts as draft)
GET/api/v1/invoices/:idRetrieve an invoice
PATCH/api/v1/invoices/:idUpdate an invoice

Fields

iduuid
client_iduuid
project_iduuid | null
invoice_numberstring
status"draft" | "sent" | "viewed" | "paid" | "overdue" | "void"
currencystring3-letter code, e.g. USD
subtotalintegercents
tax_ratenumber0–1
tax_amountintegercents
total_amountintegercents
due_datetimestamp
sent_at / viewed_at / paid_at / void_attimestamp | null
notesstring | null

Create a invoice

curl https://orbinly.com/api/v1/invoices \
  -H "Authorization: Bearer ob_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "3c1a...-uuid",
    "due_date": "2026-10-15T00:00:00Z",
    "line_items": [
      { "description": "Design work", "quantity": 1, "unit_amount": 150000 }
    ]
  }'

Webhooks

Add an endpoint URL and pick events from Settings → Developer and Orbinly will POST a JSON payload to it in real time as those events happen — no polling required. Failed deliveries are retried automatically for up to 5 attempts.

Event types

client.createdA new client was added
project.createdA new project was created
project.status_changedA project moved to a new status
invoice.createdA new invoice was created (usually as a draft)
invoice.paidAn invoice was paid in full
invoice.overdueAn invoice passed its due date unpaid
proposal.acceptedA client accepted a proposal
proposal.rejectedA client rejected a proposal
contract.acceptedA client signed a contract
contract.rejectedA client declined a contract

Payload shape

{
    "type": "invoice.paid",
    "created_at": "2026-09-16T14:03:00.000Z",
    "data": {
      "id": "0f2c...-uuid",
      "invoice_number": "INV-202609-4821",
      "total_amount": 150000,
      "currency": "USD"
    }
  }

Verifying the signature

Every delivery includes an X-Orbinly-Signature header — an HMAC-SHA256 of the raw request body, signed with the endpoint's own secret (shown once, when you create the endpoint). Recompute it and compare before trusting a payload:

const expected = "sha256=" + crypto
    .createHmac("sha256", endpointSecret)
    .update(rawRequestBody)
    .digest("hex");

  // compare to the X-Orbinly-Signature header

Embedded apps

From Admin → Integrations, an agency can embed any tool with its own web page — a booking widget, a dashboard, a form — directly in the client portal via iframe. One URL per tool, shown to every client of that agency. Orbinly appends a short-lived, signed context to the URL so your tool's own backend can verify which agency, client, and contact is viewing.

Agencies can also pick ready-made tools from a gallery — Calendly, Cal.com, Google Calendar, HubSpot Meetings, Typeform, Jotform, Google Forms, YouTube, Vimeo, Loom and Airtable. Those can't use a signed context, so they are added with “Tell this tool who is viewing it” switched off and receive the plain URL with no client details. A custom tool you build keeps it on unless the agency turns it off.

Query parameters appended to your URL

orbinly_ctxBase64url-encoded JSON payload — agency/client/contact identity plus iat/exp
orbinly_sigsha256=<hex> — HMAC-SHA256 of the orbinly_ctx value, same convention as webhook signatures

Decoded payload shape

{
    "agencyId": "…-uuid", "agencySlug": "acme",
    "clientId": "…-uuid", "clientName": "Acme Corp",
    "contactId": "…-uuid", "contactName": "Jane Smith", "contactEmail": "jane@acme.com",
    "iat": 1758000000, "exp": 1758000300
  }

Verifying the signature

Same recipe as webhooks — recompute the HMAC over the raw orbinly_ctx value using the signing secret shown once when the integration was added, and compare:

const expected = "sha256=" + crypto
    .createHmac("sha256", integrationSecret)
    .update(orbinlyCtx)
    .digest("hex");

  // compare to orbinly_sig, then check payload.exp hasn't passed

This token travels in a URL, so treat it as something that will end up in your own server logs and possibly your own outbound referrers — it isn't a secret channel. Verify it once on load, then mint your own session rather than re-trusting the URL on every subsequent request.

Connect to Zapier

There's no published Orbinly app in the Zapier directory yet — but because Orbinly is a plain, documented REST API with real webhooks, you can wire up a working Zap today with Zapier's own built-in tools. No code required.

Trigger on an Orbinly event (e.g. "when an invoice is paid")

  1. Create a Zap and choose Webhooks by Zapier → Catch Hook as the trigger.
  2. Copy the custom webhook URL Zapier gives you.
  3. In Orbinly, go to Settings → Developer → Webhooks, add that URL as an endpoint, and check the events you want (e.g. invoice.paid).
  4. Trigger a real event in Orbinly once to let Zapier capture a sample payload, then build the rest of your Zap from its fields.

Take an action in Orbinly (e.g. "create a client")

  1. Add an action step and choose Webhooks by Zapier → POST.
  2. Set the URL to the endpoint you need, e.g. https://orbinly.com/api/v1/clients.
  3. Under Headers, add Authorization: Bearer ob_live_... with your API key from Settings → Developer.
  4. Set the payload type to JSON and map in the fields from earlier steps in your Zap.

Connect to Make

Same idea in Make (formerly Integromat) — no published Orbinly app yet, but its generic HTTP and Webhooks modules cover everything above.

  1. To trigger on an Orbinly event: add a Webhooks module, create a new webhook, copy its URL into Orbinly's Developer settings as an endpoint, and select the events you want.
  2. To take an action in Orbinly: add an HTTP → Make a request module, point it at the endpoint you need (e.g. POST /api/v1/tasks), and add an Authorization: Bearer ob_live_... header with your key.

Questions, or want an endpoint that isn't here yet? Get in touch.