Register a ConnectWise webhook callback via the REST API (Postman or cURL) to trigger Field Nation work order creation on ticket status change.
A callback is the webhook that tells Field Nation a ticket is ready: when a ticket reaches your trigger status, ConnectWise posts the ticket ID to your Field Nation trigger URL, and the connector creates or updates the work order.
Not familiar with REST APIs? This step requires your ConnectWise administrator or a developer. Share this guide with them and hand off your Field Nation Trigger URL (from connector Settings) — it's a one-time setup.
System callbacks are managed through the ConnectWise REST API — most instances have no Callbacks setup-table UI. Cloud-hosted ConnectWise instances typically do not expose a callback management screen, and API members often lack permission to manage callbacks from the UI even when one exists. This guide uses the REST API (Postman or cURL) as the primary, supported method. A UI fallback is noted at the end for the rare instances that have it.
Complete Configuration Steps 1–5 before continuing. You need your Field Nation trigger URL, your API credentials, and a ConnectWise clientId (generated below) to finish this guide.
Get a ConnectWise clientId first. Every ConnectWise REST API call needs a clientId header — a value you generate on the ConnectWise Developer Network, which is separate from your ConnectWise PSA login:
clientId header on every request below.Before registering the callback, collect these values:
| Value | Where to find it |
|---|---|
| Field Nation trigger URL | Field Nation → Integrations → Field Services → ConnectWise → Manage → Settings → Trigger URL. Copy it exactly — it is environment-specific (see below) and contains a security token. |
| ConnectWise host | Your instance host, e.g. api-na.myconnectwise.net |
| Company | Your login company identifier (e.g. acme_corp) — see the Company tip in Configuration Step 4 for three ways to confirm the correct value. Used in API auth. |
| Public Key | From the API member's API Keys tab |
| Private Key | From the API member's API Keys tab |
ConnectWise clientId | Your own client ID from the ConnectWise Developer Network — generate it using the steps in the callout above. Sent as the clientId header on every API call. |
| Target status name | The ConnectWise ticket status that should trigger inbound sync |
The trigger URL is environment-specific — never assume the production URL. It differs by Field Nation environment in both host and path. Always copy the exact value from your environment's Settings → Trigger URL:
https://micro.fieldnation.com/v1/broker/inbound?client_token=<CLIENT_TOKEN>https://micro.fndev.net/v1/broker-sandbox/inbound?client_token=<CLIENT_TOKEN>The client_token is a secret (it encodes your company + integration).
ConnectWise REST uses HTTP Basic auth (Company+PublicKey:PrivateKey) plus a clientId header on every request.
Export these once so the examples below stay clean. Set HOST to your ConnectWise host, and replace <CLIENT_ID> (from Prerequisites), <COMPANY_NAME>, <PUBLIC_KEY>, and <PRIVATE_KEY> with your own values:
HOST='api-na.myconnectwise.net'
B="https://$HOST/v4_6_release/apis/3.0"
H_CLIENT='clientId: <CLIENT_ID>'
H_ACCEPT='Accept: application/vnd.connectwise.com+json; version=3.0.0'
AUTH='<COMPANY_NAME>+<PUBLIC_KEY>:<PRIVATE_KEY>'curl base64-encodes -u into the Authorization: Basic header automatically.
<COMPANY_NAME>+<PUBLIC_KEY> — concatenate with a literal +<PRIVATE_KEY>clientId → <CLIENT_ID> — your Developer Network client IDAccept → application/vnd.connectwise.com+json; version=3.0.0Content-Type → application/json (for the POST in Step 4)A header explicitly set in the Headers tab overrides the Authorization tab. If a request seems to use the wrong credentials, open the Postman Console (View → Show Postman Console) and decode the actual Authorization: Basic … header to confirm which key pair is really being sent.
The callback payload needs the numeric objectId of your target status — not the status name. Status IDs are unique per board: the same status name has a different ID on each board.
First, find the numeric board ID for the board your tickets live on. You need this to query statuses.
curl -s -G "$B/service/boards" \
--data-urlencode 'fields=id,name' \
-H "$H_CLIENT" -H "$H_ACCEPT" -u "$AUTH"GEThttps://<HOST>/v4_6_release/apis/3.0/service/boardsfields = id,nameFind your board name and copy its id (e.g. 7). Then list its statuses to get the numeric status ID.
ConnectWise returns 25 records per page by default, and custom statuses often sort beyond the first page. Always append pageSize=100 (or page through) or you may miss your target.
curl -s -G "$B/service/boards/<BOARD_ID>/statuses" \
--data-urlencode 'pageSize=100' \
--data-urlencode 'fields=id,name' \
-H "$H_CLIENT" -H "$H_ACCEPT" -u "$AUTH"GEThttps://<HOST>/v4_6_release/apis/3.0/service/boards/<BOARD_ID>/statusespageSize = 100, fields = id,nameFind your target status name and copy its top-level id:
{ "id": 142, "name": "Dispatch to FN", "board": { "id": 7, "name": "Field Services" } }Here 142 is the objectId for the next step. Repeat per board for multi-board setups.
Before registering, list current callbacks so you don't create a duplicate (ConnectWise rejects a second callback on the same status with ObjectExists). Use pageSize=200 — a recently added callback often sits on page 2 and won't appear in the default 25-record response, which makes it look like it doesn't exist.
curl -s -G "$B/system/callbacks" \
--data-urlencode 'pageSize=200' \
--data-urlencode 'fields=id,description,url,objectId,level,type' \
-H "$H_CLIENT" -H "$H_ACCEPT" -u "$AUTH"GEThttps://<HOST>/v4_6_release/apis/3.0/system/callbackspageSize = 200, fields = id,description,url,objectId,level,typeScan the url values to see which environment each callback points at (fieldnation.com = production, fndev.net = sandbox) and which objectId (status) each watches.
curl -i -X POST "$B/system/callbacks" \
-H "$H_CLIENT" -H "$H_ACCEPT" -H 'Content-Type: application/json' \
-u "$AUTH" \
-d '{
"description": "Field Nation Integration",
"url": "<FN_TRIGGER_URL>&external_id=",
"type": "ticket",
"level": "status",
"objectId": <TARGET_STATUS_ID>,
"inactiveFlag": false,
"isSoapCallbackFlag": false
}'POSThttps://<HOST>/v4_6_release/apis/3.0/system/callbacks{
"description": "Field Nation Integration",
"url": "<FN_TRIGGER_URL>&external_id=",
"type": "ticket",
"level": "status",
"objectId": <TARGET_STATUS_ID>,
"inactiveFlag": false,
"isSoapCallbackFlag": false
}Replace <FN_TRIGGER_URL> with your exact environment trigger URL (it already contains client_token; append &external_id= so ConnectWise appends the ticket ID when it fires) and <TARGET_STATUS_ID> with the integer from Step 2.
objectId must be a bare integer — "objectId": 142 is correct; "objectId": "142" returns 400 Bad Request. And level: status means the callback fires whenever any ticket on that board transitions into that status (not on tickets already sitting in it).
A successful registration returns HTTP 201 Created:
{
"id": 88,
"description": "Field Nation Integration",
"url": "https://micro.fieldnation.com/v1/broker/inbound?client_token=<CLIENT_TOKEN>&external_id=",
"objectId": 142,
"type": "ticket",
"level": "status",
"memberId": 15,
"inactiveFlag": false,
"isSoapCallbackFlag": false
}Note the returned id — the ConnectWise callback ID — in case you need to update or delete it later.
| HTTP code | Cause | Fix |
|---|---|---|
401 Unauthorized / Invalid Token | Auth invalid, or Company is the display name instead of the login identifier | Confirm <COMPANY>+<PUBLIC_KEY> format (no spaces), the Company is your login identifier, and the Private Key has no trailing whitespace |
403 Forbidden | API member lacks callback write permission | Use a member/role with callback management rights — many API roles can read (GET) callbacks but not add/delete them |
400 Bad Request (InvalidObject) | objectId quoted, or malformed JSON | objectId must be a bare integer; validate the JSON |
400 ObjectExists ("A matching callback entry already exists") | A callback for that objectId is already registered | It already exists — re-run Step 3 with pageSize=200 to find it (it may be on page 2). Update or reuse it instead of creating a new one |
404 Not Found | Path typo or wrong board/status ID | Check the endpoint path; re-run Step 2 to confirm the objectId |
A minority of ConnectWise instances expose System → Setup Tables → Callbacks. If yours does, you can register there instead of the API:
| Field | Value |
|---|---|
| Description | Field Nation Integration |
| URL | Your Field Nation trigger URL (with &external_id= appended) |
| Object Type | Service Ticket |
| Level | Status Level (target the trigger status) |
| Added / Changed | ✓ Checked |
| Deleted / Inactive Members | Leave unchecked |
If this table isn't present, or saving returns a permission error, use the API method above — that's the norm, not the exception.
| Item | Value / behavior |
|---|---|
| Primary method | REST API — POST https://<HOST>/v4_6_release/apis/3.0/system/callbacks |
| Auth | Basic Company+PublicKey:PrivateKey + clientId header (every request) |
type / level | ticket / status |
objectId | Numeric status ID — unique per board, bare integer (no quotes) |
url | Environment-specific Field Nation trigger URL (fndev.net sandbox / fieldnation.com prod) + &external_id= |
| Listing callbacks | Always pageSize=200 — the default 25 hides newer callbacks |
| Already exists | 400 ObjectExists means it's registered — find it (page 2), don't recreate |
| Fires when | A ticket transitions into the target status |
| Multi-board | One callback per board status |
| UI method | Only on instances with a Callbacks setup table — usually unavailable |
Last updated on