Skip to content
Docs

API reference

Everything the BrytIO REST API does: how to sign requests, every endpoint with its parameters and fields, and the answers you can get back. Setting up? Start with the docs, or ask us.

Download the OpenAPI file to generate a client or import the API into your own tools.

The BrytIO REST API reads and writes the records of one BrytIO workspace: contacts, companies, deals, quotes, invoices, activities, shipments, tags, email sequences and automations. Requests and responses are JSON over HTTPS, at the base URL below.

https://brytio.com/api/v1

Authentication

Every request carries an API key as a bearer token:

Authorization: Bearer <your API key>

An owner or admin creates keys in Settings > Developers. BrytIO shows a new key once and keeps only a hash of it, so copy the key when it is shown. A key belongs to one workspace and reads and writes only that workspace's records: an id from another workspace answers 404, as a missing one does.

The API and webhooks are included with the Team and Enterprise plans. On another plan every request is refused with 403 and "code": "plan_paused": nothing is changed, and the keys work again after an upgrade.

Scopes

A key has one of two kinds of access, chosen when it is created:

  • Read and write (scopes read and write): every endpoint.
  • Read only (scope read): every GET. A POST, PATCH or DELETE answers 403.

GET /me returns the key's workspace and scopes, which makes it a good first call.

Requests and responses

Send a body as JSON with Content-Type: application/json. One record comes back as {"data": {...}}, and a list as {"data": [...], "count": 25, "nextCursor": "..."}, where count is the number of records on that page.

Dates and times are ISO 8601, in UTC. A date with no time of day (an invoice's dueDate, a quote's expiresAt, a deal's expectedClose) is stored as that date at midnight UTC: send 2026-11-30, or a date and time, which is read as the date it falls on in the workspace's time zone.

Responses can carry more fields than this reference lists. Build on the fields listed here: they are the ones BrytIO keeps.

Pagination

Contacts, companies, deals, quotes, invoices, activities and shipments come back a page at a time. limit sets the page size, from 1 to 200 (50 when left out; a number outside that range is taken as the nearest end). When a page is full, nextCursor is set: send it back as cursor for the next page. On the last page nextCursor is null.

Pages are newest first (deals: most recently updated first), unless you ask for changes with updated_since.

Tags, email sequences and automations come back whole, in one response.

Changed since

To keep another system in step, ask a list for what changed since your last sync with updated_since: an ISO 8601 date and time with a time zone, such as 2026-10-01T00:00:00Z or 2026-10-01T00:00:00-05:00. In a URL, write the + of an offset as %2B. A value without a time zone, or one that isn't a date and time, answers 400.

  • The list holds the records whose updatedAt is at or after that time, oldest change first (by updatedAt, then by id).
  • Page through it with nextCursor, as above. The cursor records exactly where the page ended, so records that share a time are never skipped or repeated from one page to the next. It works only together with updated_since, and only on the list that gave it.
  • A record changed while you page moves to the end of the list and comes back there, with its new values.
  • Start your next sync from the latest updatedAt you received. Records changed at exactly that time come back again, so match records by id. A change that was still being saved while you read can carry a slightly earlier time: if you can't afford to miss one, start a minute earlier.
  • Deletions are not reported: a deleted record stops appearing, and nothing says it was deleted. Webhooks send the delete events.
  • Some changes don't move updatedAt, so updated_since doesn't return them. BrytIO keeps a contact's or company's score, a contact's lastContactedAt and a company's logoUrl up to date in the background. An automation's Update field action that sets a deal's title, value, probability, lineOfBusiness or notes leaves the deal's updatedAt as it was, so the deal doesn't look recently worked. To catch these, read the record itself, or the whole list now and then.

updated_since works on contacts, companies, deals, quotes, invoices, activities, shipments, email sequences and automations. Tags have no change time: read the whole list.

Rate limits

Each API key can make up to 120 requests a minute. All of a workspace's keys together can make up to 600 a minute, so more keys don't add more than that. An endpoint's answers carry three headers:

  • X-RateLimit-Limit: the requests a key may make in a minute. On an answer to a request that failed authentication, it is the failures its address may make instead.
  • X-RateLimit-Remaining: how many more the key (or the address) can make in the current minute. When the workspace's keys together are nearer their 600, it is what is left of those.
  • X-RateLimit-Reset: when the current minute ends, in Unix time (seconds).

Over a limit, a request answers 429 with a Retry-After header: wait that many seconds, then send it again.

Three answers come without these headers: 405 for a method an endpoint doesn't have, the automatic answer to an OPTIONS request, and an unexpected server error (500).

Requests that fail authentication (no key, or a key that is unknown or revoked) are limited by network address: 120 a minute from one address, and 120 a minute from all the addresses of one IPv6 network (a /64). Past that, until the minute is up, a request that fails authentication answers 429 instead of 401, and the address that sent the failures is refused whatever key it sends. A valid key sent from another address is not affected. So a key that has stopped working should not be retried in a loop.

Errors

An error answers with a JSON body whose error says in a sentence what went wrong, such as {"error": "firstName is required"}. A few errors also carry a code.

  • 400: the request isn't valid (a field missing, of the wrong kind or out of range, or a parameter that isn't one). Nothing was changed.
  • 401: no API key was sent, or the key is unknown or revoked.
  • 402: the workspace's subscription is inactive, or it reached a limit of its plan (for example its number of contacts or invoices).
  • 403: the key has no write scope, the plan doesn't include the feature, or code is plan_paused: the plan doesn't include the API.
  • 404: no record with that id in your workspace.
  • 409: the request is valid, but the record's state refuses it (an accepted quote, a sent invoice), or the record changed while the request ran. Read it again and retry.
  • 429: too many requests (see Rate limits).

Webhooks

BrytIO can also send your systems an HTTP POST when something changes, such as a deal won or an invoice paid. An owner or admin sets webhooks up in Settings > Developers.

Read about webhooks in the docs.

Auth

Connection test and token inspection.

The org summary object

  • idstring
  • namestring
  • planstring

Check a key and see its scopes

GET/api/v1/me

Returns the key's workspace and scopes. A good first call when you connect a tool.

Responses

Can also answer 401, as described under Errors.

Contacts

CRM contacts with custom fields and tags.

The contact object

  • idstring
  • organizationIdstring
  • typeone of LEAD, CUSTOMER, VENDOR
  • firstNamestring
  • lastNamestring, or null
  • emailstring, or null
  • phonestring, or null
  • titlestring, or null

    Job title.

  • notesstring, or null
  • companyIdstring, or null
  • companyobject, or null

    The company's id and name, on a list, a get and an update.

  • company.idstring
  • company.namestring
  • ownerIdstring, or null

    The member who owns the contact (a user id).

  • customFieldsobject, or null

    Your own key and value pairs, set through the API.

  • emailOptOutboolean

    The contact unsubscribed, so blasts and sequences skip them.

  • scoreinteger, or null

    The lead score BrytIO works out. Changes without moving updatedAt.

  • lastContactedAtdate and time, or null

    The latest call, meeting or email with the contact. Can change without moving updatedAt.

  • createdAtdate and time
  • updatedAtdate and time

List contacts

GET/api/v1/contacts

Newest first, or oldest change first with updated_since.

Parameters

  • limitintegerquery

    How many records a page holds, from 1 to 200 (50 when left out).

  • cursorstringquery

    The nextCursor of the page before. With updated_since, only a cursor from a list read with updated_since works.

  • updated_sincedate and timequery

    Only records changed at or after this time, oldest change first (by updatedAt, then id). An ISO 8601 date and time with a time zone, such as 2026-10-01T00:00:00Z; anything else answers 400. Deleted records are not reported.

  • qstringquery

    Search. Every word must match the contact's first name, last name, email or company name (any case, any part of the word).

Responses

Can also answer 400 and 401, as described under Errors.

Create a contact

POST/api/v1/contacts

A new contact starts as a lead. Sends the contact.created webhook and runs its automations.

Request body

  • firstNamestringrequired
  • lastNamestring
  • emailemail address
  • phonestring
  • titlestring

    Job title.

  • companyIdstring, or null

    The company to link. Leave the key out to link the contact to the one company in your workspace whose domain is the email's domain (only when exactly one company has it; never for personal or internet-provider mail such as gmail.com or att.net, nor for x.onmicrosoft.com). Send null to create the contact with no company.

  • ownerIdstring, or null

    The member who owns the contact (a user id of this workspace; 400 otherwise).

  • customFieldsobject

    Your own key and value pairs. Keys must match /^[a-zA-Z][a-zA-Z0-9_.-]{0,62}$/. Values can be a string, a number, true, false or null.

Responses

Can also answer 400, 401 and 403, as described under Errors.

Get a contact

GET/api/v1/contacts/{id}

Parameters

  • idstringin the pathrequired

    The record's id.

Responses

Can also answer 401 and 404, as described under Errors.

Update a contact

PATCH/api/v1/contacts/{id}

Only the fields sent change. Sends the contact.updated webhook and runs its automations.

customFields is merged into the stored fields:

  • A key with a value sets or replaces it.
  • A key with null removes it.
  • A key left out stays as it is.
  • customFields sent as null removes them all.

Parameters

  • idstringin the pathrequired

    The record's id.

Request body

  • firstNamestring
  • lastNamestring, or null
  • emailstring, or null
  • phonestring, or null
  • titlestring, or null
  • notesstring, or null
  • typeone of LEAD, CUSTOMER, VENDOR
  • companyIdstring, or null
  • ownerIdstring, or null

    The member who owns the contact (a user id of this workspace), or null for none. Sending the owner the contact already has is always accepted.

  • customFieldsobject, or null

    Merged into the stored fields: a key with a value sets it, a key with null removes it, and a key left out stays. Send null for the whole object to remove them all.

Responses

Can also answer 400, 401, 403 and 404, as described under Errors.

Delete a contact

DELETE/api/v1/contacts/{id}

Also deletes the files attached to the contact. A file that is also attached to another record stays on that record. Sends the contact.deleted webhook.

Parameters

  • idstringin the pathrequired

    The record's id.

Responses

  • 200

    Resource deleted

    • dataobject
    • data.idstring
    • data.deletedboolean

Can also answer 401, 403 and 404, as described under Errors.

List a contact's tags

GET/api/v1/contacts/{id}/tags

Parameters

  • idstringin the pathrequired

    The record's id.

Responses

Can also answer 401 and 404, as described under Errors.

Tag a contact

POST/api/v1/contacts/{id}/tags

Send id to attach an existing tag, or name to attach the tag with that name, which is created when the workspace has none. Attaching a tag the contact already has changes nothing.

Parameters

  • idstringin the pathrequired

    The record's id.

Request body

Send either id (an existing tag) or name.

  • idstring

    An existing tag of this workspace.

  • namestring

    The tag with this name, created when the workspace has none.

  • colorstring

    The color of a tag created by name, such as #0ea5e9.

Responses

  • 201

    Tag attached

Can also answer 400, 401, 403 and 404, as described under Errors.

Remove a tag from a contact

DELETE/api/v1/contacts/{id}/tags

The tag itself stays in the workspace.

Parameters

  • idstringin the pathrequired

    The record's id.

  • tagIdstringqueryrequired

    The id of the tag to remove.

Responses

  • 200

    Tag removed

    • dataobject
    • data.contactIdstring
    • data.tagIdstring
    • data.detachedboolean

Can also answer 400, 401, 403 and 404, as described under Errors.

Companies

Company accounts with address and industry data.

The company object

  • idstring
  • organizationIdstring
  • namestring
  • websitestring, or null
  • domainstring, or nullread only

    The website's domain, worked out from website.

  • logoUrlURL, or nullread only

    The company's logo, when BrytIO found or was given one. A logo BrytIO finds in the background doesn't move updatedAt.

  • industrystring, or null
  • sizestring, or null
  • phonestring, or null
  • addressLine1string, or null
  • addressLine2string, or null
  • citystring, or null
  • statestring, or null
  • postalCodestring, or null
  • countrystring, or null
  • notesstring, or null
  • billingEmailemail address, or null

    AP mailbox the company's invoices go to; wins over the billing contact's email.

  • billingContactIdstring, or null

    The contact (one of this company's) its invoices are addressed to.

  • portalCompanyAccessbooleanread only

    Company-wide customer portal access. When true, the addresses in portalAccessEmails that still qualify (the billing email, the billing contact, or a contact marked CUSTOMER) can each see all of the invoices, quotes and contracts issued to the company (their companyId) and its statement in the customer portal. A colleague's quote or contract is read-only for them; only the person it was sent to can accept or sign it. Set by an owner or admin on the company page; not settable through the API.

  • portalAccessEmailsstringread only

    JSON array (as a string) of the lowercased addresses an owner or admin approved for company-wide portal access. Someone who newly qualifies (for example a new CUSTOMER contact or a changed billingEmail) is not added automatically; they wait on the company page for approval. Not settable through the API.

  • scoreinteger, or null

    The company's lead score. Changes without moving updatedAt.

  • createdAtdate and time
  • updatedAtdate and time

List companies

GET/api/v1/companies

Newest first, or oldest change first with updated_since.

Parameters

  • limitintegerquery

    How many records a page holds, from 1 to 200 (50 when left out).

  • cursorstringquery

    The nextCursor of the page before. With updated_since, only a cursor from a list read with updated_since works.

  • updated_sincedate and timequery

    Only records changed at or after this time, oldest change first (by updatedAt, then id). An ISO 8601 date and time with a time zone, such as 2026-10-01T00:00:00Z; anything else answers 400. Deleted records are not reported.

  • qstringquery

    Search. Every word must match the company's name, website or domain (any case, any part of the word).

Responses

Can also answer 400 and 401, as described under Errors.

Create a company

POST/api/v1/companies

Sends the company.created webhook and runs its automations.

Request body

  • namestringrequired
  • websitestring
  • industrystring
  • phonestring
  • addressLine1string
  • addressLine2string
  • citystring
  • statestring
  • postalCodestring
  • countrystring
  • billingEmailemail address
  • billingContactIdstring, or null

    Leave it out. A company being created has no contacts yet, so a billing contact answers 400: set it with an update once the contact is linked.

Responses

  • 201

    Company created

    • datacompany object
    • linkedContactsinteger

      Contacts with no company whose email is at this company's website domain, linked to it now (only when it is the one company in the workspace with that domain; personal and internet-provider mail never links, and a website that is a page on a shared platform, such as facebook.com/yourpage or linkedin.com/company/yours, gives the company no domain).

Can also answer 400, 401 and 403, as described under Errors.

Get a company

GET/api/v1/companies/{id}

Parameters

  • idstringin the pathrequired

    The record's id.

Responses

Can also answer 401 and 404, as described under Errors.

Update a company

PATCH/api/v1/companies/{id}

Only the fields sent change. Sends the company.updated webhook and runs its automations.

Parameters

  • idstringin the pathrequired

    The record's id.

Request body

  • namestring
  • websitestring, or null
  • industrystring, or null
  • sizestring, or null
  • phonestring, or null
  • addressLine1string, or null
  • addressLine2string, or null
  • citystring, or null
  • statestring, or null
  • postalCodestring, or null
  • countrystring, or null
  • notesstring, or null
  • billingEmailemail address, or null
  • billingContactIdstring, or null

    Must be a contact of this company (400 otherwise). null clears it.

Responses

  • 200

    Company updated

    • datacompany object
    • linkedContactsinteger

      When the website moved to a new domain: contacts with no company at that domain, linked to this company now (only when it is the one company with that domain). 0 otherwise.

Can also answer 400, 401, 403 and 404, as described under Errors.

Delete a company

DELETE/api/v1/companies/{id}

Contacts and deals at the company are unlinked and kept. Files attached to the company itself are deleted; files on its contacts and deals stay with them, and a file also attached to another record stays on that record. Sends the company.deleted webhook.

Parameters

  • idstringin the pathrequired

    The record's id.

Responses

  • 200

    Resource deleted

    • dataobject
    • data.idstring
    • data.deletedboolean

Can also answer 401, 403 and 404, as described under Errors.

List a company's tags

GET/api/v1/companies/{id}/tags

Parameters

  • idstringin the pathrequired

    The record's id.

Responses

Can also answer 401 and 404, as described under Errors.

Tag a company

POST/api/v1/companies/{id}/tags

Send id to attach an existing tag, or name to attach the tag with that name, which is created when the workspace has none. Attaching a tag the company already has changes nothing.

Parameters

  • idstringin the pathrequired

    The record's id.

Request body

Send either id (an existing tag) or name.

  • idstring

    An existing tag of this workspace.

  • namestring

    The tag with this name, created when the workspace has none.

  • colorstring

    The color of a tag created by name, such as #0ea5e9.

Responses

  • 201

    Tag attached

Can also answer 400, 401, 403 and 404, as described under Errors.

Remove a tag from a company

DELETE/api/v1/companies/{id}/tags

The tag itself stays in the workspace.

Parameters

  • idstringin the pathrequired

    The record's id.

  • tagIdstringqueryrequired

    The id of the tag to remove.

Responses

  • 200

    Tag removed

    • dataobject
    • data.companyIdstring
    • data.tagIdstring
    • data.detachedboolean

Can also answer 400, 401, 403 and 404, as described under Errors.

Deals

Sales pipeline deals, on the default board or a custom one.

The deal object

  • idstring
  • organizationIdstring
  • pipelineIdstring, or null

    The board the deal is on, or null for the default board.

  • titlestring
  • valuenumber
  • stageone of LEAD, QUALIFIED, PROPOSAL, NEGOTIATION, WON, LOST
  • stageKeystring, or null

    The custom stage the deal is in, when its board has custom stages. stage then holds the standard stage at the same position, for integrations that know only the six.

  • probabilitynumber

    0 to 100. WON deals are always 100 and LOST deals always 0: a probability written to a closed deal is replaced by that value.

  • notesstring, or null
  • companyIdstring, or null
  • companyobject, or null

    The company's id and name, on reads and updates.

  • company.idstring
  • company.namestring
  • contactIdstring, or null
  • contactobject, or null

    The contact's id and name, on reads and updates.

  • contact.idstring
  • contact.firstNamestring
  • contact.lastNamestring, or null
  • ownerIdstring, or null

    The member who owns the deal (a user id).

  • expectedClosedate and time, or null
  • closedAtdate and time, or null

    When the deal was won or lost. null while it is open.

  • stageEnteredAtdate and time, or null

    When the deal entered its current stage. Set on create and on every stage change; null on deals that predate the field.

  • closeReasonstring, or null

    Why a WON or LOST deal closed: one of the workspace's reasons (Settings > CRM > Close reasons) or "Other". null on open deals, on deals closed without one, and cleared when a deal is reopened.

  • closeNotestring, or null

    The note given with the close reason. Cleared on reopen.

  • closedFromStagestring, or nullread only

    The open stage key the deal left when it closed (where the app's Reopen puts it back). Server-set.

  • lineOfBusinessstring, or nullread only

    The deal's line of business, for revenue reports.

  • sourceone of manual, rebillread only

    Where the deal came from. "rebill" marks the Won deal vendor-bill ingest creates per customer per distributor bill; everything else is "manual". Server-set: not accepted on create or update.

  • createdAtdate and time
  • updatedAtdate and time

    When the deal last changed. An automation's Update field action that sets title, value, probability, lineOfBusiness or notes doesn't move it (the deal shouldn't look recently worked), so updated_since doesn't return that change.

List deals

GET/api/v1/deals

Most recently updated first, or oldest change first with updated_since.

Parameters

  • limitintegerquery

    How many records a page holds, from 1 to 200 (50 when left out).

  • cursorstringquery

    The nextCursor of the page before. With updated_since, only a cursor from a list read with updated_since works.

  • updated_sincedate and timequery

    Only records changed at or after this time, oldest change first (by updatedAt, then id). An ISO 8601 date and time with a time zone, such as 2026-10-01T00:00:00Z; anything else answers 400. Deleted records are not reported.

  • stagestringquery

    Only deals in this stage: one of LEAD, QUALIFIED, PROPOSAL, NEGOTIATION, WON, LOST, or the key of a custom stage on a board (which matches open deals only).

Responses

Can also answer 400 and 401, as described under Errors.

Create a deal

POST/api/v1/deals

The deal goes on the workspace's default board. Sends the deal.created webhook and runs its automations.

Request body

  • titlestringrequired
  • valuenumber
  • stagestring

    One of LEAD, QUALIFIED, PROPOSAL, NEGOTIATION, WON, LOST, or the key of a custom stage on the default board (400 otherwise).

  • probabilitynumber

    0 to 100, else 400. Left out, the deal takes its stage's default probability (stock board: LEAD 10, QUALIFIED 25, PROPOSAL 50, NEGOTIATION 75; a board can set its own). WON is always 100 and LOST always 0, even when a probability is sent.

  • notesstring
  • companyIdstring
  • contactIdstring
  • ownerIdstring, or null

    The member who owns the deal (a user id of this workspace; 400 otherwise).

  • closeReasonstring, or null

    Optional. Only with a WON or LOST stage (a value with an open stage answers 400; null or "" is ignored). Must be one of the workspace's reasons for that outcome, or "Other" with a closeNote, else 400.

  • closeNotestring, or null

    Optional note with the close reason (WON or LOST only).

Responses

Can also answer 400, 401 and 403, as described under Errors.

Get a deal

GET/api/v1/deals/{id}

Parameters

  • idstringin the pathrequired

    The record's id.

Responses

Can also answer 401 and 404, as described under Errors.

Update a deal

PATCH/api/v1/deals/{id}

Only the fields sent change. Sends the deal.updated webhook, and deal.won or deal.lost when the deal closes.

Parameters

  • idstringin the pathrequired

    The record's id.

Request body

  • titlestring
  • valuenumber
  • stagestring

    One of LEAD, QUALIFIED, PROPOSAL, NEGOTIATION, WON, LOST, or the key of a custom stage on the deal's board (400 otherwise).

  • probabilitynumber

    0 to 100, else 400. A stage change without a probability applies the new stage's default unless the deal's probability was set by hand (0 never counts as set by hand). WON is always 100 and LOST always 0, with or without a stage in the body.

  • notesstring, or null
  • companyIdstring, or null
  • contactIdstring, or null
  • ownerIdstring, or null

    The member who owns the deal (a user id of this workspace), or null for none. Sending the owner the deal already has is always accepted.

  • expectedClosedate, or null

    The date the deal is expected to close (2026-11-30, or a date and time, read as its date in the workspace's time zone).

  • closeReasonstring, or null

    Applies to the stage the deal ends up in, which must be WON or LOST (else 400): with a stage change it is stored with the close; on a deal already closed it edits the stored reason (leave it out to keep it). Must be one of the workspace's reasons for that outcome, or "Other" with a closeNote. A stage change into WON or LOST without one stores no reason; reopening clears it. A body sent back from a GET works: a value equal to the deal's stored one is treated as unchanged, and null or "" is ignored on a deal that ends up open. Only a new value on an open deal is a 400. On a switch between WON and LOST the switch replaces the old close, so a repeated value is stored for the new outcome, except in a copy of the old close, which is ignored (the old outcome's reason and note are not carried over, and the request is not refused): a body sending both closeReason and closeNote equal to the stored pair, as a GET returns them (this includes "Other" and its note), or a stored reason not on the new outcome's list, with a closeNote equal to the stored one. To keep the same reason on the new outcome, send closeReason without closeNote, or with a new closeNote.

  • closeNotestring, or null

    The note with the close reason, under the same rules as closeReason.

Responses

  • 200The deal object

    Deal updated

  • 409

    A stage change in the body lost a race: the deal moved to another stage (or board) after this request read it. Nothing was written. Read the deal again and retry.

Can also answer 400, 401, 403 and 404, as described under Errors.

Delete a deal

DELETE/api/v1/deals/{id}

Also deletes the files attached to the deal. A file that is also attached to another record stays on that record. Sends the deal.deleted webhook.

Parameters

  • idstringin the pathrequired

    The record's id.

Responses

  • 200

    Resource deleted

    • dataobject
    • data.idstring
    • data.deletedboolean

Can also answer 401, 403 and 404, as described under Errors.

Quotes

Customer-facing price quotes with line items and totals.

The quote object

  • idstring
  • numberstring
  • organizationIdstring
  • statusone of DRAFT, SENT, ACCEPTED, DECLINED, EXPIRED
  • issueDatedate and time
  • expiresAtdate and time, or null
  • customerNamestring
  • customerEmailstring, or null
  • customerAddressstring, or null
  • contactIdstring, or null
  • contactobject, or null

    The contact's id, name and email, on a get and an update.

  • contact.idstring
  • contact.firstNamestring
  • contact.lastNamestring, or null
  • contact.emailstring, or null
  • dealIdstring, or null
  • dealobject, or null

    The deal's id, title and stage, on a get and an update.

  • deal.idstring
  • deal.titlestring
  • deal.stageone of LEAD, QUALIFIED, PROPOSAL, NEGOTIATION, WON, LOST
  • companyIdstring, or null

    The company the quote was issued to, recorded when it was created: the companyId sent, else its contact's company, else its deal's. It does not follow the contact to another company later; it changes only when an update sends companyId, re-addresses the quote to another contactId, or (with no contact) moves it to another dealId. Company-wide customer portal access lists quotes by this field, read-only for anyone the quote wasn't sent to.

  • discountTypeone of flat, percent, or null
  • discountValuenumber
  • taxRatenumber

    Percent, 0 to 100.

  • subtotalnumber
  • totalnumber
  • notesstring, or null
  • termsstring, or null
  • paymentTermsstring, or nullread only

    The "Payment Terms" label printed on the quote PDF when terms is blank or longer than one line, stamped from the workspace's due-in days when the quote is created ("Net 30") and never worked out again. null on quotes created before it existed.

  • sentAtdate and time, or null
  • viewedAtdate and time, or null

    When the customer last opened the quote while it awaited a decision.

  • viewCountinteger

    How many times the customer opened it (views within 30 minutes count once).

  • acceptedAtdate and time, or null
  • declinedAtdate and time, or null
  • declineReasonstring, or null
  • signatureNamestring, or null

    The name the customer signed with.

  • signatureTitlestring, or null
  • revisionOfIdstring, or null

    The quote this one revised.

  • revisedByobject, or null

    The newer revision that replaced this quote (its id and number), on a get and an update.

  • revisedBy.idstring
  • revisedBy.numberstring
  • invoiceIdstring, or null

    The invoice made from this quote, if one was.

  • lineItemsarray of line item objects
  • createdAtdate and time
  • updatedAtdate and time

The line item object

  • idstring
  • namestring, or null

    A short product or SKU name.

  • descriptionstring
  • quantitynumber
  • unitPricenumber
  • unitCostnumber

    Your cost, never shown to customers.

  • lineOfBusinessstring, or null

    Your line of business for the line (such as "Microsoft" or "Managed Services"), which revenue by line of business reports on. null means not set.

  • totalnumber

    quantity times unitPrice.

  • positioninteger

    The line's place on the document, from 0.

The line item input object

  • namestring, or null

    A short product or SKU name shown on the document.

  • descriptionstringrequired
  • quantitynumberrequired
  • unitPricenumberrequired
  • unitCostnumber

    Your cost, never shown to customers; used for gross profit. Set by the server on a fee line, whatever is sent: a credit card fee (such as "Credit card processing fee" or "CC surcharge 3%") costs its unitPrice, and a late fee (such as "3% late fee") costs 0.

  • lineOfBusinessstring, or null

    Your line of business for the line, free text (trimmed). null or "" means not set. When an update replaces lineItems, every line is created again: a line that leaves out lineOfBusiness (or name) keeps the stored value of the existing line with the same description; send null to clear it.

List quotes

GET/api/v1/quotes

Newest first, or oldest change first with updated_since. Each quote carries its line items.

Parameters

  • limitintegerquery

    How many records a page holds, from 1 to 200 (50 when left out).

  • cursorstringquery

    The nextCursor of the page before. With updated_since, only a cursor from a list read with updated_since works.

  • updated_sincedate and timequery

    Only records changed at or after this time, oldest change first (by updatedAt, then id). An ISO 8601 date and time with a time zone, such as 2026-10-01T00:00:00Z; anything else answers 400. Deleted records are not reported.

  • statusone of DRAFT, SENT, ACCEPTED, DECLINED, EXPIREDquery

    Only quotes with this status. Any other value is ignored.

Responses

Can also answer 400 and 401, as described under Errors.

Create a quote

POST/api/v1/quotes

The quote starts as a DRAFT and gets the workspace's next quote number. Totals are worked out from the lines, the discount and the tax. Sends the quote.created webhook and runs its automations.

Request body

  • customerNamestringrequired
  • customerEmailstring
  • customerAddressstring
  • contactIdstring
  • dealIdstring
  • companyIdstring

    The company (in this workspace; 400 otherwise) the quote is issued to. Left out, the contact's company, else the deal's.

  • expiresAtdate

    The date the quote expires (2026-11-30, or a date and time, read as its date in the workspace's time zone).

  • discountTypeone of flat, percent
  • discountValuenumber

    An amount, or a percent up to 100 with percent.

  • taxRatenumber

    Percent, 0 to 100.

  • notesstring
  • termsstring
  • lineItemsarray of line item input objectsrequired

Responses

Can also answer 400, 401 and 403, as described under Errors.

Get a quote

GET/api/v1/quotes/{id}

With its line items, its contact and deal, and the revision that replaced it, if any.

Parameters

  • idstringin the pathrequired

    The record's id.

Responses

Can also answer 401 and 404, as described under Errors.

Update a quote

PATCH/api/v1/quotes/{id}

Only the fields sent change. If lineItems is sent, it replaces every line. Totals (subtotal, total) are worked out again whenever lineItems, discountType, discountValue or taxRate change.

A quote the customer accepted or signed, or one replaced by a newer revision, can't be changed: the request answers 409. Revise it in the app instead.

Parameters

  • idstringin the pathrequired

    The record's id.

Request body

  • customerNamestring
  • customerEmailstring, or null
  • customerAddressstring, or null
  • contactIdstring, or null

    Re-address the quote to another contact (the company it is issued to follows that contact's company unless companyId is also sent). null unlinks the contact and keeps the company.

  • dealIdstring, or null
  • companyIdstring, or null

    The company (in this workspace; 400 otherwise) the quote is issued to. null for none.

  • expiresAtdate, or null
  • discountTypeone of flat, percent, or null
  • discountValuenumber
  • taxRatenumber
  • notesstring, or null
  • termsstring, or null
  • lineItemsarray of line item input objects

    When sent, replaces every line.

Responses

  • 200The quote object

    Quote updated

  • 409

    The quote was accepted, signed or revised, so it can't be changed. Nothing was written.

Can also answer 400, 401, 403 and 404, as described under Errors.

Delete a quote

DELETE/api/v1/quotes/{id}

The app's rules apply. A quote the customer accepted or signed is deleted only with confirm set to its number. A version of a revised quote hands its place in the chain to the next version, and the newest version is deleted only while it is a draft that was never sent. Anything else answers 409, with an error that says why.

Parameters

  • idstringin the pathrequired

    The record's id.

  • confirmstringquery

    The quote's number (such as Q-0042). Needed only to delete a quote the customer accepted or signed.

Responses

  • 200

    Resource deleted

    • dataobject
    • data.idstring
    • data.deletedboolean
  • 409

    The quote is kept as it stands; error says why.

Can also answer 401, 403 and 404, as described under Errors.

Change a quote's status

POST/api/v1/quotes/{id}/status

Does what the buttons on the quote page do. Moving a quote into ACCEPTED closes its deal as won (when it has one), makes its contact a customer if the contact was a lead, and sends the quote.accepted webhook. DECLINED stores the declineReason, if one is sent. Sending the status the quote already has changes nothing.

An accepted quote keeps its status, and a quote replaced by a newer revision is never sent or accepted: both answer 409.

Parameters

  • idstringin the pathrequired

    The record's id.

Request body

  • statusone of DRAFT, SENT, ACCEPTED, DECLINED, EXPIREDrequired
  • declineReasonstring, or null

    Why the customer declined. Stored only with DECLINED.

Responses

  • 200The quote object

    Status changed (or already that status)

  • 409

    The quote's state refuses the change; error says why. Nothing was written.

Can also answer 400, 401, 403 and 404, as described under Errors.

Invoices

Invoices, payment recording, and status transitions.

The invoice object

  • idstring
  • numberstring
  • organizationIdstring
  • statusone of DRAFT, SENT, PARTIALLY_PAID, PAID, OVERDUE, VOID
  • issueDatedate and time
  • customerNamestring
  • customerEmailstring, or null
  • customerAddressstring, or null
  • contactIdstring, or null
  • contactobject, or null

    The contact's id, name and email, on a get and an update.

  • contact.idstring
  • contact.firstNamestring
  • contact.lastNamestring, or null
  • contact.emailstring, or null
  • companyIdstring, or null

    The company the invoice was issued to, recorded when it was created: the companyId sent, else its contact's company. It does not follow the contact to another company later; it changes only when an update sends companyId, or re-addresses the invoice to another contactId (setting contactId to null keeps it). Company-wide customer portal access lists invoices by this field.

  • dealIdstring, or null
  • dueDatedate and time
  • discountTypeone of flat, percent, or null
  • discountValuenumber
  • taxRatenumber
  • subtotalnumber
  • totalnumber
  • amountPaidnumber
  • paidAtdate and time, or null
  • sentAtdate and time, or null
  • notesstring, or null
  • termsstring, or null
  • remindersEnabledboolean

    Whether the customer gets payment reminders.

  • promisedPayDatedate and time, or null

    The date the customer promised to pay.

  • promiseNotestring, or null
  • portalUrlURL, or nullread only

    The link to give the customer (added October 2026): the invoice's payment page, where they see the invoice and, when the workspace takes card payments through Stripe, pay it. Its Pay now charges the balance as it is when they click, so a link shared before a partial payment still charges the right amount. null for a DRAFT invoice (the page opens once the invoice is sent) and for a VOID one. Use this field wherever you send, show or store a customer's link to pay or view an invoice. Webhook deliveries that carry an invoice (invoice.created, invoice.paid) include it too.

  • stripePaymentLinkUrlstring, or nullread onlydeprecated

    The Stripe Payment Link BrytIO last created for this invoice (since October 2026, only when a customer chooses Pay now on its payment page), kept so existing integrations don't break. Don't give it to customers: it is usually null now (sending an invoice no longer creates one), and it is replaced when the balance changes. Use portalUrl instead.

  • lineItemsarray of line item objects
  • paymentsarray of payment objects
  • createdAtdate and time
  • updatedAtdate and time

The payment object

  • idstring
  • invoiceIdstring
  • amountnumber
  • methodstring

    How the payment was received. BrytIO writes manual, bank, check, stripe or other, and Marked paid on the record Mark paid makes (placeholder is then true). A payment recorded through the API keeps the method it was sent with, so expect other values too.

  • referencestring, or null
  • placeholderboolean

    True for the record Mark paid makes in the app, which is not money received.

  • paidAtdate and time
  • createdAtdate and time

List invoices

GET/api/v1/invoices

Newest first, or oldest change first with updated_since. Each invoice carries its line items and payments.

Parameters

  • limitintegerquery

    How many records a page holds, from 1 to 200 (50 when left out).

  • cursorstringquery

    The nextCursor of the page before. With updated_since, only a cursor from a list read with updated_since works.

  • updated_sincedate and timequery

    Only records changed at or after this time, oldest change first (by updatedAt, then id). An ISO 8601 date and time with a time zone, such as 2026-10-01T00:00:00Z; anything else answers 400. Deleted records are not reported.

  • statusone of DRAFT, SENT, PARTIALLY_PAID, PAID, OVERDUE, VOIDquery

    Only invoices with this status. Any other value is ignored.

Responses

Can also answer 400 and 401, as described under Errors.

Create an invoice

POST/api/v1/invoices

The invoice starts as a DRAFT and gets the workspace's next invoice number. Totals are worked out from the lines, the discount and the tax. Sends the invoice.created webhook and runs its automations.

A line whose description starts with Prepayment received (invoice answers 400: that credit is added only by applying a paid invoice as a prepayment on the invoice page.

Request body

  • customerNamestringrequired
  • customerEmailstring
  • customerAddressstring
  • contactIdstring
  • companyIdstring

    The company (in this workspace; 400 otherwise) the invoice is issued to: for billing a company with no contact, or naming the company outright. Left out, the contact's company.

  • dueDatedate

    The date the invoice is due (2026-11-30, or a date and time, read as its date in the workspace's time zone). Left out, the window terms states ("Net 45" means 45 days from today), else the workspace's due-in days (Settings > General > Invoicing defaults; 30 unless changed).

  • discountTypeone of flat, percent
  • discountValuenumber

    An amount, or a percent up to 100 with percent.

  • taxRatenumber

    Percent, 0 to 100.

  • notesstring
  • termsstring, or null

    Left out, text matching the due date: the workspace's default terms text ("Net 30" unless changed) when due on the workspace's default window, else "Net N" for the window dueDate gives (or "Due on receipt"). Send "" for none.

  • remindersEnabledboolean

    Customer payment reminders. Defaults to the workspace's "reminders on for new invoices" setting.

  • lineItemsarray of line item input objectsrequired

Responses

Can also answer 400, 401 and 403, as described under Errors.

Get an invoice

GET/api/v1/invoices/{id}

With its line items, payments and contact.

Parameters

  • idstringin the pathrequired

    The record's id.

Responses

Can also answer 401 and 404, as described under Errors.

Update an invoice

PATCH/api/v1/invoices/{id}

Only the fields sent change. If lineItems is sent, it replaces every line, and the totals are worked out again.

Prepayments: send an applied Prepayment received (invoice ...) line back with any price and it is kept exactly as applied; leave it out and the prepayment is removed. A Prepayment received (invoice ...) line for a prepayment that isn't applied to this invoice answers 400. An invoice applied as a prepayment to another invoice keeps its total: lines that change it answer 409.

A request that changes the lines, the discount or the tax answers 409 and changes nothing if the invoice was changed by something else while it was being saved (a payment, a prepayment applied or removed): fetch it again and retry.

promisedPayDate and promiseNote log the customer's promise to pay, as Log promise does in the app: only on a sent invoice with a balance left.

Parameters

  • idstringin the pathrequired

    The record's id.

Request body

  • customerNamestring
  • customerEmailstring, or null
  • customerAddressstring, or null
  • contactIdstring, or null

    Re-address the invoice to another contact (the company it is issued to follows that contact's company unless companyId is also sent). null unlinks the contact and keeps the company.

  • companyIdstring, or null

    The company (in this workspace; 400 otherwise) the invoice is issued to. null for none.

  • dueDatedate, or null
  • notesstring, or null
  • termsstring, or null
  • remindersEnabledboolean

    Switch this invoice's customer payment reminders on or off.

  • promisedPayDatedate, or null

    The date the customer promised to pay (2026-11-30), on a sent invoice with a balance left (400 otherwise). null clears the promise and its note.

  • promiseNotestring, or null

    A note with the promise. Needs a promisedPayDate.

  • discountTypeone of flat, percent, or null
  • discountValuenumber
  • taxRatenumber
  • lineItemsarray of line item input objects

    When sent, replaces every line.

Responses

  • 200The invoice object

    Invoice updated

  • 409

    The invoice is applied as a prepayment and its total would change, or it changed while this request was being saved

Can also answer 400, 401, 403 and 404, as described under Errors.

Delete a draft invoice

DELETE/api/v1/invoices/{id}

Deletes a draft invoice (and its line items) that was never sent, never paid and never given a Stripe pay link.

Contract change (October 2026): an invoice that was sent (it has a sentAt, or its status is SENT, OVERDUE, PARTIALLY_PAID or PAID) or that was ever paid (it has a payment, or a paidAt: an invoice marked paid and then moved back to DRAFT or to VOID still counts) is no longer deleted, together with its payments. Neither is one that was given a Stripe pay link (until October 2026 the app's Create pay link worked on a draft), since the customer may already have that link. The request answers 409 with an error that says to void the invoice instead: POST /invoices/{id}/status with {"status": "VOID"}, which keeps the invoice and any payments received. A mark-paid record (a payment with placeholder: true) is not money received: voiding releases it, as moving the invoice to any status other than PAID does. A draft that was voided without ever being sent, paid or given a pay link can still be deleted. The in-app bulk delete follows the same rule.

Parameters

  • idstringin the pathrequired

    The record's id.

Responses

  • 200

    Resource deleted

    • dataobject
    • data.idstring
    • data.deletedboolean
  • 409

    The invoice was sent, paid or given a pay link, so it is kept. Void it instead. An invoice that is already void is kept as it is, and its error says so instead of asking you to void it.

Can also answer 401, 403 and 404, as described under Errors.

Change an invoice's status

POST/api/v1/invoices/{id}/status

Sends the invoice.paid webhook when the invoice moves into PAID.

A VOID invoice takes no payment: setting it to PAID or PARTIALLY_PAID answers 409 and changes nothing. Contract change (October 2026): before, PAID on a void invoice answered 400 and changed nothing, and PARTIALLY_PAID answered 200 and was applied, moving the void invoice to PARTIALLY_PAID. Both now answer 409. Setting a void invoice back to DRAFT, SENT or OVERDUE is still allowed, unless it still carries a Prepayment received (invoice ...) line: voiding it released that prepayment, so the move answers 409 and changes nothing until the line is deleted.

An invoice applied as a prepayment to another invoice keeps its status: any change answers 409 until the prepayment is removed from that invoice.

Parameters

  • idstringin the pathrequired

    The record's id.

Request body

  • statusone of DRAFT, SENT, PARTIALLY_PAID, PAID, OVERDUE, VOIDrequired

Responses

  • 200The invoice object

    Status changed (or already that status)

  • 409

    The invoice is VOID, so it takes no payment. This request recorded and changed nothing. Set it back to SENT first if it really is owed.

Can also answer 400, 401, 403 and 404, as described under Errors.

List an invoice's payments

GET/api/v1/invoices/{id}/payments

Newest payment first.

Parameters

  • idstringin the pathrequired

    The record's id.

Responses

Can also answer 401 and 404, as described under Errors.

Record a payment on an invoice

POST/api/v1/invoices/{id}/payments

Moves the invoice to PARTIALLY_PAID or PAID by what has been paid in all. Sends the invoice.paid webhook when it is paid in full.

Contract change (October 2026): a VOID invoice takes no payment. The request answers 409 and records nothing; before, the payment was recorded and moved the voided invoice to PARTIALLY_PAID or PAID.

reference makes a retry safe: a payment with a reference already recorded on this invoice is not recorded again, and the request answers 200 with duplicate: true. That holds after the invoice is voided too, so a retry of a payment recorded before the void (its first response lost) answers 200, never 409: the money is in BrytIO. A 409 means this request recorded nothing.

Parameters

  • idstringin the pathrequired

    The record's id.

Request body

  • amountnumberrequired

    The amount received, in the workspace's currency. Must be more than 0.

  • methodstring

    How the payment was received, kept as sent. BrytIO itself uses manual, bank, check, stripe and other.

  • referencestring, or null

    A check number, wire reference or Stripe charge id. MARK_PAID is reserved.

Responses

  • 200

    Duplicate: a payment with this reference is already recorded on this invoice (a retry), so nothing new was recorded. Answered whatever the invoice's status now is, VOID included.

  • 201

    Payment recorded; invoice status updated

  • 409

    The invoice is VOID, so it takes no payment. This request recorded and changed nothing. Set it back to SENT first if it really is owed.

Can also answer 400, 401, 403 and 404, as described under Errors.

Activities

Notes, calls, emails, meetings, and tasks linked to CRM records.

The activity object

  • idstring
  • organizationIdstring
  • typeone of NOTE, CALL, EMAIL, MEETING, TASK, SYSTEM
  • titlestring
  • bodystring, or null
  • dueAtdate and time, or null
  • completedAtdate and time, or null
  • repeatRuleone of daily, weekly, monthly, or null

    Tasks only. Completing the task creates its next occurrence (same links and assignee, stepping from repeatAnchorAt at the same time of day).

  • repeatNextIdstring, or null

    Id of the occurrence created when this task was completed.

  • repeatAnchorAtdate and time, or null

    The series anchor every occurrence steps from (its first dueAt; moved when dueAt is changed through the API or the app, never by a snooze). Server-maintained.

  • repeatSeriesIdstring, or null

    Id of the series' first task, on every occurrence it spawned (null on the first task). Server-maintained.

  • priorityone of high, or null

    Tasks only. "high", or null for normal priority.

  • emailReminderboolean

    Tasks only. When true, the assignee (while still a member) is also emailed when the task comes due.

  • callOutcomestring, or null

    Calls and meetings only. A CALL: connected, voicemail, no_answer, busy, wrong_number. A MEETING: held, no_show, rescheduled, cancelled.

  • durationMinutesinteger, or null

    Calls and meetings only. Length in whole minutes.

  • userIdstring, or null

    The member who logged it (a user id). null for one created through the API.

  • assignedToIdstring, or null

    The member a task is assigned to (a user id).

  • contactIdstring, or null
  • dealIdstring, or null
  • companyIdstring, or null
  • sourcestring

    Where it came from. app for one made in BrytIO or through the API; microsoft, google or bcc for an email a connected mailbox or the BCC address logged.

  • directionstring, or null

    A logged email's direction, IN or OUT. null on other activities.

  • occurredAtdate and time, or null

    When it happened (a logged email's sent or received time); set to the creation time otherwise.

  • createdAtdate and time
  • updatedAtdate and time

    The last change. Activities created before October 2026 show the time this field was added.

List activities

GET/api/v1/activities

Newest first, or oldest change first with updated_since. A synced email that was deleted (hidden) is not listed.

Parameters

  • limitintegerquery

    How many records a page holds, from 1 to 200 (50 when left out).

  • cursorstringquery

    The nextCursor of the page before. With updated_since, only a cursor from a list read with updated_since works.

  • updated_sincedate and timequery

    Only records changed at or after this time, oldest change first (by updatedAt, then id). An ISO 8601 date and time with a time zone, such as 2026-10-01T00:00:00Z; anything else answers 400. Deleted records are not reported.

  • contactIdstringquery

    Only this contact's activities.

  • dealIdstringquery

    Only this deal's activities.

  • companyIdstringquery

    Only this company's activities.

  • typeone of NOTE, CALL, EMAIL, MEETING, TASK, SYSTEMquery

    Only activities of this type. Any other value is ignored.

Responses

Can also answer 400 and 401, as described under Errors.

Create an activity

POST/api/v1/activities

A note, call, email, meeting or task. Every activity must be linked to at least one of contactId, dealId or companyId.

Request body

At least one of contactId, dealId or companyId is required.

  • typeone of NOTE, CALL, EMAIL, MEETING, TASK, SYSTEM
  • titlestringrequired
  • bodystring, or null
  • dueAtdate and time
  • completedAtdate and time
  • repeatRuleone of daily, weekly, monthly

    Tasks only; needs dueAt.

  • priorityone of high, normal, or null

    Tasks only. "high" flags the task; "normal" or null leaves it unflagged.

  • emailReminderboolean

    Tasks only. Email the assignee when the task comes due (default false).

  • callOutcomestring, or null

    Calls and meetings only (400 otherwise). A CALL: connected, voicemail, no_answer, busy, wrong_number. A MEETING: held, no_show, rescheduled, cancelled.

  • durationMinutesinteger, or null

    Calls and meetings only (400 otherwise). Length in whole minutes.

  • contactIdstring
  • dealIdstring
  • companyIdstring

Responses

Can also answer 400, 401 and 403, as described under Errors.

Get an activity

GET/api/v1/activities/{id}

Parameters

  • idstringin the pathrequired

    The record's id.

Responses

Can also answer 401 and 404, as described under Errors.

Update an activity

PATCH/api/v1/activities/{id}

Only the fields sent change. Completing a repeating task creates its next occurrence. An email logged by a connected mailbox or the BCC address can't be edited: the request answers 409.

Parameters

  • idstringin the pathrequired

    The record's id.

Request body

  • typeone of NOTE, CALL, EMAIL, MEETING, TASK, SYSTEM
  • titlestring
  • bodystring, or null
  • dueAtdate and time, or null
  • completedAtdate and time, or null
  • repeatRuleone of daily, weekly, monthly, or null

    Tasks only; needs a due date. null stops the repeat.

  • priorityone of high, normal, or null

    Tasks only. "high" flags the task; "normal" or null clears the flag.

  • emailReminderboolean

    Tasks only. Email the assignee when the task comes due.

  • callOutcomestring, or null

    Calls and meetings only, judged on the type the activity will have (see ActivityCreate). Turning the activity into another type clears it, and a call turned into a meeting drops an outcome a meeting doesn't have.

  • durationMinutesinteger, or null

    Calls and meetings only. Cleared when the activity becomes another type.

  • contactIdstring, or null
  • dealIdstring, or null
  • companyIdstring, or null

Responses

  • 200The activity object

    Activity updated

  • 409

    The activity is an email logged by a connected mailbox or the BCC address, which can't be edited.

Can also answer 400, 401, 403 and 404, as described under Errors.

Delete an activity

DELETE/api/v1/activities/{id}

An email logged by a connected mailbox or the BCC address (source microsoft, google or bcc) is hidden rather than deleted, so the next mailbox sync doesn't write it back; the response then carries hidden: true, and the activity answers 404 and leaves every list from then on. The message itself stays in the mailbox. Such an email can't be edited (PATCH answers 409). A synced message is logged once per matched contact, each copy its own activity with the same Message-ID. By default (scope=message) deleting one hides every contact's copy; scope=activity hides only this one. hiddenIds lists every activity hidden, this one first. Deleting a call, meeting or email works out its contact's lastContactedAt again from the ones that remain.

Parameters

  • idstringin the pathrequired

    The record's id.

  • scopeone of message, activityquery

    For a synced email only. message (the default) hides every contact's copy of the message; activity hides this contact's copy only. Ignored for other activities.

Responses

  • 200

    Activity deleted, or hidden when it is a synced email

    • dataobject
    • data.idstring
    • data.deletedboolean
    • data.hiddenboolean

      Present (true) when a synced email was hidden rather than deleted.

    • data.hiddenIdsarray of strings

      Present with hidden. Every activity hidden (this one, then its copies on other contacts).

Can also answer 400, 401, 403 and 404, as described under Errors.

Sequences

Email sequences and their enrollments.

The sequence object

  • idstring
  • organizationIdstring
  • namestring
  • descriptionstring, or null
  • enabledboolean

    Whether it sends. A sequence that is off sends nothing and enrolls no one.

  • stepsstring

    The emails, as a JSON array in a string: each step has an id, a delayDays (days after the step before; 0 sends right away), a subject and a body, which can use merge fields such as {{firstName}}.

  • _countobject

    On a list and a get.

  • _count.enrollmentsinteger

    Every enrollment the sequence has had.

  • enrollmentsarray of objects

    On the list only. One active enrollment's id when it has any, so an empty array means no one is enrolled now.

  • enrollments[].idstring
  • createdAtdate and time
  • updatedAtdate and time

List email sequences

GET/api/v1/sequences

Every sequence in one response, newest first, or only the ones changed at or after updated_since, oldest change first.

Parameters

  • updated_sincedate and timequery

    Only records changed at or after this time, oldest change first (by updatedAt, then id). An ISO 8601 date and time with a time zone, such as 2026-10-01T00:00:00Z; anything else answers 400. Deleted records are not reported.

Responses

Can also answer 400 and 401, as described under Errors.

Create an email sequence

POST/api/v1/sequences

The plan must include email sequences (403 otherwise).

Request body

  • namestringrequired
  • descriptionstring, or null
  • enabledboolean
  • stepsarray of objectsrequired

    The emails, in order (an array, or the same array as a JSON string). Each step: delayDays (a number of days after the step before), subject and body.

  • steps[].idstring
  • steps[].delayDaysnumber
  • steps[].subjectstring
  • steps[].bodystring

Responses

Can also answer 400, 401 and 403, as described under Errors.

Get an email sequence

GET/api/v1/sequences/{id}

Parameters

  • idstringin the pathrequired

    The record's id.

Responses

Can also answer 401 and 404, as described under Errors.

Update an email sequence

PATCH/api/v1/sequences/{id}

Only the fields sent change. Turning a sequence back on needs a plan that includes sequences; turning it off and editing it don't.

Parameters

  • idstringin the pathrequired

    The record's id.

Request body

  • namestring
  • descriptionstring, or null
  • enabledboolean
  • stepsarray of objects

    When sent, replaces every step (an array, or the same array as a JSON string).

  • steps[].idstring
  • steps[].delayDaysnumber
  • steps[].subjectstring
  • steps[].bodystring

Responses

Can also answer 400, 401, 403 and 404, as described under Errors.

Delete an email sequence

DELETE/api/v1/sequences/{id}

Its enrollments are deleted with it, so nothing more is sent. Answers 204 with no body.

Parameters

  • idstringin the pathrequired

    The record's id.

Responses

  • 204

    Sequence deleted

Can also answer 401, 403 and 404, as described under Errors.

Enroll contacts in an email sequence

POST/api/v1/sequences/{id}/enroll

Enrolls each contact once, at its email address. A contact without an email, one already enrolled, or an id that isn't a contact of this workspace is skipped, and so is every contact when the sequence is off or not this workspace's. The plan must include email sequences.

Parameters

  • idstringin the pathrequired

    The record's id.

Request body

  • contactIdsarray of stringsrequired

    The contacts to enroll, 1 to 500 ids.

Responses

  • 200

    How many were enrolled and how many skipped

    • enrolledinteger
    • skippedinteger

Can also answer 400, 401 and 403, as described under Errors.

Automations

Automations that run steps when something happens in BrytIO.

The automation object

  • idstring
  • organizationIdstring
  • namestring
  • descriptionstring, or null
  • enabledboolean
  • triggerstring

    What starts it, as JSON in a string: the event (such as deal.won) and any conditions on the record.

  • actionsstring

    The steps it runs, as a JSON array in a string.

  • _countobject

    On a list and a get.

  • _count.runsinteger

    How many times it has run.

  • createdAtdate and time
  • updatedAtdate and time

List automations

GET/api/v1/automations

Every automation in one response, newest first, or only the ones changed at or after updated_since, oldest change first.

Parameters

  • updated_sincedate and timequery

    Only records changed at or after this time, oldest change first (by updatedAt, then id). An ISO 8601 date and time with a time zone, such as 2026-10-01T00:00:00Z; anything else answers 400. Deleted records are not reported.

Responses

Can also answer 400 and 401, as described under Errors.

Create an automation

POST/api/v1/automations

The same rules as the automation builder in the app. The plan must include automations (403 otherwise).

Request body

  • namestringrequired
  • descriptionstring, or null
  • enabledboolean
  • triggerobjectrequired

    What starts it (an object, or the same object as a JSON string): {"event": "deal.won"}, with conditions on the record's fields if you want them. Build one in the app and read it back to see the full shape.

  • actionsarray of objectsrequired

    The steps to run, in order (an array, or the same array as a JSON string). Each has a type, such as send_notification, and that step's settings.

Responses

Can also answer 400, 401 and 403, as described under Errors.

Get an automation

GET/api/v1/automations/{id}

Parameters

  • idstringin the pathrequired

    The record's id.

Responses

Can also answer 401 and 404, as described under Errors.

Update an automation

PATCH/api/v1/automations/{id}

Only the fields sent change. A new trigger or new steps are checked against each other, as the builder checks them. Turning an automation back on needs a plan that includes automations; turning it off and editing it don't.

Parameters

  • idstringin the pathrequired

    The record's id.

Request body

  • namestring
  • descriptionstring, or null
  • enabledboolean
  • triggerobject

    A new trigger (an object, or the same object as a JSON string).

  • actionsarray of objects

    New steps, replacing every step (an array, or the same array as a JSON string).

Responses

Can also answer 400, 401, 403 and 404, as described under Errors.

Delete an automation

DELETE/api/v1/automations/{id}

Its run history goes with it.

Parameters

  • idstringin the pathrequired

    The record's id.

Responses

  • 200

    Resource deleted

    • dataobject
    • data.idstring
    • data.deletedboolean

Can also answer 401, 403 and 404, as described under Errors.

Shipments

Shipment tracking with status events.

The shipment object

  • idstring
  • organizationIdstring
  • referencestring

    Your own order reference.

  • trackingNumberstring
  • carrierstring
  • statusone of PENDING, LABEL_CREATED, IN_TRANSIT, OUT_FOR_DELIVERY, DELIVERED, EXCEPTION, RETURNED, CANCELLED
  • customerNamestring
  • customerEmailstring, or null
  • contactIdstring, or null

    The contact the shipment is tracked against.

  • dealIdstring, or null

    The deal the shipment is tracked against. Set to null when the deal is deleted.

  • invoiceIdstring, or null

    The invoice the shipment is tracked against. Set to null when the invoice is deleted.

  • fromAddressstring, or null
  • toAddressstring, or null
  • estimatedDeliverydate and time, or null
  • actualDeliverydate and time, or null
  • eventsarray of objects

    Tracking events, newest first (the 5 latest on a list).

  • events[].idstring
  • events[].statusone of PENDING, LABEL_CREATED, IN_TRANSIT, OUT_FOR_DELIVERY, DELIVERED, EXCEPTION, RETURNED, CANCELLED
  • events[].descriptionstring
  • events[].locationstring, or null
  • events[].occurredAtdate and time
  • createdAtdate and time
  • updatedAtdate and time

List shipments

GET/api/v1/shipments

Newest first, or oldest change first with updated_since. Each shipment carries its 5 latest tracking events.

Parameters

  • limitintegerquery

    How many records a page holds, from 1 to 200 (50 when left out).

  • cursorstringquery

    The nextCursor of the page before. With updated_since, only a cursor from a list read with updated_since works.

  • updated_sincedate and timequery

    Only records changed at or after this time, oldest change first (by updatedAt, then id). An ISO 8601 date and time with a time zone, such as 2026-10-01T00:00:00Z; anything else answers 400. Deleted records are not reported.

  • statusone of PENDING, LABEL_CREATED, IN_TRANSIT, OUT_FOR_DELIVERY, DELIVERED, EXCEPTION, RETURNED, CANCELLEDquery

    Only shipments with this status. Any other value is ignored.

Responses

Can also answer 400 and 401, as described under Errors.

Create a shipment

POST/api/v1/shipments

BrytIO then tracks it with the carrier and updates its status. Runs the shipment.created automations.

Request body

customerName is required unless invoiceId is set: then a blank customerName or customerEmail is filled from the invoice's customer. contactId, dealId and invoiceId must be records of your workspace, or the request is refused with 400 and nothing is created.

  • referencestringrequired
  • trackingNumberstringrequired
  • carrierstringrequired
  • customerNamestring
  • customerEmailstring
  • fromAddressstring
  • toAddressstring
  • contactIdstring, or null
  • dealIdstring, or null
  • invoiceIdstring, or null

Responses

Can also answer 400, 401 and 403, as described under Errors.

Get a shipment

GET/api/v1/shipments/{id}

With all its tracking events, newest first.

Parameters

  • idstringin the pathrequired

    The record's id.

Responses

Can also answer 401 and 404, as described under Errors.

Update a shipment

PATCH/api/v1/shipments/{id}

Only the fields sent change. Setting status to DELIVERED also sets actualDelivery to now.

Parameters

  • idstringin the pathrequired

    The record's id.

Request body

Only the fields sent change. Send contactId, dealId or invoiceId as an id to link it, or null to unlink it. Each id must be a record of your workspace, or the request is refused with 400 and nothing changes. Linking an invoice fills a blank customerName or customerEmail from the invoice's customer.

  • statusone of PENDING, LABEL_CREATED, IN_TRANSIT, OUT_FOR_DELIVERY, DELIVERED, EXCEPTION, RETURNED, CANCELLED
  • fromAddressstring, or null
  • toAddressstring, or null
  • estimatedDeliverydate and time, or null
  • contactIdstring, or null
  • dealIdstring, or null
  • invoiceIdstring, or null

Responses

Can also answer 400, 401, 403 and 404, as described under Errors.

Delete a shipment

DELETE/api/v1/shipments/{id}

Parameters

  • idstringin the pathrequired

    The record's id.

Responses

  • 200

    Resource deleted

    • dataobject
    • data.idstring
    • data.deletedboolean

Can also answer 401, 403 and 404, as described under Errors.

Tags

Org-wide labels that can be attached to contacts and companies.

The tag object

  • idstring
  • organizationIdstring

    Not in the GET /tags list.

  • namestring
  • colorstring

List all tags in the organization

GET/api/v1/tags

Responses

  • 200

    Tag list with usage counts

    • dataarray
    • countinteger

Can also answer 401, as described under Errors.

Create or update a tag (upsert by name)

POST/api/v1/tags

If a tag with the same name already exists in the organization, its color is updated and the same record is returned.

Request body

  • namestringrequired
  • colorstring

    Hex color code

Responses

Can also answer 400, 401 and 403, as described under Errors.

Delete a tag (detaches from all contacts and companies)

DELETE/api/v1/tags/{id}

Parameters

  • idstringin the pathrequired

    The record's id.

Responses

  • 200

    Resource deleted

    • dataobject
    • data.idstring
    • data.deletedboolean

Can also answer 401, 403 and 404, as described under Errors.