Torch CRMCRM for manufacturers' reps

TEC World API

Last updated October 14, 2026

Connect your own tools, reports and integrations to your TEC World workspace.

Overview

The TEC World API gives your own tools, reports and integrations access to your workspace's data over HTTPS. Requests and responses are JSON, every request is authenticated with an API key, and a key can never see more than the person it belongs to can see in TEC World.

The API reads every module listed under Endpoints and can create, update, delete and restore the records whose endpoints list those verbs.

The machine-readable OpenAPI 3.1 description of everything on this page is at /developers/openapi.json. Import it into Postman, Insomnia or a client generator.

Use of the API is governed by your organization's Terms of Service.

Getting a key

A workspace admin creates keys in Settings > Integrations > Private API, for themselves or for a member. A member can also create their own in Settings > My API Keys.

  • Give each key a name that says which integration uses it, so you can find and revoke it later.
  • Turn on only the access groups the integration needs. The Scopes table under Reference says which group grants each scope. A scope marked as not offered on the key form cannot be added to a key there yet.
  • Copy the secret when it is shown. It is shown once and cannot be retrieved later. If it is lost, revoke the key and create a new one.
  • Keep keys out of browser code, public websites and mobile apps. Anyone holding a key can read what its owner can read in TEC World.
  • The key settings page also shows your API address and a test request you can paste into a terminal.
  • Each key in the list shows when TEC World last accepted it ("Last used 3 hours ago", or "Not used yet"), so you can tell whether an integration is calling. A request turned away before the key is let in, for example for a missing permission or too many requests, does not count. A key made before October 2, 2026 that has not been used since says "Not used since" that date, because uses were not recorded before then.

A key belongs to one person and acts as them: it sees what they see, and it stops working as soon as they are deactivated or lose the access it needs. A key on a person's account therefore breaks when that person leaves or changes role.

For an integration the whole company relies on, such as a Power BI refresh or a data warehouse sync, we recommend a dedicated account used only for integrations (for example "Integrations", with a shared mailbox your team monitors, so its alerts reach someone). Make it an admin so it can read every record of the access groups you give its key, and turn on only the groups the integration needs (read-only unless the integration changes records); every change made through its key is recorded under its name. Keep its sign-in details in your company's password manager rather than with one person, do not use it for everyday work in TEC World, and note when its key stops working (at most a year after it is made) so you can replace it in time. The account takes a seat like any other user. A key for your own spreadsheet or AI assistant belongs on your own account.

Authentication

Send the key as a bearer token on every request. Keys start with tcrm_.

curl "https://your-crm-address/api/v1" \
  -H "Authorization: Bearer tcrm_your_key_here"

GET /api/v1 checks a key: it answers the key's details and the endpoints the API serves. GET /api/v1/health adds the key's rate-limit settings and its recent request activity.

What a key can read is the overlap of its scopes and its owner's own access in TEC World: their role, their territory and manufacturer assignments, and the app's own-records rules. If the owner loses access to a module, the key loses it on the next request. A missing, wrong, expired or revoked key answers 401. A key without the scope an endpoint needs, or whose owner cannot read that module, answers 403.

Requests and responses

Every response is JSON with ok, and carries the same three values in its body and in its headers:

  • requestId, header x-torch-request-id: quote it when you contact support about a request.
  • apiVersion, header x-torch-api-version: the response format version (see Versioning).
  • deprecated, header x-torch-api-deprecated: true when the version you are on is scheduled to change.

A list answers data (an array), pagination and sync. A single record answers data (an object).

{
  "ok": true,
  "requestId": "5f9b2dc7-c130-4bb4-b7f5-47d7f2d8a1cb",
  "apiVersion": "2026-05-01",
  "deprecated": false,
  "data": [],
  "pagination": { "page": 1, "pageSize": 50, "total": 0, "totalPages": 1, "hasNextPage": false, "hasPreviousPage": false },
  "sync": { "fields": [], "includes": [], "updatedSince": null, "createdSince": null, "nextCursor": null }
}

Ignore fields you do not recognize: new fields can be added to a response at any time without a version change. Any field other than id can be null or, where a field needs extra access, left out.

Long-text fields such as notes and activity bodies are always plain text with lines separated by a newline. Formatting applied in the app is removed, so you never receive HTML.

Paging and search

Every list endpoint takes these query parameters:

  • page: the page number, from 1 (the default).
  • pageSize: records per page, 50 by default and at most 200.
  • search: a text search over the module's main fields, at most 200 characters.
  • fields: a comma-separated list of the fields you want back, such as id,updated_at. id is always included, and a name the endpoint does not return is ignored.
curl "https://your-crm-address/api/v1/accounts?page=1&pageSize=10&search=acme" \
  -H "Authorization: Bearer tcrm_your_key_here"

Incremental sync

To keep a copy of your data up to date without re-reading everything, pull only what changed:

  • updatedSince: an ISO 8601 timestamp. Only records changed at or after it are returned, on the modules that track changes.
  • createdSince: the same, for records created at or after it.
  • cursor: each list answers sync.nextCursor. Send it back unchanged as cursor to get the next batch, and keep going until sync.nextCursor is null. A malformed cursor answers 400.

A sync run that never misses a change:

  • Note the time each run starts, and save it once the run has finished.
  • Begin the next run with updatedSince a few minutes before that start. The time is inclusive and the windows overlap, so a record can come back twice: update your copy by id rather than adding rows.
  • Follow sync.nextCursor until it is null, sending the same parameters with each cursor. A list that hands out no cursor answers null on every page: page it with page until pagination.hasNextPage is false.
  • Send timestamps in UTC ending in Z, or encode + as %2B. A raw + arrives as a space, and a timestamp the API cannot read is ignored, so the whole list comes back. When you sent one, check that sync.updatedSince in the answer is not null.
  • Commission lines have no change time, so updatedSince does not narrow them: read them in full on each run.
  • Ask only for the fields you keep, with fields.
curl "https://your-crm-address/api/v1/contacts?updatedSince=2026-10-11T14:55:00Z&pageSize=200&fields=id,updated_at,email" \
  -H "Authorization: Bearer tcrm_your_key_here"

Changes never tell your copy that a record was deleted. Now and then (weekly suits most copies), read the whole list with fields=id, following the cursor, and drop the ids it no longer returns. That also drops records the key can no longer see.

Deleted records

A copy kept up to date with updatedSince never learns which records are gone. GET /api/v1/deletions?resource=<resource> lists the ids of one resource's deleted records, oldest first, so your copy can drop them. It takes the same key and read scope as that resource's list, and it only names a record the key would be allowed to read if the record still existed: the list's own visibility rules, applied to the record as it was stored.

  • resource (required): a resource name from the Endpoints reference, such as accounts. An unknown name answers 400.
  • since: an ISO 8601 timestamp. Only deletions at or after it are returned. Send the time the previous run started minus 15 minutes. deletedAt is when a deletion began, and a large one can take a while to finish, so it can appear after a run that started later than its deletedAt. The overlap catches it. The same row can then come back, and dropping an id twice does no harm.
  • pageSize and cursor work as on every list. A page shorter than pageSize is the last one, and sync.nextCursor is null. A cursor belongs to the resource and since it came from. It marks a position, not a permission: it is not tied to the key, and a page read with it still lists only rows that key may read. Follow sync.nextCursor rather than pagination.total, which is a full count only on the first page, for a key whose owner can read every record of the resource.
  • Each row has id, resource, deletedAt and kind. kind is soft for a record that can still be brought back by an admin for 30 days (if it is, it leaves this list), or hard for a record that is gone for good. A hard deletion is listed when the key would have been allowed to read the record, judged on what the record, and the company, quote or sale it was linked to, held when it was deleted. When that can no longer be shown, the row is left out for that key: for example a hard deletion recorded before the API kept those values, a record linked to a company, quote or sale that was already in Recently Deleted on its own, or a commission line the Commissions report would have to match again. Hard deletions are kept for 12 months. A key whose owner can read every record of the resource gets every hard deletion.
  • Commissions: each recalculation of a month deletes its draft lines and creates them again under new ids, so every replaced draft is listed here as a hard deletion, and one recalculation can list many. Drop the old id, and pick up the new line from the commissions list with updatedSince.
  • Unlike updatedSince, a since the API cannot read answers 400, so send UTC ending in Z or encode + as %2B.
  • Read the list at least every 12 months: hard deletions are kept for 12 months, then they are gone. A since older than that still works, but some hard deletions may be missing, so every page then has sync.sinceBeforeJournalWindow: true (and sync.journalRetainedFrom, the oldest deletion still kept): read the whole list once to find what is gone. A deleted record can be removed for good 31 days after its deletion, and it then appears here as hard, but a key limited to some territories, manufacturers or its own records may not be shown every one. With such a key, read the list at least every 30 days, and now and then read the whole list with fields=id too, which catches those.
curl "https://your-crm-address/api/v1/deletions?resource=accounts&since=2026-10-01T00:00:00Z" \
  -H "Authorization: Bearer tcrm_your_key_here"

Filters and sorting

Some lists also take filters and a sort, listed under each resource below. filter[<field>]=<value> matches a value exactly, and filter[<field>][<op>]=<value> takes the operators the table lists: eq, in (comma-separated, up to 50 values), gte, lte or is_null (true for empty, false for has a value). For example filter[created_at][gte]=2026-01-01. Filters combine with each other and with search, and only ever narrow what the key can see.

sort=<field> sorts ascending and sort=-<field> descending, one field at a time. Dates are YYYY-MM-DD and timestamps ISO 8601. On a timestamp field, gte or lte with a date alone covers that whole day in UTC. A filter or sort the table does not list answers 400 naming the parameter. A cursor belongs to the query it came from: changing the filters, search or sort while following one answers 400, so start again without it.

Embedding related records

A few reads take include=<name> to embed related records on each record, saving a call per record: GET /api/v1/accounts and /api/v1/accounts/{id} take include=contacts (the company's contact links), GET /api/v1/contacts and /api/v1/contacts/{id} take include=accounts (the contact's company links), and GET /api/v1/quotes/{id} takes include=items (the quote's line items). Each embed is exactly what the matching endpoint lists for that record, under the same scope and visibility rules.

  • The embed sits on the record under the include's name as { "data": [...], "has_more": false }. data holds at most 100 rows, in that endpoint's order; has_more is true when the record has more, and the endpoint itself pages the rest.
  • An include that needs another scope is refused outright: include=contacts needs contacts:read and include=accounts needs accounts:read (403 missing_scope), and the key's owner must be able to read that module (403 forbidden). A name the read does not take is 400 invalid_request.
  • On a list, pageSize is at most 50 with an include (400 past it), and sync.includes lists what was embedded. A single-record read with an include answers sync.includes too.
  • fields narrows the record only, never the embed. An embed is asked for by name, so it is always present once asked for, with an empty data when the record has nothing to embed.
curl "https://your-crm-address/api/v1/accounts?pageSize=50&include=contacts" \
  -H "Authorization: Bearer tcrm_your_key_here"

Creating and changing records

POST creates a record and PATCH changes the fields you send. A field a write does not accept, including one the server sets itself, answers 400 and nothing is saved. Each write answers the record as a read returns it.

  • Idempotency: send an Idempotency-Key header (any unique string, such as a UUID) on a create, a delete or a restore. Retrying with the same key and body answers the first result instead of acting twice. The same key with a different body answers 409. Where an endpoint requires the header, a call without it answers 428. A key is remembered for 7 days after the last call that ran with it (a retry answered from memory does not extend that). After that, the same key and body is a new request and acts again.
  • Concurrency: a PATCH can send expected_updated_at, the updated_at a read returned. If the record changed since, the answer is 409 with the latest updated_at, and nothing is saved.
  • Deletes are soft: for 30 days, POST .../restore with a key of the same person who deleted the record brings it back. After that the answer is 410.
  • A write body is at most 64 KiB unless the endpoint says otherwise. A larger one answers 413.

Errors

An error answers ok: false, a human-readable error and a machine-readable code:

{
  "ok": false,
  "error": "Private API token is missing the required scope",
  "code": "forbidden",
  "requestId": "5f9b2dc7-c130-4bb4-b7f5-47d7f2d8a1cb",
  "apiVersion": "2026-05-01",
  "deprecated": false
}
  • 400 invalid_request: a parameter or body is not valid. The error says which.
  • 401 unauthorized: the key is missing, wrong, expired or revoked.
  • 402 payment_required: the workspace has no active subscription. A workspace admin can subscribe in the app's billing settings; retrying will not help until then.
  • 403 forbidden: the key lacks the scope, or its owner lacks the access.
  • 404 not_found: no such record in your workspace, or one the key cannot see. The two look the same on purpose.
  • 409 conflict: the record changed since you read it, or an idempotency key was reused with a different body.
  • 429 rate_limited: too many requests (see Limits). When the answer carries a Retry-After header, wait that many seconds before retrying.
  • 503 service_unavailable: a required service is briefly unavailable. Retry later.
  • 500 internal_error: something went wrong on our side. Retry later, and contact support with the requestId if it persists.

Write endpoints can also answer more specific codes, such as 409 duplicate or paid_locked, 410 restore_expired, 413 payload_too_large, 422 constraint and 428 precondition_required. Each operation in the OpenAPI description lists the statuses it can answer.

Handle errors by HTTP status first, then use code for detail. Treat a code you do not recognize by its status, and never match on the wording of error, which can change.

Limits

  • Each key may make 300 requests a minute, across every endpoint and every program using it. Beyond that the answer is 429.
  • All of one person's keys together may make 400 requests a minute, counted toward the person each key belongs to. Beyond that their requests answer 429 until the minute ends; their colleagues' keys are not held to it.
  • All of a workspace's keys together may make 1,200 requests a minute, whichever keys and programs send them. Beyond that every key of the workspace gets 429 until the minute ends, so a job spread over several keys should pace them together.
  • Reads also share a daily allowance with the AI assistant (MCP) server: 1,000 a day for everything one person's keys and connections do, and 10,000 a day for the whole workspace, unless your workspace has its own numbers. GET /api/v1 and GET /api/v1/health do not count. Past it the answer is 429 with a Retry-After header: the seconds until the allowance resets.
  • Failed sign-ins are throttled separately: after 20 failures in 5 minutes from one address with the same key, further failures answer 429 instead of 401 until the 5 minutes pass. A correct key keeps working.
  • Creating, changing, deleting and restoring records have lower limits of their own per key, which also answer 429 with a Retry-After header.
  • On a 429, wait the number of seconds in the Retry-After header when the answer has one; otherwise wait up to a minute. Then send the same request again.
  • GET /api/v1/health shows a key's current limits (its own, its owner's and its workspace's, the daily allowance included) and its recent failures.

Versioning

The API's paths start with /api/v1, and every response names its format version in apiVersion (currently 2026-05-01). There is one version today, and a request cannot ask for another. Adding an endpoint, a field, a filter, an error code or an event is not a breaking change and can happen without notice, so build your client to tolerate them. When a version is scheduled to be retired, its responses will answer deprecated: true before it changes: watch for that value.

Webhooks

A webhook sends an event to an HTTPS address you run each time something it subscribes to happens, so you do not have to poll for it. A workspace admin adds one on the Connections page of the app's integration settings, choosing which events it sends, and copies its signing secret, which is shown once.

Each event arrives as an HTTPS POST request with a JSON body and these headers:

  • x-torch-event: the event name, such as contact.created.
  • x-torch-delivery: this delivery's id, the same on every retry of it.
  • x-torch-timestamp: when this attempt was sent, in ISO 8601 UTC. Every attempt has a new one.
  • x-torch-signature: sha256= followed by the signature in lowercase hex. For 24 hours after the webhook's signing secret is rotated it carries two, separated by a comma: the first made with the new secret, the second with the old one.
{
  "eventId": "6f1c0d9e2b7a4c3d8e5f1a2b",
  "eventType": "contact.created",
  "entityType": "contact",
  "entityId": "3f6c2a1e-8b4d-4c2a-9e7f-1d2b3c4d5e6f",
  "actorUserId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
  "workspaceId": "b2a1c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
  "occurredAt": "2026-10-11T15:04:05.123Z",
  "data": { "id": "3f6c2a1e-8b4d-4c2a-9e7f-1d2b3c4d5e6f", "name": "Grace Hopper", "email": "grace@example.com" }
}

eventId names the event: every delivery and retry of it carries the same one. entityType and entityId name the record, actorUserId the person whose action caused it (or null), and occurredAt when the change happened, which can be well before the event reaches you. data holds ids and a few labels, never the whole record: read the record through the API for its current state.

To check that an event is genuine, compute an HMAC-SHA256 keyed with the webhook's secret over the timestamp header, a period and the raw request body exactly as received, and compare it with each sha256= entry of the signature header using a constant-time comparison: the event is genuine when any entry matches. Refuse an event whose timestamp is more than 5 minutes from your clock. Each retry is signed again with a fresh timestamp, so a genuine retry is never refused. When a workspace admin rotates the signing secret, events are signed with both the new and the old secret for 24 hours: put the new secret in place within that time.

import crypto from "node:crypto";

// rawBody: the request body exactly as received (a Buffer); headers: the request's headers.
function verifyEvent(rawBody, headers, secret) {
    const timestamp = headers["x-torch-timestamp"] ?? "";
    const sentAt = Date.parse(timestamp);
    if (!Number.isFinite(sentAt) || Math.abs(Date.now() - sentAt) > 5 * 60 * 1000) return null;
    const wanted = Buffer.from("sha256=" + crypto.createHmac("sha256", secret).update(`${timestamp}.`).update(rawBody).digest("hex"));
    // One entry, or two (new, old) for 24 hours after a rotation: any match is genuine.
    const entries = String(headers["x-torch-signature"] ?? "").split(",").map((entry) => Buffer.from(entry.trim()));
    if (!entries.some((given) => given.length === wanted.length && crypto.timingSafeEqual(given, wanted))) return null;
    return JSON.parse(rawBody.toString("utf8"));
}
  • Answer with any 2xx status within 15 seconds, and do slow work after answering. Only a 2xx counts as delivered: any other status, a redirect (never followed), a timeout or a failed connection is retried.
  • Retries come no sooner than 5, 10, 15 and 30 minutes, then 1, 2, 4 and 8 hours, then 14 hours four times after each failed attempt, and often later: about 3 days in all. After the 13th failed attempt the event is not retried to that address.
  • Delivery is at least once: the same event can arrive more than once, so skip an eventId you have already handled.
  • Order is not guaranteed: a retry can arrive after newer events. Use occurredAt when order matters.

Events are sent when most records are created, updated or deleted, through the API or in the app. On the Connections page a webhook's events are chosen in groups, such as Companies or Quotes, or as Everything, which also takes kinds of event added later. Imports and merges send none, so keep a copy current with updatedSince rather than with events alone.

Reference

The scopes a key can hold, then each resource with its endpoints, the scope they need and the fields it returns. In the endpoint paths, {id} is a record's id. "Returned by" says whether a field comes back in the list, the single-record read, or both. A resource without a field table returns the fields its OpenAPI description lists.

Scopes

ScopeAllowsAccess group on the key form
accounts:readReadCustomers & Contacts
contacts:readReadCustomers & Contacts
quotes:readReadQuotes & Sales
activities:readReadTasks & Activity
manufacturers:readReadProducts & Inventory
products:readReadProducts & Inventory
leads:readReadTasks & Activity
sales:readReadQuotes & Sales
commissions:readReadQuotes & Sales
inventory:readReadProducts & Inventory
samples:readReadProducts & Inventory
documents:readReadProducts & Inventory
tokens:manageAdministrationNot offered on the key form
contacts:writeCreate and changeNot offered on the key form
activities:writeCreate and changeNot offered on the key form
contacts:deleteDelete and restoreDelete and restore records
activities:deleteDelete and restoreDelete and restore records
opportunities:readReadQuotes & Sales
opportunities:writeCreate and changeCreate and edit records
manufacturers:writeCreate and changeCreate and edit records
inventory:writeCreate and changeCreate and edit records
inventory:deleteDelete and restoreDelete and restore records
line_sheets:writeCreate and changeCreate and edit records
samples:writeCreate and changeCreate and edit records
samples:deleteDelete and restoreDelete and restore records
leads:writeCreate and changeCreate and edit records
leads:deleteDelete and restoreDelete and restore records
accounts:writeCreate and changeCreate and edit records
products:writeCreate and changeCreate and edit records
products:deleteDelete and restoreDelete and restore records
opportunities:deleteDelete and restoreDelete and restore records
accounts:deleteDelete and restoreDelete and restore records
manufacturers:deleteDelete and restoreDelete and restore records
price_sheets:writeCreate and changeCreate and edit records
multiplier:writeCreate and changeCreate and edit records
inventory:stockActionCreate and edit records
quotes:writeCreate and changeCreate and edit records
quotes:deleteDelete and restoreDelete and restore records

Key and health

MethodPathScope
GET/api/v1Any valid key
GET/api/v1/healthAny valid key
GET/api/v1/deletionsThe read scope of the resource named by `resource`
GET/api/v1/tokenstokens:manage
DELETE/api/v1/tokens/{id}tokens:manage
GET/api/v1/price-book/price-sheetsprice_sheets:write
POST/api/v1/price-book/price-sheetsprice_sheets:write
PATCH/api/v1/price-book/price-sheets/{id}price_sheets:write
GET/api/v1/price-book/price-sheet-itemsprice_sheets:write
POST/api/v1/price-book/price-sheet-itemsprice_sheets:write
PATCH/api/v1/price-book/price-sheet-items/{id}price_sheets:write
GET/api/v1/price-book/spasmultiplier:write
POST/api/v1/price-book/spasmultiplier:write
PATCH/api/v1/price-book/spas/{id}multiplier:write
GET/api/v1/price-book/manufacturer-ratesmultiplier:write
PATCH/api/v1/price-book/manufacturer-rates/{id}multiplier:write
GET/api/v1/price-book/tariff-surchargesmultiplier:write
POST/api/v1/price-book/tariff-surchargesmultiplier:write
PATCH/api/v1/price-book/tariff-surcharges/{id}multiplier:write
GET/api/v1/price-book/tariff-originsmultiplier:write
POST/api/v1/price-book/tariff-originsmultiplier:write
PATCH/api/v1/price-book/tariff-origins/{id}multiplier:write
GET/api/v1/price-book/tariff-duty-rulesmultiplier:write
POST/api/v1/price-book/tariff-duty-rulesmultiplier:write
PATCH/api/v1/price-book/tariff-duty-rules/{id}multiplier:write

Companies

Reads need accounts:read.

MethodPathScope
GET/api/v1/accountsaccounts:read
GET/api/v1/accounts/{id}accounts:read
GET/api/v1/search/accountsaccounts:read
GET/api/v1/accounts/{id}/contactsaccounts:read
POST/api/v1/accountsaccounts:write
PATCH/api/v1/accounts/{id}accounts:write
DELETE/api/v1/accounts/{id}accounts:delete
POST/api/v1/accounts/{id}/contactsaccounts:write
DELETE/api/v1/accounts/{id}/contacts/{contactId}accounts:write
FieldTypeWritten byReturned byNotes
iduuid; not nullno (set by the server)list, detail, writeThe company's id.
workspace_iduuidno (set by the server)list, detail, writeThe token's workspace.
account_nametext, ≤ 200 chars; not nullcreate, update; required on createlist, detail, writeThe company's name (a rename follows onto its quotes, activities, contacts, sales and commissions). Required on create and never blank.
account_statustext, ≤ 200 charscreate, updatelist, detail, writeStatus, as text (Active, Prospect, Inactive, ...).
primary_phonephone, ≤ 40 charscreate, updatelist, detail, writeMain phone number. A new or changed number must be a phone number: a US or Canadian number (10 digits, or 1 and 10 digits) or an international number starting with +.
street_addresstext, ≤ 200 charscreate, updatedetail, writeStreet address.
street_address_2text, ≤ 200 charscreate, updatedetail, writeStreet address, second line.
citytext, ≤ 200 charscreate, updatelist, detail, writeCity.
statetext, ≤ 200 charscreate, updatelist, detail, writeState or region.
zip_codetext, ≤ 20 charscreate, updatelist, detail, writePostal code.
territorytext, ≤ 200 charscreate, updatelist, detail, writeThe company's territory, as the app types it (the territory code follows it unless territory_code is sent too). The company must stay inside the token owner's territories (its account manager or creator arm aside); moving it also moves its sales, which needs sales edit and every moved sale in the owner's sales scope.
territory_codetext, ≤ 200 charscreate, updatelist, detail, writeThe territory's code. On create, a territory-restricted owner sends it only together with territory (else 400); on an update it is kept as sent, and the company must stay inside the owner's territories (403).
zonetext, ≤ 200 charscreate, updatelist, detail, writeZone.
mfg_inttext, ≤ 200 charscreate, updatedetail, writeManufacturer interest, as text.
account_managertext, ≤ 200 charscreate, updatelist, detail, writeThe company's account manager, as the app shows it (a name, email or user id: free text). A member's key may leave it blank or set its owner, never another active member (403); with the workspace's account-manager auto-fill on, the company's sales, quotes and commissions follow it.
typetext, ≤ 200 charscreate, updatelist, detail, writeCompany type.
created_atISO 8601 timestamp; not nullno (set by the server)list, detail, writeWhen the company was created.
updated_atISO 8601 timestamp; not nullno (set by the server)list, detail, writeWhen the company last changed: send it back as PATCH's expected_updated_at.
parent_account_iduuidcreate, updatedetail, writeThe parent company (a branch's head office); null detaches it. A company the token's owner can read and edit (else 404 Linked record not found, or 403), never the company itself or one of its own descendants (422 parent_loop).
is_master_accountbooleancreate, updatedetail, writeWhether the company is a master account.
ship_to_nametext, ≤ 200 charscreate, updatedetail, writeShip-to name.
ship_to_attentiontext, ≤ 200 charscreate, updatedetail, writeShip-to attention line.
ship_to_street_addresstext, ≤ 200 charscreate, updatedetail, writeShip-to street address.
ship_to_citytext, ≤ 200 charscreate, updatedetail, writeShip-to city.
ship_to_statetext, ≤ 200 charscreate, updatedetail, writeShip-to state or region.
ship_to_zip_codetext, ≤ 20 charscreate, updatedetail, writeShip-to postal code.
ship_to_countrytext, ≤ 200 charscreate, updatedetail, writeShip-to country.

Contacts

Reads need contacts:read.

MethodPathScope
GET/api/v1/contactscontacts:read
GET/api/v1/contacts/{id}contacts:read
GET/api/v1/search/contactscontacts:read
GET/api/v1/contacts/{id}/accountscontacts:read
POST/api/v1/contactscontacts:write
PATCH/api/v1/contacts/{id}contacts:write
DELETE/api/v1/contacts/{id}contacts:delete
POST/api/v1/contacts/{id}/restorecontacts:delete
FieldTypeWritten byReturned byNotes
iduuidno (set by the server)list, detail, writeThe contact's id.
workspace_iduuidno (set by the server)list, detail, writeThe token's workspace.
first_nametext, ≤ 200 charscreate, updatelist, detail, writeFirst name.
last_nametext, ≤ 200 charscreate, updatelist, detail, writeLast name.
company_nametext, ≤ 200 charscreate, updatelist, detail, writeCompany name as text.
phonephone, ≤ 40 charscreate, updatelist, detail, writePhone number. A US or Canadian number (10 digits, or 1 and 10 digits) or an international number starting with +. Any other new or changed value (letters, an extension, a 7-digit local number) is a 400; the contact's own stored number sent back unchanged is accepted and left as stored.
titletext, ≤ 200 charscreate, updatelist, detail, writeJob title.
addresstext, ≤ 500 charscreate, updatewriteStreet address.
citytext, ≤ 200 charscreate, updatewriteCity.
statetext, ≤ 200 charscreate, updatewriteState or region.
zip_codetext, ≤ 20 charscreate, updatewritePostal code.
full_nametext, ≤ 400 charscreate, updatelist, detail, writeSplit into first_name / last_name when those are absent.
emailemail, ≤ 320 charscreate, updatelist, detail, writeEmail address. A write takes name@domain.tld: any other new or changed value is a 400; the contact's own stored email sent back unchanged is accepted when it has the name@domain shape.
tagsarray of strings, ≤ 50 of ≤ 100 charscreate, updatewriteUp to 50 tags, deduplicated.
account_iduuidnolist, detail, writeThe contact's primary company. Sending it is a 400: "Link a contact to a company with POST /api/v1/accounts/{id}/contacts."
created_atISO 8601 timestamp; not nullno (set by the server)list, detail, writeWhen the contact was created.
updated_atISO 8601 timestamp; not nullno (set by the server)list, detail, writeWhen the contact last changed.
Filter fieldOperatorsSortValue
emaileq—exact text
account_ideq, in, is_null—uuid
created_atgte, ltecreated_at, -created_atISO 8601 date or timestamp (send + as %2B); a date alone is a whole UTC day: gte from its start, lte through its end
updated_atgte, lteupdated_at, -updated_atISO 8601 date or timestamp (send + as %2B); a date alone is a whole UTC day: gte from its start, lte through its end

Quotes

Reads need quotes:read.

MethodPathScope
GET/api/v1/quotesquotes:read
GET/api/v1/quotes/{id}quotes:read
GET/api/v1/search/quotesquotes:read
GET/api/v1/quotes/{id}/itemsquotes:read
POST/api/v1/quotesquotes:write
PATCH/api/v1/quotes/{id}quotes:write
DELETE/api/v1/quotes/{id}quotes:delete
POST/api/v1/quotes/{id}/restorequotes:delete

The fields of this resource are listed in the OpenAPI description.

Activities

Reads need activities:read.

MethodPathScope
GET/api/v1/activitiesactivities:read
GET/api/v1/activities/{id}activities:read
POST/api/v1/activitiesactivities:write
PATCH/api/v1/activities/{id}activities:write
DELETE/api/v1/activities/{id}activities:delete
POST/api/v1/activities/{id}/restoreactivities:delete
FieldTypeWritten byReturned byNotes
iduuidno (set by the server)list, detail, writeThe activity's id.
workspace_iduuidno (set by the server)list, detail, writeThe token's workspace.
typetext, ≤ 80 charscreate, updatelist, detail, writeActivity type, e.g. Call, Email, Meeting, Task, Note. Defaults to Task.
subjecttext, ≤ 200 charscreate, updatelist, detail, writeSubject line.
activity_nametext, ≤ 200 charscreate, updatelist, detail, writeActivity name.
descriptiontext, ≤ 10000 charscreate, updatedetail, writeNotes, as plain text (newlines kept).
accounttext, ≤ 200 charscreate, updatelist, detail, writeCompany name as text.
contacttext, ≤ 200 charscreate, updatelist, detail, writeContact name as text.
manufacturertext, ≤ 200 charscreate, updatelist, detail, writeManufacturer name as text.
end_usertext, ≤ 200 charscreate, updatelist, detail, writeEnd user name.
end_user_contacttext, ≤ 200 charscreate, updatelist, detail, writeEnd user contact name.
manufacturer_contacttext, ≤ 200 charscreate, updatelist, detail, writeManufacturer contact name.
assigned_touuidcreate, updatelist, detail, writeA user id in the token's workspace.
account_iduuidcreate, updatelist, detail, writeThe linked company.
contact_iduuidcreate, updatelist, detail, writeThe linked contact.
manufacturer_iduuidcreate, updatelist, detail, writeThe linked manufacturer.
quote_iduuidcreate, updatelist, detail, writeThe linked quote.
sale_iduuidcreate, updatelist, detail, writeThe linked sale.
activity_dateISO 8601 datecreate, updatelist, detail, writeISO 8601 date or timestamp.
due_dateISO 8601 datecreate, updatelist, detail, writeISO 8601 date or timestamp.
reminder_atISO 8601 timestampcreate, updatelist, detail, writeISO 8601 date or timestamp.
completedbooleanupdatelist, detail, writeWhether the activity is done; empty (null) counts as not done in the app.
prioritylow / medium / high (any case); or null ("" too)updatelist, detail, writelow, medium or high (any case); empty clears it, and an empty priority (null) counts as medium in the app.
bodytextnodetail, writeSynced mail body, as plain text.
updated_atISO 8601 timestamp; not nullno (set by the server)list, detail, writeWhen the activity last changed.
created_atISO 8601 timestamp; not nullno (set by the server)list, detail, writeWhen the activity was created.
Filter fieldOperatorsSortValue
typeeq—exact text
assigned_toeq—uuid
account_ideq, in, is_null—uuid
contact_ideq, in, is_null—uuid
manufacturer_ideq, in, is_null—uuid
quote_ideq, in, is_null—uuid
sale_ideq, in, is_null—uuid
due_dategte, lte, is_nulldue_date, -due_date (empty last)date, YYYY-MM-DD
completedeq, is_null—true / false
priorityeq, in, is_null—one of low / medium / high (exact)
updated_atgte, lteupdated_at, -updated_atISO 8601 date or timestamp (send + as %2B); a date alone is a whole UTC day: gte from its start, lte through its end
created_atgte, ltecreated_at, -created_atISO 8601 date or timestamp (send + as %2B); a date alone is a whole UTC day: gte from its start, lte through its end

Manufacturers

Reads need manufacturers:read.

MethodPathScope
GET/api/v1/manufacturersmanufacturers:read
GET/api/v1/manufacturers/{id}manufacturers:read
POST/api/v1/manufacturersmanufacturers:write
PATCH/api/v1/manufacturers/{id}manufacturers:write
DELETE/api/v1/manufacturers/{id}manufacturers:delete
FieldTypeWritten byReturned byNotes
iduuid; not nullno (set by the server)list, detail, writeThe manufacturer's id.
workspace_iduuidno (set by the server)list, detail, writeThe token's workspace.
manufacturer_nametext, ≤ 200 chars; not nullcreate, update; required on createlist, detail, writeThe manufacturer's name, unique in the workspace (a rename follows onto its quotes, sales, activities, commissions, products, inventory and the opportunities' principal lists). One name: a semicolon, a vertical bar or a line break in it is a 400 (the territory / manufacturer scope reads them as separators between names), and a name another manufacturer in the workspace has ignoring case, a soft-deleted one included, is a 409.
parent_manufacturer_iduuidnolist, detail, writeThe parent manufacturer (set in the app).
terms_and_conditionstext, ≤ 10000 charscreate, updatelist, detail, writeTerms and conditions, as plain text (newlines kept).
mfg_territorytext, ≤ 200 charscreate, updatelist, detail, writeThe territory the manufacturer belongs to; it must stay inside the token owner's territories.
expected_salesamount, ≤ 2 decimals, ≥ 0, ≤ 1000000000000; or null ("" too)create, updatelist, detail, writeExpected annual sales.
primary_phonephone, ≤ 40 charscreate, updatelist, detail, writeMain phone number.
citytext, ≤ 200 charscreate, updatelist, detail, writeCity.
statetext, ≤ 200 charscreate, updatelist, detail, writeState or region.
zip_codetext, ≤ 20 charscreate, updatelist, detail, writePostal code.
regional_managertext, ≤ 200 charscreate, updatelist, detail, writeThe manufacturer's regional manager, as text.
updated_atISO 8601 timestamp; not nullno (set by the server)list, detail, writeWhen the manufacturer last changed. Send it back as PATCH's expected_updated_at.
Filter fieldOperatorsSortValue
id—id, -iduuid
parent_manufacturer_ideq, in, is_null—uuid
mfg_territoryeq—exact text

Products

Reads need products:read.

MethodPathScope
GET/api/v1/productsproducts:read
GET/api/v1/products/{id}products:read
POST/api/v1/productsproducts:write
PATCH/api/v1/products/{id}products:write
DELETE/api/v1/products/{id}products:delete
POST/api/v1/products/{id}/restoreproducts:delete
FieldTypeWritten byReturned byNotes
iduuidno (set by the server)list, detail, writeThe product's id.
workspace_iduuidno (set by the server)list, detail, writeThe token's workspace.
stockboolean; or nullcreate, updatelist, detail, writeWhether the product is a stocked item. true, false or null.
manufacturer_nametext, ≤ 200 chars; not nullcreate, update; required on createlist, detail, writeThe manufacturer's name as text: with part_number, the product's catalog key in the workspace, and what a token owner limited to some manufacturers is matched by. Required on create, never empty; one name (no semicolon, vertical bar or line break). The product must stay inside the token owner's manufacturer scope (403 otherwise).
part_numbertext, ≤ 200 chars; not nullcreate, update; required on createlist, detail, writePart number: with manufacturer_name, the product's catalog key in the workspace. Required on create, never empty.
product_familytext, ≤ 200 charscreate, updatelist, detail, writeProduct family.
product_linetext, ≤ 200 charscreate, updatelist, detail, writeProduct line.
root_part_notext, ≤ 200 charscreate, updatelist, detail, writeRoot part number.
list_priceamount, ≤ 4 decimals, ≥ 0, ≤ 9999999999; or nullcreate, updatelist, detail, writeList price. A number (or decimal text) from 0, at most 4 decimal places. Setting it (create) or changing it (update) needs the token owner's Edit pricing ability (403 otherwise); null sets no price.
stock_priceamount, ≤ 4 decimals, ≥ 0, ≤ 9999999999; or nullcreate, updatelist, detail, writeStock price. A number (or decimal text) from 0, at most 4 decimal places. Setting it (create) or changing it (update) needs the token owner's Edit pricing ability (403 otherwise); null sets no price.
commission_rateamount, ≤ 6 decimals, ≥ 0, ≤ 1; or nullcreate, updatelist, detail, writeCommission rate as a fraction (0.08 = 8%). A number (or decimal text) from 0 to 1, at most 6 decimal places (0.08 = 8%; "8%" is refused). Setting it (create) or changing it (update) needs the token owner's Edit pricing ability (403 otherwise); null sets no price.
lead_timetext, ≤ 200 charscreate, updatelist, detail, writeLead time as text.
upctext, ≤ 200 charscreate, updatelist, detail, writeUPC code.
uomtext, ≤ 50 charscreate, updatelist, detail, writeUnit of measure.
hou_stockinteger, ≥ 0, ≤ 2147483647; or nullcreate, updatelist, detail, writeStock on hand in the first location stock column. Usually 0 or empty in a workspace that does not record stock here. A whole number from 0, or null.
pharr_stockinteger, ≥ 0, ≤ 2147483647; or nullcreate, updatelist, detail, writeStock on hand in the second location stock column. Usually 0 or empty in a workspace that does not record stock here. A whole number from 0, or null.
reorder_levelinteger, ≥ 0, ≤ 2147483647; or nullcreate, updatelist, detail, writeReorder level. A whole number from 0, or null.
shipping_weightamount, ≤ 4 decimals, ≥ 0, ≤ 1000000; or nullcreate, updatelist, detail, writeShipping weight. A number (or decimal text) from 0 to 1,000,000, at most 4 decimal places, or null.
unit_costamount, ≤ 4 decimals, ≥ 0, ≤ 9999999999; or nullcreate, updatelist, detail, writeUnit cost. Returned only to a token whose owner is an admin or a manager (has reports). Only for a token whose owner is an admin or a manager (for any other owner it is an unknown field: 400). A number (or decimal text) from 0, at most 4 decimal places. Setting it (create) or changing it (update) needs the token owner's Edit pricing ability (403 otherwise); null sets no price.
descriptiontext, ≤ 2000 charscreate, updatelist, detail, writeDescription.
price_codetext, ≤ 50 charscreate, updatelist, detail, writePrice code. Compared as text: "a" is a change from "A". Setting it (create) or changing it (update) needs the token owner's Edit pricing ability (403 otherwise); null sets no price.
image_urlhttp(s) URL (no control or invisible character), ≤ 2000 charscreate, updatelist, detail, writeImage link (http or https).
specification_urlhttp(s) URL (no control or invisible character), ≤ 2000 charscreate, updatelist, detail, writeSpecification sheet link (http or https).
notestext, ≤ 10000 charscreate, updatelist, detail, writeNotes.
created_timetextnolist, detail, writeWhen the product was created, as a legacy import recorded it (text; read only).
modified_timetextnolist, detail, writeWhen the product was last modified, as a legacy import recorded it (text; read only).
created_atISO 8601 timestamp; not nullno (set by the server)list, detail, writeWhen the product was created.
updated_atISO 8601 timestamp; not nullno (set by the server)list, detail, writeWhen the product last changed.

Leads

Reads need leads:read.

MethodPathScope
GET/api/v1/leadsleads:read
GET/api/v1/leads/{id}leads:read
POST/api/v1/leadsleads:write
PATCH/api/v1/leads/{id}leads:write
DELETE/api/v1/leads/{id}leads:delete
POST/api/v1/leads/{id}/restoreleads:delete
POST/api/v1/leads/{id}/convertleads:write
FieldTypeWritten byReturned byNotes
iduuidno (set by the server)list, detail, writeThe lead's id.
workspace_iduuidno (set by the server)list, detail, writeThe token's workspace.
companytext, ≤ 200 charscreate, updatelist, detail, writeThe company the lead is for. Defaults to an empty string; null stores an empty string.
contact_nametext, ≤ 200 charscreate, updatelist, detail, writeThe person at the company.
titletext, ≤ 200 charscreate, updatelist, detail, writeTheir job title.
emailemail, ≤ 320 charscreate, updatelist, detail, writeTheir email address.
phonephone, ≤ 50 charscreate, updatelist, detail, writeTheir phone number.
sourcetext, ≤ 120 charscreate, updatelist, detail, writeWhere the lead came from (Website, Trade Show, Referral, ...).
statusNew / Attempting Contact / Qualified / Quoted / Lost / Disqualified / No Responsecreate, updatelist, detail, writeWhere the lead stands. Defaults to New. Converted is set only by POST /api/v1/leads/{id}/convert.
priorityHot / Warm / Coldcreate, updatelist, detail, writeHot, Warm or Cold. Defaults to Warm.
assigned_touuidcreate, updatelist, detail, writeThe user who owns the lead (a user id in the token's workspace). Empty unless set. An active user of the workspace (else 404 Linked record not found, or 422 assignee_inactive); a member's token may not assign a lead to another member (403).
territorytext, ≤ 120 charscreate, updatelist, detail, writeThe lead's territory, as text (a territory code or name). The lead must stay inside the token owner's lead scope (403).
manufacturer_interesttext, ≤ 1000 charscreate, updatelist, detail, writeThe manufacturers the lead is interested in, as text (names separated by semicolons).
account_iduuidcreate, updatelist, detail, writeThe company record the lead is linked to. One the token's owner can read (else 404 Linked record not found). null unlinks.
contact_iduuidcreate, updatelist, detail, writeThe lead's primary contact record. One the token's owner can read (else 404 Linked record not found). null unlinks.
manufacturer_iduuidcreate, updatelist, detail, writeThe manufacturer record the lead is linked to. One the token's owner can read (else 404 Linked record not found). null unlinks.
next_follow_upISO 8601 datecreate, updatelist, detail, writeThe next follow-up date (YYYY-MM-DD).
estimated_valueamount, ≤ 2 decimals, ≥ 0, ≤ 9999999999.99create, updatelist, detail, writeThe lead's estimated value. Defaults to 0.
notestext, ≤ 10000 charscreate, updatelist, detail, writeNotes, as plain text.
last_touch_atISO 8601 timestampno (set by the server)list, detail, writeWhen the lead was last touched (set by the server).
created_atISO 8601 timestamp; not nullno (set by the server)list, detail, writeWhen the lead was created.
updated_atISO 8601 timestamp; not nullno (set by the server)list, detail, writeWhen the lead last changed.

Sales

Reads need sales:read.

MethodPathScope
GET/api/v1/salessales:read
GET/api/v1/sales/{id}sales:read

The fields of this resource are listed in the OpenAPI description.

Commissions

Reads need commissions:read.

MethodPathScope
GET/api/v1/commissionscommissions:read
GET/api/v1/commissions/{id}commissions:read

The fields of this resource are listed in the OpenAPI description.

Inventory

Reads need inventory:read.

MethodPathScope
GET/api/v1/inventoryinventory:read
GET/api/v1/inventory/{id}inventory:read
GET/api/v1/inventory/{id}/movementsinventory:read
GET/api/v1/inventory/{id}/balancesinventory:read
GET/api/v1/inventory/locationsinventory:read
POST/api/v1/inventoryinventory:write
PATCH/api/v1/inventory/{id}inventory:write
DELETE/api/v1/inventory/{id}inventory:delete
POST/api/v1/inventory/{id}/restoreinventory:delete
POST/api/v1/inventory/{id}/movementsinventory:stock
POST/api/v1/inventory/{id}/moveinventory:stock
PATCH/api/v1/inventory/{id}/balancesinventory:stock
POST/api/v1/inventory/locationsinventory:stock
FieldTypeWritten byReturned byNotes
iduuidno (set by the server)list, detail, writeThe item's id.
workspace_iduuidno (set by the server)list, detail, writeThe token's workspace.
item_nametext, ≤ 200 charscreate, updatelist, detail, writeItem name.
manufacturertext, ≤ 200 charscreate, updatelist, detail, writeManufacturer name as text; must be in the key owner's manufacturer scope when they have one.
part_numbertext, ≤ 200 charscreate, updatelist, detail, writePart number.
descriptiontext, ≤ 2000 charscreate, updatelist, detail, writeDescription.
houston_stockinteger, ≥ 0, ≤ 1000000create, updatelist, detail, writeStock on hand, a whole number. Defaults to 0 on create. On an ERP-linked item a change is a count at the ERP's main location and needs expected_houston_stock.
bin_locationtext, ≤ 200 charscreate, updatelist, detail, writeBin or shelf location.
assigned_totext, ≤ 200 charscreate, updatelist, detail, writeWho holds the item, as the name the app shows (the own-records lock reads it).
last_modified_bytextno (set by the server)list, detail, writeWho last changed the item (set by the server).
created_atISO 8601 timestamp; not nullno (set by the server)list, detail, writeWhen the item was created.
updated_atISO 8601 timestamp; not nullno (set by the server)list, detail, writeWhen the item last changed.

Samples

Reads need samples:read.

MethodPathScope
GET/api/v1/samplessamples:read
GET/api/v1/samples/{id}samples:read
POST/api/v1/samplessamples:write
PATCH/api/v1/samples/{id}samples:write
DELETE/api/v1/samples/{id}samples:delete
POST/api/v1/samples/{id}/restoresamples:delete
FieldTypeWritten byReturned byNotes
iduuidno (set by the server)list, detail, writeThe sample's id.
workspace_iduuidno (set by the server)list, detail, writeThe token's workspace.
manufacturertext, ≤ 200 charscreate, updatelist, detail, writeManufacturer name as text.
part_numbertext, ≤ 200 charscreate, updatelist, detail, writePart number.
descriptiontext, ≤ 2000 charscreate, updatelist, detail, writeDescription.
locationtext, ≤ 200 charscreate, updatelist, detail, writeWhere the sample is kept (a city or office).
houston_stockinteger, ≥ 0, ≤ 2147483647create, updatelist, detail, writeHow many are on hand, a whole number. Defaults to 0 on create.
bin_locationtext, ≤ 200 charscreate, updatelist, detail, writeBin or shelf location.
assigned_totext, ≤ 200 charscreate, updatelist, detail, writeWho has the sample checked out, as the name the app shows (free text). Setting it checks the sample out now; clearing it checks it back in.
workflow_stateavailable / requested / approved / checked_out / returned / lost / damagedcreate, updatelist, detail, writeWhere the sample is in its checkout workflow. lost, damaged, requested and approved are kept as sent; any other state is set from assigned_to (checked_out when someone has it, else available), as the app does.
linked_account_iduuidcreate, updatelist, detail, writeThe company the sample is for: one the token's owner can read (else 404 Linked record not found; an owner without accounts read: 403, whatever the id). null unlinks.
linked_contact_iduuidcreate, updatelist, detail, writeThe contact the sample is for: one the token's owner can read (else 404 Linked record not found; an owner without contacts read: 403, whatever the id). null unlinks.
updated_atISO 8601 timestamp; not nullno (set by the server)list, detail, writeWhen the sample last changed.
created_atISO 8601 timestamp; not nullno (set by the server)list, detail, writeWhen the sample was created.

Line Sheets

Reads need documents:read.

MethodPathScope
GET/api/v1/line-sheetsdocuments:read
GET/api/v1/line-sheets/{id}documents:read
POST/api/v1/line-sheetsline_sheets:write
PATCH/api/v1/line-sheets/{id}line_sheets:write
FieldTypeWritten byReturned byNotes
iduuidno (set by the server)list, detail, writeThe line sheet's id.
workspace_iduuidno (set by the server)list, detail, writeThe token's workspace.
titletext, ≤ 200 chars; not nullcreate, update; required on createlist, detail, writeThe line sheet's title.
reference_codetext, ≤ 64 chars; not nullcreate, updatelist, detail, writeStored in upper case; any run of characters other than A-Z, 0-9, ., _ and - becomes one -. Made from the title when a create leaves it out. On create a code another sheet in the workspace has gets the next free -2, -3, ... suffix; on update it is a 409.
descriptiontext, ≤ 2000 charscreate, updatelist, detail, writeA description, as plain text.
categorytext, ≤ 200 charscreate, updatelist, detail, writeCategory, e.g. Territory Line Sheet, Product Brochure, Stock Sheet.
product_familytext, ≤ 200 charscreate, updatelist, detail, writeProduct family.
territory_codesarray of strings, ≤ 50 of ≤ 100 charscreate, updatelist, detail, writeTerritory codes, stored in upper case; an entry holding commas, semicolons or line breaks is split.
tagsarray of strings, ≤ 50 of ≤ 100 charscreate, updatelist, detail, writeTags; an entry holding commas, semicolons or line breaks is split.
manufacturer_iduuidcreate, updatelist, detail, writeThe linked manufacturer: one in the token's workspace that is not deleted.
source_kindshared_path / external_url / uploaded_fileno (set by the server)list, detail, writeWhere the file is: external_url (a web link), shared_path (a file-share path, returned as its file name only) or uploaded_file (uploaded in the app). Always external_url for a sheet the API creates or re-points.
source_urlhttps URL (no user name or password, no control or invisible character), ≤ 2000 chars; not nullcreate, update; required on createlist, detail, writeThe web link. Another sheet in the workspace with the same link (ignoring case) is a 409. Sending it makes the sheet a web link; an uploaded sheet's file cannot be replaced through the API (422).
file_nametextno (set by the server)list, detail, writeAn uploaded sheet's file name.
mime_typetextno (set by the server)list, detail, writeAn uploaded sheet's file type.
file_sizeintegerno (set by the server)list, detail, writeAn uploaded sheet's size in bytes.
activebooleancreate, updatelist, detail, writefalse archives the sheet (archived_at is stamped); true brings it back. A new sheet is active unless the create says false.
featuredbooleancreate, updatelist, detail, writeWhether the sheet is featured. Defaults to false.
created_by_nametextno (set by the server)list, detail, writeWho created the sheet.
created_atISO 8601 timestamp; not nullno (set by the server)list, detail, writeWhen the sheet was created.
updated_atISO 8601 timestamp; not nullno (set by the server)list, detail, writeWhen the sheet last changed.
archived_atISO 8601 timestampno (set by the server)list, detail, writeWhen the sheet was archived (empty while active).
Filter fieldOperatorsSortValue
manufacturer_ideq, in, is_null—uuid
source_kindeq, in—one of shared_path / external_url / uploaded_file (exact)
activeeq—true / false
featuredeq—true / false
created_atgte, ltecreated_at, -created_atISO 8601 date or timestamp (send + as %2B); a date alone is a whole UTC day: gte from its start, lte through its end
updated_atgte, lteupdated_at, -updated_atISO 8601 date or timestamp (send + as %2B); a date alone is a whole UTC day: gte from its start, lte through its end

Team Directory

Any valid key can read these.

MethodPathScope
GET/api/v1/usersAny valid key
GET/api/v1/users/{id}Any valid key
FieldTypeReturned byNotes
iduuidlist, detailThe user's id (an assigned_to id names it).
user_nametextlist, detailThe user's display name.
emailemaillist, detailThe user's email address.
statustext; not nulllist, detailThe user's status as stored (Active, Inactive, ...); active says whether it lets them sign in.
created_atISO 8601 timestamp; not nulllist, detailWhen the user was added.
updated_atISO 8601 timestamp; not nulllist, detailWhen the user last changed.
Filter fieldOperatorsSortValue
statuseq—exact text
created_at—created_at, -created_atISO 8601 date or timestamp (send + as %2B); a date alone is a whole UTC day: gte from its start, lte through its end
updated_at—updated_at, -updated_atISO 8601 date or timestamp (send + as %2B); a date alone is a whole UTC day: gte from its start, lte through its end

Opportunities

Reads need opportunities:read.

MethodPathScope
GET/api/v1/opportunitiesopportunities:read
GET/api/v1/opportunities/{id}opportunities:read
POST/api/v1/opportunitiesopportunities:write
PATCH/api/v1/opportunities/{id}opportunities:write
DELETE/api/v1/opportunities/{id}opportunities:delete
POST/api/v1/opportunities/{id}/restoreopportunities:delete
PUT/api/v1/opportunities/{id}/quotes/{quoteId}opportunities:write
DELETE/api/v1/opportunities/{id}/quotes/{quoteId}opportunities:write
FieldTypeWritten byReturned byNotes
nametext, ≤ 200 chars; not nullcreate, update; required on createlist, detail, writeThe project's name.
account_iduuidcreate, updatelist, detail, writeThe project's company (a company id in the token's workspace), or null.
contact_iduuidcreate, updatelist, detail, writeThe project's contact (a contact id the key can read), or null.
manufacturersarray of strings, ≤ 25 of ≤ 200 charscreate, updatelist, detail, writeManufacturer names the project is for (deduplicated); they decide its manufacturer scope.
estimated_valueamount, ≤ 2 decimals, ≥ 0, ≤ 999999999999.99create, updatelist, detail, writeThe estimate, in the workspace currency. Counted in the pipeline until a quote is linked.
stagetext, ≤ 80 charscreate, updatelist, detail, writeThe stage, as configured in the workspace's project stages.
win_probabilityamount, ≤ 2 decimals, ≥ 0, ≤ 100; or nullcreate, updatelist, detail, writeWin % (0 to 100), or null to follow the stage's percent.
expected_closeISO 8601 datecreate, updatelist, detail, writeExpected close date, YYYY-MM-DD.
owner_user_iduuidcreate, updatelist, detail, writeThe owner (an active user in the token's workspace). A create without one is owned by the key's owner.
sourcetext, ≤ 120 charscreate, updatelist, detail, writeWhere the project came from.
next_steptext, ≤ 500 charscreate, updatelist, detail, writeThe next step.
notestext, ≤ 4000 charscreate, updatelist, detail, writeNotes.
lost_reasontext, ≤ 200 charscreate, updatelist, detail, writeWhy it was lost; kept only on a move into a Lost stage, cleared on any other stage.
lost_competitortext, ≤ 200 charscreate, updatelist, detail, writeWho it was lost to; kept only with a Lost stage, like lost_reason.
iduuidno (set by the server)list, detail, writeThe project's id.
accounttextno (set by the server)list, detail, writeThe company's name, copied from the company.
contacttextno (set by the server)list, detail, writeThe contact's name, copied from the contact.
closed_atISO 8601 timestampno (set by the server)list, detail, writeWhen it was decided (Won or Lost), else null.
created_atISO 8601 timestamp; not nullno (set by the server)list, detail, writeWhen the project was created.
updated_atISO 8601 timestamp; not nullno (set by the server)list, detail, writeWhen the project last changed.
Filter fieldOperatorsSortValue
account_ideq, in, is_null—uuid
contact_ideq, in, is_null—uuid
stageeq, is_null—exact text
expected_closegte, lte, is_nullexpected_close, -expected_close (empty last)date, YYYY-MM-DD
owner_user_ideq, in, is_null—uuid
created_at—created_at, -created_atISO 8601 date or timestamp (send + as %2B); a date alone is a whole UTC day: gte from its start, lte through its end
updated_at—updated_at, -updated_atISO 8601 date or timestamp (send + as %2B); a date alone is a whole UTC day: gte from its start, lte through its end

Support

Questions, or a request that does not behave as described here? Email support@jmcmahanllc.com with the request's requestId.