Skip to main content
Version: v12

Ticket Creation API

The Ticket Creation API lets you create a remediation ticket from a selection of findings from your own scripts or agents. It is the programmatic counterpart to creating ad hoc tickets from a findings page in the Brinqa UI: the ticket goes through the same path, so SLA timers, the application event log, and consolidation behave exactly as they do for tickets created through the UI.

You select the findings, name the ticket, and pick an SLA definition; the ticket type is derived from the finding model. A selection of Vulnerability findings produces a vulnerability ticket, a selection of Violation findings produces a violation ticket, and so on. You never send the ticket model. The examples below use Vulnerability findings to make the calls concrete, but the same call works on any concrete finding model.

Authentication​

The Ticket Creation API uses API tokens for authentication. See API Token Authentication for instructions on generating, using, and managing API tokens. Pass the token in the Authorization header using the ApiKey scheme:

Authorization: ApiKey <your-api-token>

Create a ticket​

Creates one ticket and attaches the selected findings to it.

POST /v1/api/tickets

Headers:

Content-Type: application/json
Authorization: ApiKey <your-api-token>

Request body:

{
"query": "FIND Vulnerability AS v WHERE v.severity = \"Critical\" AND v.status = \"Confirmed active\"",
"name": "Remediate active critical vulnerabilities",
"summary": "Active critical vulnerabilities across the environment",
"description": "Prioritized remediation of every active critical vulnerability.",
"slaPolicy": { "id": 2060003840241509001 }
}
FieldTypeRequiredDescription
querystringOne ofA BQL query selecting the findings to attach. The finding model is derived from the query's main entity. Mutually exclusive with dataModel + datasetIds.
dataModelstringOne ofThe finding data model of the datasetIds selection: a numeric data model id, a resource name, or a case-insensitive model name (for example Vulnerability). Mutually exclusive with query.
datasetIdsarray of numbersOne ofThe ids of the finding records to attach. Requires dataModel. At most 1,000 ids.
namestringYesName of the ticket. Maximum 500 characters.
summarystringYesShort, high-level statement of the ticket's purpose. Maximum 2,000 characters.
descriptionstringNoAdditional details about the ticket. Maximum 50,000 characters.
slaPolicyobjectYesThe SLA definition for the ticket, identified by exactly one of its numeric id (preferred) or its uid: {"id": 2060003840241509001} or {"uid": "3f9c2b7a1d4e8f60"}. Sending both or neither returns 400. Resolve the id with a BQL query over SLADefinition, the same way you resolve other record ids.
assignedobjectNoPrimary remediation owner, as {"id": <recordId>}. Defaults to unassigned.
delegatesarray of objectsNoAlternate remediation owners, as a list of {"id": <recordId>}.
remediationCampaignobjectNoRemediation campaign to link the ticket to, as {"id": <recordId>}.
sprintobjectNoSprint to link the ticket to, as {"id": <recordId>}.

The finding selection​

Every request selects findings in exactly one of two ways:

  • By query: a BQL query over one finding model, in the query field. The finding model is the query's main entity; you do not send it separately.
  • By ids: a finding model in dataModel plus a non-empty list of record ids in datasetIds.

Sending both or neither returns 400. The selection must match at least one finding, and at most the platform's configured findings limit (1,000 by default); an empty selection or one over the limit returns 400 and no ticket is created.

A minimal body selecting by query:

{
"query": "FIND Vulnerability AS v WHERE v.severity = \"Critical\" AND v.status = \"Confirmed active\"",
"name": "Remediate active critical vulnerabilities",
"summary": "Active critical vulnerabilities across the environment",
"slaPolicy": { "id": 2060003840241509001 }
}

The same ticket selecting by explicit ids. Resolve the ids with a BQL query first; the finding model moves into dataModel because there is no query to derive it from:

{
"dataModel": "Vulnerability",
"datasetIds": [2060003840241508371, 2060003840241508372],
"name": "Remediate active critical vulnerabilities",
"summary": "Active critical vulnerabilities across the environment",
"slaPolicy": { "id": 2060003840241509001 }
}

Select over a specific concrete finding model (for example Vulnerability or Violation), never the abstract Finding parent. Each finding type maps to its own ticket type, so no single ticket type can be derived from Finding; such a request is rejected. This mirrors the UI, where ad hoc ticketing is not available on the All findings page.

The selection only sees findings you can read. Findings outside your access control scope are silently excluded from the selection, exactly as they are hidden from your findings pages in the UI.

Reference fields​

The assigned, delegates, remediationCampaign, and sprint fields reference existing records by id, in the same {"id": <recordId>} shape the Dataset Write API uses for relationships. You never send the referenced data model: it is fixed by the corresponding attribute of the derived ticket type (for example, assigned on a vulnerability ticket always points at the model that ticket type's assigned attribute targets).

Resolve the record ids with a BQL query first, for example FIND User WHERE userName = "jdoe@example.com". A referenced record that does not exist, or that you cannot read, returns 404.

Response​

201 Created

{
"ticket": {
"id": 2073123085283299328,
"dataModel": "VulnerabilityTicket",
"displayValue": "Remediate active critical vulnerabilities"
},
"findingCount": 42,
"transactionId": "9f3a4c10-2c47-4e11-9d7a-7b1f5b3a82e8"
}
FieldTypeDescription
ticket.idnumberId of the new ticket record.
ticket.dataModelstringThe derived ticket data model.
ticket.displayValuestringDisplay value of the ticket (its name).
findingCountnumberHow many findings were selected and attached to the ticket.
transactionIdstringIdentifier of the run that created the ticket. Use it to correlate the run in the application event log.

The ticket's SLA due dates are computed asynchronously right after creation, so they can lag the response by a moment.

warning

Record ids exceed JavaScript's Number.MAX_SAFE_INTEGER. A naive JSON.parse silently rounds them to a nearby value, and the rounded id no longer resolves. In JavaScript, parse ids from the raw response text as strings, or use a big-integer-aware JSON parser. This applies to every id you send or receive: finding ids, referenced record ids, and the returned ticket id.

Examples​

Create a ticket from a BQL query selection:

curl -X POST 'https://<your-brinqa-instance>/v1/api/tickets' \
-H 'Content-Type: application/json' \
-H 'Authorization: ApiKey <your-api-token>' \
-d '{
"query": "FIND Vulnerability AS v WHERE v.severity = \"Critical\" AND v.status = \"Confirmed active\"",
"name": "Remediate active critical vulnerabilities",
"summary": "Active critical vulnerabilities across the environment",
"slaPolicy": { "id": 2060003840241509001 }
}'
note

Replace <your-brinqa-instance> with the URL of your Brinqa Platform and <your-api-token> with your API token.

Create a ticket from explicit finding ids, with the SLA definition given by its uid:

curl -X POST 'https://<your-brinqa-instance>/v1/api/tickets' \
-H 'Content-Type: application/json' \
-H 'Authorization: ApiKey <your-api-token>' \
-d '{
"dataModel": "Vulnerability",
"datasetIds": [2060003840241508371, 2060003840241508372],
"name": "Remediate CVE-2026-0001 on web servers",
"summary": "OpenSSL CVE-2026-0001 on the web tier",
"slaPolicy": { "uid": "3f9c2b7a1d4e8f60" }
}'

Create a fully specified ticket with an owner, delegates, a remediation campaign, and a sprint:

curl -X POST 'https://<your-brinqa-instance>/v1/api/tickets' \
-H 'Content-Type: application/json' \
-H 'Authorization: ApiKey <your-api-token>' \
-d '{
"query": "FIND Vulnerability AS v WHERE v.severity = \"Critical\" AND v.status = \"Confirmed active\"",
"name": "Remediate active critical vulnerabilities",
"summary": "Active critical vulnerabilities across the environment",
"description": "Prioritized remediation of every active critical vulnerability.",
"slaPolicy": { "id": 2060003840241509001 },
"assigned": { "id": 2060003840241510420 },
"delegates": [{ "id": 2060003840241510421 }, { "id": 2060003840241510422 }],
"remediationCampaign": { "id": 2060003840241511307 },
"sprint": { "id": 2060003840241512118 }
}'

Permissions and access control​

Ticket creation enforces the same permissions as the ticket-creation action in the UI:

  • The finding selection is scoped to your read access: you can only attach findings you can read.
  • Creating the ticket requires permission to execute your tenant's ticket-creation button flow for the finding's model, the same permission that makes the Create ticket action appear on that findings page in the UI. A caller without it, or a finding model with no ticket-creation button flow installed, receives 403.
  • Referenced records (assigned, delegates, remediationCampaign, sprint) must be readable by you. A record you cannot read returns the same 404 as a record that does not exist.

Rate limits​

The endpoint is rate limited at 60 requests per minute. 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​

HTTP StatusMeaningCommon cause
201 CreatedTicket created.Normal response. The body holds the ticket reference, the finding count, and the transaction id.
400 Bad RequestThe request was rejected and no ticket was created.A missing or over-length name, summary, or description (the message lists every violation); a selection that is both or neither of query and dataModel + datasetIds; invalid BQL; a slaPolicy with both or neither of id and uid; a selection matching no findings; a selection over the configured findings limit (1,000 by default); or a finding model no ticket type can be derived from (for example the abstract Finding model).
401 UnauthorizedAuthentication failed.Missing, invalid, expired, or revoked API token.
403 ForbiddenNot permitted.The caller lacks permission to execute the tenant's ticket-creation button flow on the finding's model, or no such flow exists for that model.
404 Not FoundTarget not found.Unknown data model identifier, unknown SLA definition, or a referenced record (assigned, delegates, remediationCampaign, sprint) that does not exist or that the caller cannot read.
409 ConflictSome selected findings already belong to another remediation.The body carries a findingIds list with up to 50 of the conflicting finding ids. Exclude them from the selection and retry.
429 Too Many RequestsRate limit exceeded.Too many requests in a short period. Wait for the Retry-After interval and retry.

409 Conflict body:

{
"status": 409,
"error": "Conflict",
"message": "There are findings that are already included in external remediations; findingIds=[2060003840241508371]",
"findingIds": [2060003840241508371]
}