PUT /v2/transaction-labels tells Tracio how a transaction actually turned
out: "this was bonus abuse", "a false alert", "a chargeback". The request body
and the vocabulary are the ones of SEON's Label API v2, so an existing SEON
labeling integration moves over by changing the URL and the key header (see
Migrating from SEON).
Base URL: https://api.tracio.ai. The routes live under /v2, next to
POST /v2/transactions: every key in the request, the
response and the error body is snake_case.
| Method | Path | What it does |
|---|---|---|
| PUT | /v2/transaction-labels | set a label on up to 50 transactions |
| DELETE | /v2/transaction-labels | remove the label from up to 50 transactions |
| GET | /v2/transaction-labels/value-set | the 26 accepted label values with their polarity |
A label is the final outcome of a transaction, as in SEON:
DECLINE;APPROVE;state that POST /v2/transactions returned.A transaction has at most one label. Setting a label on a transaction that already has one replaces it; setting the same label again changes nothing.
Setting, replacing or removing a label changes the transaction's effective
state, and a webhook subscribed to
transaction_state_changed receives an event —
also when a label is replaced with another one of the same polarity. Setting
the same label again sends nothing. The current label and effective state are
also returned by
GET /v2/transactions/{transaction_id}.
You can label only transactions you have already sent to
POST /v2/transactions: transaction_id is the same id,
looked up within the workspace of your key. A repeated POST /v2/transactions
with that transaction_id still returns the original stored decision, not the
labeled state (see transactions.md, section
"Idempotency").
What labels feed:
user_id; it feeds the reputation of
the person behind that account. Labels where the account is a victim or the
case is not fraud (account takeover, phishing, a chargeback dispute, ...) file
no report. When a transaction's label changes so that its report type is no
longer needed — a positive label, a negative label that files no report or a
report of another type, or removing the label — the report that labels filed
is revoked, unless another transaction of the same account still carries a
label of that report type. A report an analyst filed in the dashboard is never
revoked by labels. The fraud report and the reputation are updated in the background,
normally within a minute after the label is set.The same secret key (tracio_sk_…) and the same header as the rest of the Data
API — see data-api.md, section "Keys":
Authorization: Bearer tracio_sk_…The endpoints require the Business plan or higher. A key on a lower plan
gets HTTP 402:
{ "error": { "code": "upgrade_required", "message": "Transaction labels require the Business plan or higher", "request_id": "01J8F3..." } }Calls count against the usual Data API per-second limit and daily quota of your plan; there is no separate meter.
PUT /v2/transaction-labelscurl -X PUT https://api.tracio.ai/v2/transaction-labels \ -H "Authorization: Bearer $TRACIO_SECRET_KEY" \ -H "Content-Type: application/json" \ -d '{ "transactions": [ { "transaction_id": "txn_12345", "label": "fraud_detection_bonus_abuse" }, { "transaction_id": "txn_67890", "label": "fraud_detection_false_alert" } ] }'Validation runs on the whole body before anything is written — all or
nothing. If any item is invalid, the response is 400 invalid_request with
every invalid field listed in errors, and no transaction is changed:
| Field | Rule |
|---|---|
transactions | an array of 1 to 50 items |
transactions[i].transaction_id | a non-empty string of at most 255 bytes; the same id twice in one request is an error (duplicate in request) |
transactions[i].label | one of the 26 values of the value set; case-sensitive, as in SEON |
The body is at most 64 KiB. Unknown keys are rejected with 400 invalid_request. A request with more than 50 items gets a single error on
transactions; the labels in it are not checked.
A transaction_id that does not exist in your workspace does not fail the
request: it gets not_found in the response, and the other items are written.
200 OK:
{ "transactions": [ { "transaction_id": "txn_12345", "status": "labeled", "label": "fraud_detection_bonus_abuse", "state": "DECLINE" }, { "transaction_id": "txn_67890", "status": "not_found" } ] }Items come back in the order of the request.
status | Meaning |
|---|---|
labeled | the label is set — including the case where the same label was already there (a repeat changes nothing) |
not_found | no transaction with this transaction_id in your workspace; nothing was written for it |
label and state are present only with labeled. state is the effective
state of the transaction after the write: DECLINE for a negative label,
APPROVE for a positive one.
DELETE /v2/transaction-labelscurl -X DELETE https://api.tracio.ai/v2/transaction-labels \ -H "Authorization: Bearer $TRACIO_SECRET_KEY" \ -H "Content-Type: application/json" \ -d '{ "transactions": [ { "transaction_id": "txn_12345" } ] }'The same checks as for PUT, without label: 1 to 50 items, a non-empty
transaction_id of at most 255 bytes, no duplicates. A label key in the body
is an unknown key and gets 400 invalid_request.
200 OK:
{ "transactions": [ { "transaction_id": "txn_12345", "status": "removed", "state": "REVIEW" } ] }status | Meaning |
|---|---|
removed | the label is removed; state is again the decision of the rules |
not_labeled | the transaction had no label; nothing was changed, state is its current state |
not_found | no transaction with this transaction_id in your workspace |
state is present with removed and not_labeled.
GET /v2/transaction-labels/value-setcurl -H "Authorization: Bearer $TRACIO_SECRET_KEY" \ https://api.tracio.ai/v2/transaction-labels/value-set200 OK:
{ "labels": [ { "value": "fraud_detection_fraud", "polarity": "negative" }, { "value": "fraud_detection_bonus_abuse", "polarity": "negative" } ] }The response has 26 elements, in the order of the table below: 23 negative, then 3 positive. These are the values of SEON's "Fraud detection" label set.
value | polarity | Resulting state | Creates fraud report |
|---|---|---|---|
fraud_detection_fraud | negative | DECLINE | manual_ban |
fraud_detection_bonus_abuse | negative | DECLINE | multiaccount |
fraud_detection_multi_accounting | negative | DECLINE | multiaccount |
fraud_detection_ato | negative | DECLINE | — |
fraud_detection_underage | negative | DECLINE | manual_ban |
fraud_detection_false_identity | negative | DECLINE | manual_ban |
fraud_detection_phishing | negative | DECLINE | — |
fraud_detection_remote_access_fraud | negative | DECLINE | — |
fraud_detection_chargeback_fraud | negative | DECLINE | chargeback |
fraud_detection_chargeback_dispute | negative | DECLINE | — |
fraud_detection_chargeback_processing_error | negative | DECLINE | — |
fraud_detection_chargeback_authorization_issue | negative | DECLINE | — |
fraud_detection_suspicious_login | negative | DECLINE | — |
fraud_detection_vishing | negative | DECLINE | — |
fraud_detection_front_man | negative | DECLINE | manual_ban |
fraud_detection_arbitrage | negative | DECLINE | manual_ban |
fraud_detection_vishing_rat | negative | DECLINE | — |
fraud_detection_bot | negative | DECLINE | manual_ban |
fraud_detection_campaign_abuse | negative | DECLINE | multiaccount |
fraud_detection_missed_fraud | negative | DECLINE | manual_ban |
fraud_detection_stolen_card | negative | DECLINE | stolen_card |
fraud_detection_scam | negative | DECLINE | — |
fraud_detection_affiliate_fraud | negative | DECLINE | — |
fraud_detection_marked_as_approved | positive | APPROVE | — |
fraud_detection_verified_payment | positive | APPROVE | — |
fraud_detection_false_alert | positive | APPROVE | — |
"Creates fraud report" is the type of the fraud report the label files on the
transaction's user_id (see Overview); "—" means no report: the
account is a victim, the case is unclear, it is not fraud, or the label is
positive. fraud_detection_affiliate_fraud marks a conversion as affiliate fraud
and sets its state to DECLINE, but it does not file a fraud report: the
affiliate, not the account, is the offender. The value set response itself
carries only value and polarity.
Errors of these endpoints use the v2 envelope:
{ "error": { "code": "invalid_request", "message": "request validation failed", "request_id": "01J8F3...", "errors": [ { "field": "transactions[0].label", "message": "must be one of: fraud_detection_fraud, fraud_detection_bonus_abuse, ..." }, { "field": "transactions[1].transaction_id", "message": "duplicate in request" } ] } }errors is present only on validation failures and lists every invalid field
at once. request_id is the id of this API call (also sent as the
X-Request-Id header) — quote it to support.
| HTTP | code | Reason |
|---|---|---|
| 400 | invalid_request | the body is not valid JSON, has an unknown key, is over 64 KiB, or fails validation (see errors); nothing was written |
| 402 | upgrade_required | plan below Business |
| 503 | unavailable | storage is temporarily unavailable; nothing was written — retry the same request |
Responses of the shared authorization layer are still in the v1 envelope
until the whole API moves to v2: {"error":{"code","message","requestId"}},
with camelCase requestId and without errors. These are 401 unauthorized
(missing, revoked or expired key), 402 upgrade_required for a key without
Data API access (below Pro), 429 rate_limited with Retry-After, and 503 unavailable when the key store is unreachable. Their meaning is the one in
data-api.md, section "Errors". Read the code from
error.code: it has the same name in both envelopes.
Retry 429 and 503 with a growing pause. PUT and DELETE are safe to
repeat: a repeated label or a repeated removal changes nothing.
| SEON Label API v2 | Tracio | Difference |
|---|---|---|
PUT https://api.seon.io/SeonRestService/fraud-api/transaction-label/v2 | PUT https://api.tracio.ai/v2/transaction-labels | path |
DELETE …/transaction-label/v2 | DELETE https://api.tracio.ai/v2/transaction-labels | path |
GET …/transaction-label/v2/label-value-set | GET https://api.tracio.ai/v2/transaction-labels/value-set | path; SEON's documentation does not show its response shape — ours is described above |
header X-API-KEY: <license_key> | Authorization: Bearer tracio_sk_… | key header (as for the whole Data API) |
body {"transactions":[{"transaction_id","label"}]} | the same | none |
DELETE body {"transactions":[{"transaction_id"}]} | the same | none |
| ≤ 50 transactions per request | ≤ 50 | none |
| one label per transaction, overwrite, removal | the same | none |
| removal returns the state of the rules evaluation | the same | none |
| only existing transactions can be labeled | the same; an unknown one gets not_found in its result item | SEON's documentation does not describe its answer to an unknown transaction |
errors {"success":false,"error":{"code":"1000",…},"data":{}} | v2 envelope {"error":{"code","message","request_id","errors"}} | error format (as for POST /v2/transactions) |
| successful response — not shown | 200 with a result per item | ours, see PUT and DELETE |
https://api.tracio.ai/v2/transaction-labels (both PUT and DELETE) and
read the vocabulary from
https://api.tracio.ai/v2/transaction-labels/value-set.X-API-KEY: <license_key> with
Authorization: Bearer tracio_sk_… — a secret key of your workspace (see
Authentication and plan).PUT and DELETE bodies are the same as in SEON;
the fraud_detection_* values are the same.200 body has no success / data
wrapper: read transactions[].status (labeled, removed, not_labeled,
not_found) for every item.error.code. An error is a non-2xx status with
{"error":{…}}; branch on the string error.code (invalid_request,
upgrade_required, ...), not on SEON's numeric code.transaction_id. It is the id you send to
POST /v2/transactions; a transaction not sent there is
not_found.Not supported:
fraud_detection_* set gets 400 invalid_request, and the error message
lists the accepted values;X-API-KEY header — a request without Authorization: Bearer gets 401 unauthorized.