Creating trails in bulk with the API
The batch endpoint creates many trails in one request: the same thing the Workload Generator does with a spreadsheet, for an integration that feeds work into Floxar on its own, such as a ticketing tool, a scheduler or an HR platform. Each row becomes a trail on the flow it names, already on that flow's first step, assigned to someone or waiting in the queue. The rows, their checks and the result are the same as an uploaded file's, so Creating trails in bulk with the Workload Generator is the reference for what each column means.
What you need
- A registered agent for the integration, with Edit at the level where the trails are created: the account, or one organization or group. An account admin registers it and gives it its role; see Registering an agent. Keep its client secret in the integration's own secret store.
- Assignees who can run the trails. Everyone a row assigns must hold at least Engage at that same level. For a request at the account level, that permission has to be on the account itself.
- Active, approved flows at that level, each with a published start bit.
A person's own AI client cannot call this endpoint: the token its connection holds is refused by the REST API. A person imports a file on the Workload Generator page instead, and can ask their AI client to prepare that file, or to write the integration this article describes.
Get a token
The integration authenticates with the OAuth 2 client credentials grant at tokens.floxar.com, without a resource parameter, which gives a token for Floxar's REST API. Registering an agent shows the request. Cache the token for its expires_in and send it as Authorization: Bearer <token>.
Find your API address
The REST API's address is specific to your account, and it can change if your account is moved, so read it at the start of every run instead of writing it into your configuration. The account URL, https://mcp.floxar.com/a/<account_id>, never changes, and the get_identity tool there answers with your API's address:
- Request a second token from the same credentials, with
resourceset to your account URL. - Call
get_identityat the account URL with that token. - Its
integration.openapi_spec_urlis an address on your API; its origin (https://and the host) is the address to use for the requests below, and the document it names is the full API specification, which needs your REST token to read.
The Workload Generator page also shows the address for your account, to copy while you build.
Check the row limit
GET /api/v1/agent/capabilities answers data.limits.workload_batch_max_rows: the most rows one request accepts. Read it rather than assuming a number, and split larger sets into several requests.
Send the rows
curl --request POST "$FLOXAR_API/api/v1/trails/batch" \
--header "Authorization: Bearer $FLOXAR_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"accountId": "<account_id>",
"scopeId": "<scope_id>",
"rows": [
{
"flowId": "<flow_id>",
"trailName": "Refund - ACME Corp - TK-4501",
"status": "transferred",
"assigneeEmail": "sue.johnson@example.com",
"priority": "high",
"trailCategories": ["refunds"],
"trailContext": { "customer_id": "ACME-001" },
"customFields": { "ticket": "TK-4501" }
},
{
"flowId": "<flow_id>",
"trailName": "Refund - Globex - TK-4502",
"status": "queued",
"trailContext": { "customer_id": "GLBX-044" }
}
]
}'
accountId is your account, the account_id claim of your token. Leave out scopeId to create the trails at the account level. Each row takes:
| Field | Required | Notes |
|---|---|---|
flowId | Yes | The flow the trail runs. One request may name several flows. |
trailName | Yes | Up to 256 characters. |
status | Yes | transferred (assigned) or queued (in the queue). |
assigneeEmail or assigneeUserId | On transferred rows | People by email or user id, agents by user id only. When both are sent, the user id is used. On a queued row they are dropped. |
priority | No | low, medium, high or critical; the flow's priority when left out. |
trailCategories | No | An array of strings; the flow's categories when left out. |
trailContext | As the flow requires | The flow's context fields, by the names its trail_context_schema gives them; required fields must be present, and a date field holds a calendar date YYYY-MM-DD with no time. |
customFields | No | Your own key and value fields, such as the source system's ticket number, returned when the trail is read. An object, never an array. |
The trail_context_schema of each flow, and its id, can be read with the MCP tools list_flows and get_flow, or through the REST API.
Read the answer
A successful request answers 201 with data.count and data.trails: one entry per row, in the order you sent them, each with trail_id, trail_name, status, assigned_user_id (null for a queued trail) and first_sequence_id. When the server adjusted a row, meta.warnings lists it by its zero-based row_index:
QUEUED_ASSIGNEE_DROPPED: a queued row carried an assignee, which was ignored.ASSIGNEE_EMAIL_OVERRIDDEN: a row carried both assignee fields, and the user id was used.
Errors
A request is all or nothing: if any row fails, nothing is created, and the error names the first failing row by its zero-based details.row_index.
| Code | Status | Meaning |
|---|---|---|
BATCH_EMPTY | 400 | rows is empty or not an array. |
BATCH_TOO_LARGE | 400 | More rows than the limit; details gives max and received. |
INVALID_ROW | 400 | A row's flowId, trailName, trailCategories or customFields is missing or malformed; details.field names it. |
MISSING_STATUS | 400 | A row has no status. |
INVALID_STATUS | 422 | status is neither queued nor transferred. |
STATUS_REQUIRES_ASSIGNEE | 400 | A transferred row names no assignee. |
ASSIGNEE_NOT_FOUND | 400 | An assignee is not a member of the account. |
ASSIGNEE_INSUFFICIENT_PERMISSION | 403 | An assignee holds less than Engage at the level; details names them and their rows. |
INVALID_PRIORITY | 422 | priority is not one of the four values. |
TRAIL_CONTEXT_SCHEMA_VIOLATION | 422 | A row's trailContext lacks a required field or holds a date in another form. |
FLOW_NOT_FOUND | 404 | A flow is unknown, inactive, or not at the request's level. |
FLOW_NOT_APPROVED | 403 | A flow has not been approved. |
FLOW_START_BIT_ARCHIVED | 422 | A flow's start bit is archived. |
Fix the rows the error names and send the request again: a refused request created nothing, so resending it is safe.
Never resend a request that succeeded
The endpoint does not recognise rows it has already created: sending the same rows twice creates every trail twice. Keep a record of what each request sent and whether it succeeded, and when a set takes several requests, resend only the ones that failed. If a request's outcome is unknown, for example because the connection dropped before the answer arrived, check whether its trails exist, for example by listing the flow's trails created since you sent it, before sending it again.
What happens next
Every trail starts on its flow's first step. Each person who received trails is told once per request that new work is waiting for them; agents are not notified. Queued trails wait in the queue of their level for someone to claim them, and every trail is worked like one created any other way.
Last reviewed: 2026-10-25