Button Flow API
The Button Flow API lets your scripts or agents find which button flows apply to a data model or a specific record, inspect the input fields a flow expects, and launch a flow against the records you choose.
A button flow is a flow categorized as BUTTON_FLOW that always acts on a selection of records of a data model. It is the kind of on-demand action Brinqa surfaces as a button on a data model or a record in the UI. Each button flow declares a scope that fixes the record selection it launches against:
DATA_MODEL: the flow runs against a set of records of the data model, chosen at launch with a BQL query. Use the model-level list endpoint to discover these.DATA_SET: the flow runs against one specific record of the data model. Use the record-level list endpoint to discover these.
The discovery endpoints are read-only: they tell you what button flows exist and what each one needs as input. The launch endpoints start a flow against the records you select. A typical integration discovers a flow, reads its input fields, then launches it.
The examples below use Vulnerability records to make the calls concrete, but the same calls work on any data model that has button flows.
Authentication
The Button Flow API uses API tokens for authentication. Pass the token in the Authorization header using the ApiKey scheme:
Authorization: ApiKey brq_<prefix>.<secret>
See API Token Authentication for instructions on generating, using, and managing API tokens.
Results are always filtered by the caller's permissions. A token only sees button flows on models and records its user account can access, and only flows that are enabled and in scope. The returned active field is a separate property: it reports whether a flow can be launched right now, not whether it is enabled. See the response shapes below.
The data model identifier
Every endpoint takes a {dataModelIdentifier} path parameter that names the data model. It is resolved flexibly: the API accepts the internal data model id, the resource name, or the data model name (for example Vulnerability). An identifier that matches nothing returns 404.
Endpoints
| Operation | Method and path |
|---|---|
| List button flows for a data model | GET /v1/api/button-flows/{dataModelIdentifier} |
| List button flows for a record | GET /v1/api/button-flows/{dataModelIdentifier}/datasets/{dataSetId} |
| Get a button flow's input fields | GET /v1/api/button-flows/{dataModelIdentifier}/flows/{flowName}/fields |
| Launch a model-wide button flow | POST /v1/api/button-flows/{dataModelIdentifier}/flows/{flowName}/launch |
| Launch a record button flow | POST /v1/api/button-flows/{dataModelIdentifier}/datasets/{dataSetId}/flows/{flowName}/launch |
The {dataSetId} path parameter is a 17 to 19 digit numeric record id. The {flowName} path parameter is the flow name returned by the list endpoints.
List button flows for a data model
Returns the DATA_MODEL-scoped button flows that apply to the given model: flows that can be launched against any record of that model. The result is filtered by the caller's permissions and excludes disabled flows. Each returned flow carries an active field reporting whether it can be launched right now.
GET /v1/api/button-flows/{dataModelIdentifier}
Headers:
Authorization: ApiKey brq_<prefix>.<secret>
Response: 200 OK
A JSON array of button flow summaries. See Response shapes for the fields.
[
{
"name": "escalate-vulnerability",
"title": "Escalate Vulnerability",
"scope": "DATA_MODEL",
"active": true
},
{
"name": "bulk-assign-owner",
"title": "Bulk Assign Owner",
"scope": "DATA_MODEL",
"active": true
}
]
Example:
curl 'https://<your-brinqa-instance>/v1/api/button-flows/Vulnerability' \
-H 'Authorization: ApiKey brq_<prefix>.<secret>'
Replace <your-brinqa-instance> with the URL of your Brinqa Platform and brq_<prefix>.<secret> with your API token.
List button flows for a record
Returns the DATA_SET-scoped button flows that apply to one specific record: flows that can be launched against that record. The result is filtered by the caller's permissions and excludes disabled flows. Each returned flow carries an active field reporting whether it can be launched right now.
GET /v1/api/button-flows/{dataModelIdentifier}/datasets/{dataSetId}
Headers:
Authorization: ApiKey brq_<prefix>.<secret>
Response: 200 OK
A JSON array of button flow summaries, each with scope set to DATA_SET.
[
{
"name": "create-remediation-ticket",
"title": "Create Remediation Ticket",
"scope": "DATA_SET",
"active": true
}
]
Example:
curl 'https://<your-brinqa-instance>/v1/api/button-flows/Vulnerability/datasets/184726195308400123' \
-H 'Authorization: ApiKey brq_<prefix>.<secret>'
Get a button flow's input fields
Returns the input fields a button flow expects when it is launched, so a client can build a form or assemble the launch arguments. For a DATA_MODEL-scoped flow the fields include a required query field: a BQL query that selects the records the flow runs against. A DATA_SET-scoped flow instead acts on the single record named by {dataSetId} when launched, so it has no query field.
This endpoint requires permission to execute the button flow. If the caller lacks that permission, or the flow does not exist on the model, the endpoint returns 403.
GET /v1/api/button-flows/{dataModelIdentifier}/flows/{flowName}/fields
Pass the flow name from the list endpoints as {flowName}.
Headers:
Authorization: ApiKey brq_<prefix>.<secret>
Response: 200 OK
An object with the flow name and its input fields. See Response shapes for the field object.
{
"flowName": "escalate-vulnerability",
"fields": [
{
"name": "query",
"title": "Records to act on (BQL query)",
"type": "TextAttributeType",
"required": true,
"options": [],
"defaultValue": null
},
{
"name": "priority",
"title": "Priority",
"type": "SingleChoiceAttributeType",
"required": true,
"options": ["Low", "Medium", "High", "Critical"],
"defaultValue": "High"
},
{
"name": "justification",
"title": "Justification",
"type": "TextAttributeType",
"required": false,
"options": [],
"defaultValue": null
}
]
}
Not every button flow has form fields. A DATA_SET-scoped flow with an empty launch form returns an empty fields array. A DATA_MODEL-scoped flow always returns at least the query selection field.
Example:
curl 'https://<your-brinqa-instance>/v1/api/button-flows/Vulnerability/flows/escalate-vulnerability/fields' \
-H 'Authorization: ApiKey brq_<prefix>.<secret>'
Launch a button flow
Launching a button flow starts the flow against the records you choose and returns a transactionId you use to track it. There are two launch endpoints, one per scope:
- A
DATA_MODEL-scoped flow launches against a set of records you select with a BQLquery. - A
DATA_SET-scoped flow launches against the single record named in the path.
Both endpoints validate the request before they start the flow. Required input fields are enforced, the flow's pre-launch conditions are checked, and any pre-launch form validation script runs. A request that is missing inputs or fails validation is rejected synchronously with an error, so the flow never starts in a bad state.
Before you launch, call Get a button flow's input fields to learn which arguments the flow requires. The name of each field marked required must appear as a key in arguments.
Field value formats
Most fields take a plain value: a string for text, a number, a boolean, or one of the listed options for a choice field. Two cases need more care:
-
Relationship (reference) fields. A field whose
typeisReferenceAttributeTypepoints at a record of another data model, named by the field'srelatedDataModel(see Input field). Supply the id of that related record as the value. You do not build the internal reference object: pass the id and the server resolves the rest. If the field'smultipleflag istrue, pass an array of ids. For example, anslaPolicyfield withrelatedDataModelSLADefinitiontakes the id of an SLADefinition record:{"arguments": {"query": "severity = 'Critical'","name": "Escalation ticket","summary": "Escalating unresolved critical findings","slaPolicy": "2059997699363495936"}}To find a valid id, query the related model (here
SLADefinition) through the platform's normal data APIs. The id must resolve to a record of the related model that the caller can read; an id that does not, including one the caller has no read access to, is rejected with406(a record you cannot read is indistinguishable from one that does not exist). -
Record selection (
query). For a model-wide launch, thequeryargument is BQL selecting the records to act on, not a declared form field. See the model-wide launch below. -
Parent record (
__MAIN_ID__). Some button flows act on the records shown within a specific parent record (for example, removing vulnerabilities from one ticket). Their input fields include a required__MAIN_ID__whoserelatedDataModelis the parent model: supply the id of that parent record. It rides alongsidequery, which selects the related records to act on, so the parent and the target selection are two different records.
Launching a button flow is a write operation. The flow runs and changes data as soon as the launch is accepted. There is no server-side confirmation step for API callers. See Approval model before you automate a launch.
Launch a model-wide button flow
Launches a DATA_MODEL-scoped button flow against the records selected by a BQL query. This is the same selection the platform UI sends when an operator runs the flow.
POST /v1/api/button-flows/{dataModelIdentifier}/flows/{flowName}/launch
Headers:
Authorization: ApiKey brq_<prefix>.<secret>
Content-Type: application/json
Request body:
The arguments object holds the flow's input values. For a DATA_MODEL-scoped flow it must include a query argument: the BQL that selects which records the flow runs against. The query is not one of the flow's declared form fields, it is the record selection. Add any other required form fields alongside it.
{
"arguments": {
"query": "status = 'Open' and severity = 'Critical'",
"priority": "High",
"justification": "Quarterly escalation of unresolved critical findings"
}
}
Response: 201 Created
The Location header holds the URL of the new instance on the flow status endpoint. The body returns the same transactionId. Poll the status endpoint with that transactionId to observe progress and the result.
HTTP/2 201
Location: /v1/api/automation/management/9f3a4c10-2c47-4e11-9d7a-7b1f5b3a82e8
{
"transactionId": "9f3a4c10-2c47-4e11-9d7a-7b1f5b3a82e8"
}
Example:
curl -i -X POST 'https://<your-brinqa-instance>/v1/api/button-flows/Vulnerability/flows/escalate-vulnerability/launch' \
-H 'Authorization: ApiKey brq_<prefix>.<secret>' \
-H 'Content-Type: application/json' \
-d '{
"arguments": {
"query": "status = '"'"'Open'"'"' and severity = '"'"'Critical'"'"'",
"priority": "High",
"justification": "Quarterly escalation of unresolved critical findings"
}
}'
Launch a record button flow
Launches a DATA_SET-scoped button flow against the single record named by {dataSetId}. The record is identified in the path, so the request needs no query.
POST /v1/api/button-flows/{dataModelIdentifier}/datasets/{dataSetId}/flows/{flowName}/launch
Headers:
Authorization: ApiKey brq_<prefix>.<secret>
Content-Type: application/json
Request body:
The arguments object holds the flow's required form field values. A flow with an empty launch form takes an empty arguments object.
{
"arguments": {
"assignee": "security-team",
"due_date": "2026-07-15"
}
}
Response: 201 Created
Same shape as the model-wide launch: a Location header pointing at the flow status endpoint and a body with the transactionId.
HTTP/2 201
Location: /v1/api/automation/management/1b2c3d4e-5f60-7182-93a4-b5c6d7e8f901
{
"transactionId": "1b2c3d4e-5f60-7182-93a4-b5c6d7e8f901"
}
Example:
curl -i -X POST 'https://<your-brinqa-instance>/v1/api/button-flows/Vulnerability/datasets/184726195308400123/flows/create-remediation-ticket/launch' \
-H 'Authorization: ApiKey brq_<prefix>.<secret>' \
-H 'Content-Type: application/json' \
-d '{
"arguments": {
"assignee": "security-team",
"due_date": "2026-07-15"
}
}'
Launch errors
| HTTP Status | Meaning | Common cause |
|---|---|---|
400 Bad Request | Launch refused. | The flow already has an instance running for this target. A button flow cannot run concurrently against the same model or record. Under a rare concurrent-launch race, an already-running flow may instead surface as 406. |
401 Unauthorized | Authentication failed. | Missing, invalid, expired, or revoked API token. |
403 Forbidden | Not permitted. | The caller lacks permission to execute this flow on this model or record. An unknown flow name also returns 403, so the endpoint never confirms whether a flow exists. |
404 Not Found | Target not found. | The data model identifier resolves to nothing. |
406 Not Acceptable | Invalid arguments. | A required field is missing, the required query selection is missing (model-wide launch), or an argument is otherwise invalid. The response lists the missing field names. |
429 Too Many Requests | Rate limit exceeded. | Too many requests in a short period. Wait for the Retry-After interval and retry. |
Approval model
Brinqa does not apply a server-side confirmation gate to launches made through this API. Launching a button flow is a write operation that changes data as soon as the request is accepted, and the flow runs immediately against the selected records. A client that automates a launch is responsible for its own confirmation step before it calls a launch endpoint.
Response shapes
Button flow summary
Returned by both list endpoints.
| Field | Type | Description |
|---|---|---|
name | string | The flow's internal name. Pass this as {flowName} to the input fields endpoint. |
title | string | The flow's display title. |
scope | string | The launch scope: DATA_MODEL (applies to any record of the model) or DATA_SET (applies to one record). |
active | boolean | Whether the flow can be launched right now. false when an instance is already running for the model or record context. Only button flows the caller may launch are returned, so active is never about permission. |
Input field
Returned in the fields array of the input fields endpoint.
| Field | Type | Description |
|---|---|---|
name | string | The field's internal name. Use this as the key when assembling launch arguments. |
title | string | The field's display label. |
type | string | The attribute type discriminator, for example TextAttributeType, NumberAttributeType, SingleChoiceAttributeType, MultipleChoiceAttributeType, TrueFalseAttributeType, DateTimeAttributeType, or ReferenceAttributeType. |
required | boolean | Whether the field must be supplied to launch the flow. |
options | array | The allowed values for a choice field (SingleChoiceAttributeType, MultipleChoiceAttributeType). Empty for non-choice types. |
defaultValue | any | The field's default value if one is defined, otherwise null. |
relatedDataModel | string | For a reference field (ReferenceAttributeType), the data model the field points to (for example SLADefinition). The value you supply for the field is the id of a record of this model. null for non-reference fields. |
multiple | boolean | true when the field accepts more than one value, so its launch value is an array. A multi-valued reference field takes an array of record ids. |
Permissions and access control
These endpoints enforce the same access control as the rest of the platform. The listings include only button flows on models and records the caller can access, and only flows that are enabled and in the requested scope. A caller without read access to a model or record receives 403. The input fields and launch endpoints additionally require execute permission on the button flow; if the caller lacks it, or the flow does not exist on the model, they return 403. An unknown data model identifier returns 404.
Rate limits
The Button Flow API endpoints share a rate limit of 300 requests per minute, the platform default. If you exceed the limit, the API returns 429 Too Many Requests; wait for the interval given in the Retry-After response header before retrying.
Error handling
These statuses apply to the discovery endpoints. The launch endpoints return additional statuses, listed under Launch errors.
| HTTP Status | Meaning | Common cause |
|---|---|---|
401 Unauthorized | Authentication failed. | Missing, invalid, expired, or revoked API token. |
403 Forbidden | Not permitted. | The caller lacks read access to the data model or record (list endpoints), or lacks execute permission on the button flow (input fields endpoint). The input fields endpoint also returns 403 when the flow does not exist on the model. |
404 Not Found | Target not found. | Unknown data model identifier. |
429 Too Many Requests | Rate limit exceeded. | Too many requests in a short period. Wait for the Retry-After interval and retry. |