Choosing an endpoint
Open in the interactive reference
Many resources offer more than one way to do the same thing: a read by id, a collection and a search, and for some resources bulk writes or events.
The choice decides which filters you can use, whether you get list records or full records, and how many requests a job takes.
Common jobs
Each row names the endpoint to call and the section with the detail.
| To | Call | See |
|---|---|---|
| List or scan records | GET /x |
Pagination and querying |
| Find a record by its name or number | POST /x/search |
Reading records |
| Download a file a record carries | GET /public/files/{handle} |
Files |
| Send a file, such as an attachment | POST /public/files/{namespace}/{operationId}, then the endpoint with the upload reference |
Files |
Read a record another record points to, such as customerId |
GET /customers/{id} as a second request. No endpoint can include related records. |
Reading records |
| Sync the changes since your last run | GET /x?filter[lastModifiedDate][gte]=…&sort=lastModifiedDate. People absences and absence types don't return lastModifiedDate. Deleted records don't appear; see Deleted records. |
Pagination and querying |
| Export every record | A paging loop over GET /x. A walk ends after about 100,000 records, so narrow larger exports with a filter. |
Pagination and querying |
| Create or change a record, then check it | POST or PATCH, then GET /x/{id} |
Writes |
| Create or delete many records at once | POST /x/bulk or /bulk-delete, where the resource has one. Inventory and some project endpoints do. |
Bulk writes |
| React to changes as they happen | Subscribe to events. Invoices, journal entries and people publish them. For other records, sync on a schedule. | Webhooks |
| Retry a write safely after a timeout | Send an Idempotency-Key header. Almost every write accepts it, and one that doesn't lists IDEMPOTENCY_NOT_SUPPORTED. |
Idempotency |
Reading: by id, the collection or search
Check the resource's endpoint list first. Many resources offer both a collection, GET /x, and a search, POST /x/search. When a resource has both, choose in this order:
- You know the id: use
GET /x/{id}. - You match text, such as a name, email or number, or pass several values for one filter: use
POST /x/search. Its filters travel in the request body. - You list or sync records, filtering on ids, statuses or dates: use
GET /x. - Still unsure: use search. It returns full records, and its filters sit in the body rather than the query string.
Collections that page differently
Twelve collections don't follow Pagination and querying. They take pageSize and a cursor as plain query parameters, return the records in data.items, and ignore page[…], filter[…], sort and fields without an error. Each one's description says so.
| Collection | Cursor | Changed since |
|---|---|---|
GET crm/opportunities, crm/prospects, crm/quotes |
cursor |
modifiedFrom, modifiedTo |
GET accounting/refunds, accounting/sales-order-shipments |
cursor |
modifiedFrom, modifiedTo |
GET accounting/usages |
cursor |
lastModifiedFrom |
GET accounting/performance-obligations/{id}/products |
cursor |
— |
GET accounting/books/{bookId}/entity-assignments |
page |
— |
GET base/custom-dimensions, base/custom-dimensions/{customDimensionUuid}/values |
cursor |
— |
GET psa/expenses/budgets |
cursor |
— |
GET psa/expenses/summary |
pageCursor |
— |
Examples
Which read to use
GET /accounting/customers/{id} id known
POST /accounting/customers/search a name, or several values
GET /accounting/customers ids, statuses or dates