Description
n8n-nodes-brightpearl
An n8n community node for the Brightpearl REST API. Covers sales orders, products, price lists, and order custom fields. Works as a standard n8n node and is usableAsTool for AI agents. (AI agents are currently untested with it.)
Disclaimer
Most of the “code” portion of modifying the template into this was written with Claude in a day. Sort of a mixture of proof of concept and making something that works for some quick features I needed. I feel it’s important to note that while I at best provided direction, it did the work of modifying things to ensure it would work with n8n properly. (I had done an attempt before, but some docs were out of date, so I fed what I had into Claude and let it do the rest.)
Claude did attempt to incorporate the rate limit handling per the API docs, but this is an untested option that I am not sure how n8n will operate with as of yet.
BREAKING CHANGES
v0.21.0 Restructures some nodes to make them easier to use in the future. If you see an error, after updating the node, restart your n8n instance in case the workers are using the outdated version.
Migration for existing workflows
Any workflow using one of these old Order operations needs a manual update:
Old (Order resource) New
Order → Add Note Order Note → Create
Order → Get Custom Fields Order Custom Field → Get
Order → Get Custom Field Metadata Order Custom Field → Get Metadata
Order → Update Custom Fields Order Custom Field → Update
Installation
In your n8n instance:
Settings → Community Nodes → Install and enter:
n8n-nodes-brightpearl
Or via CLI on a self-hosted instance:
npm install n8n-nodes-brightpearl
See Cloud Note for more information when it comes to n8n cloud, but TL;DR, I’m using self hosted, so it has a few options that may not work on n8n Cloud.
Authentication
The node supports both Brightpearl auth modes — pick one via the Authentication field at the top of the node:
Private App (three-header auth)
Use this for internal integrations on your own account. Headers sent:
brightpearl-account-tokenbrightpearl-app-refbrightpearl-staff-tokenbrightpearl-app-refbrightpearl-dev-ref- Get — fetch order(s) via
/sales-order/{id}. Rich response includesorderStatus.name. A Simplify toggle (default on) flattens it into a cleaner shape withstatusId/statusNameat the top level, rows as an array, etc. Accepts an ID set (single, ascending range100-200, or comma list1,2,3) — each order returns as its own output item. - Get (Order Endpoint) — same data via the generic
/order/{id}endpoint (also includes status name and supports Simplify + ID sets). Use whichever endpoint your workflow prefers; results are equivalent for sales orders. - Get Many — search sales orders with column-based filters; results should be auto-enriched with reference data labels (e.g.
orderStatusId: 5gainsorderStatusName: "Complete - Cancelled") - Create — create a new sales order with rows Currently Untested Please let me know if you do test this functionality.
- Update Status — change order status, optionally with a note
- Create — add a note to an order via
POST /order-service/order/{orderId}/note. OptionalisPublic,contactId,fileId,addedOn. - Get Metadata — list every order custom field definition (code, name, type, and for SELECT/list fields the available option IDs + labels). Run this first to discover what to send in Update.
- Get — read all custom fields set on a specific order
- Update — set or remove custom fields via JSON Patch. Two Input Modes:
- Get — fetch a single product by ID
- Get Many — search products
- Create — create a new product Currently Untested Please let me know if you do test this functionality.
- Create — add a row to an existing order via
POST /order-service/order/{orderId}/row(productId + quantity required, optional net/tax/taxCode/productPrice/nominalCode/discountPercentage) - Update — modify an existing row via
PATCH /order-service/order/{orderId}/row/{rowId}with a JSON Patch body - Delete — remove a row via
DELETE /order-service/order/{orderId}/row/{rowId} - Get — fetch one or more contacts by ID via
/contact-service/contact/{ids}. ID set syntax supported. - Get Many — search contacts via
/contact-service/contact-searchwith filters (name, company, email, phone, isCustomer/isSupplier/isStaff flags, date ranges), columns, sort, pagination, batching. - Get Product Availability — fetch on-hand / available / allocated / in-transit stock for one or more products via
/warehouse-service/product-availability/{ids}(all warehouses) or/warehouse-service/warehouse/{id}/product-availability/{ids}(single warehouse). Accepts ID sets. - Get Many — list all warehouses on the account; useful for discovering warehouse IDs.
- Get Many — list all price lists on the account Currently Untested Please let me know if you do test this functionality.
- Get Product Prices — get a product’s prices on a specific price list Currently Untested Please let me know if you do test this functionality.
- Set Product Price — set or update a product’s price (with optional quantity-break tiers) Currently Untested Please let me know if you do test this functionality.
- HTTP 503 (quota exhausted) — waits the number of seconds in the
brightpearl-throttle-timeheader before retrying - HTTP 429 (burst limit) — waits the number of seconds in the
Retry-Afterheader - Up to 5 retries per request, with a single wait capped at 60 seconds
orderStatusId: 5→orderStatusName: "Complete - Cancelled"- Brightpearl API documentation
- n8n community nodes documentation
| Credential field | Where to find it |
|—|—|
| Account Code | The subdomain part of your Brightpearl URL |
| Datacenter Hostname | Match your account URL (e.g. use1.brightpearlconnect.com) |
| App Reference | Set when you create the private app under Apps → Private Apps |
| Account Token | Issued when the private app is created |
| Staff Token | The staff token for the user the app runs as |
OAuth2 (public app)
For published apps that need user-authorized access. Standard OAuth2 authorization-code flow against Brightpearl’s endpoints, plus app-ref/dev-ref headers alongside the Bearer token.
Note: If you plan to use the oauth2 when using it with a generic http request node, you’ll need to add two headers manually:
| Credential field | Where to find it |
|—|—|
| Account Code | The target account’s code (used to build the per-account authorize/token URLs) |
| Datacenter Hostname | Datacenter for API calls |
| App Reference | Your registered app reference |
| Developer Reference | Your developer reference (required for public apps) |
| Client ID / Client Secret | From your Brightpearl app registration |
n8n handles the OAuth handshake (authorize URL https://oauth.brightpearl.com/authorize/{account}, token URL https://oauth.brightpearlapp.com/token/{account}) and the refresh-token cycle. The node injects brightpearl-app-ref and brightpearl-dev-ref alongside the Bearer token automatically.
Supported Operations
Order
> v0.21.0 breaking change: Add Note, Get Custom Fields, Get Custom Field Metadata, and Update Custom Fields moved out of the Order resource into their own top-level resources (Order Note, Order Custom Field). If you have workflows using the old Order operations for these, update the Resource dropdown.
Order Note
Order Custom Field
– Builder — entries with an Operation (Add/Replace/Remove), Field Code, Value Type (Text/Date, Number, Boolean, List/Select), and Value. The Value Type ensures the correct JSON type is sent — a mismatch makes Brightpearl return a 500. For List/Select enter the numeric option ID (from Get Metadata).
– Raw JSON Patch — paste a complete RFC 6902 patch array yourself, e.g. [{ "op": "add", "path": "/PCF_SHIPPEDD", "value": "={{ $json.ShippedDate }}" }]. Expressions work inside string values.
Product
Order Row
Contact
Warehouse
Price List
Rate Limiting
Brightpearl enforces a per-account quota. The node handles rate limits automatically:
This is transparent to your workflow — if a transient throttle hits, the node sleeps and tries again with no extra configuration needed.
For batch workloads that intentionally pace themselves (e.g. updating thousands of orders), layer your own Wait node into the workflow. The in-node retry covers transient throttling, not long-term pacing.
> Note on n8n Cloud: the rate-limit retry uses node:timers/promises for sleeping, which n8n Cloud’s sandbox doesn’t allow. This package is therefore configured for self-hosted n8n and is not verifiable for n8n Cloud. If you specifically need Cloud verification, remove the retry loop from GenericFunctions.ts and switch eslint.config.mjs back to the config export from @n8n/node-cli/eslint.
Reference Data Enrichment
Brightpearl search endpoints return rows as positional arrays plus a top-level reference block mapping coded values (status IDs, etc.) to display names. This node converts results to keyed objects and, for any column that declares referenceData, adds a sibling field with the resolved label:
There should also be an option to return the raw output if that is helpful for your use case.
Columns ending in Id get a Name counterpart; other columns get a Label suffix. The resolution is automatic for any column Brightpearl flags with reference data.
Links
License
MIT