Transaction
O recurso Transaction é o coração da API de antifraude transacional de cartão. Você envia os dados da transação antes de autorizá-la e recebe de volta uma recomendação (fraud_status) para decidir se gera ou não o código de autorização.
O fluxo completo de integração tem três passos:
POST /card_issuance/transaction— envia a transação para análise e recebe a recomendação.PUT /card_issuance/transaction/{id}— informa o desfecho real (capturada, cancelada, chargeback). Esse retorno alimenta o modelo e é o que mantém a qualidade das decisões ao longo do tempo.GET /card_issuance/transaction/{id}— consulta o estado atual e o histórico de eventos de uma transação.
Se você quer subir uma integração rápida, vá direto para Payload mínimo. São 13 campos obrigatórios. Todo o resto é opcional e serve para aumentar a acurácia do modelo.
Payload mínimo
Este é o menor corpo aceito pelo POST /card_issuance/transaction. Ele contém apenas os campos obrigatórios e é suficiente para receber uma decisão.
{
"id": "678",
"cardholder_id": "b812da2e-e6be-4712-8e57-6f3f2791625b",
"amount": 13725,
"currency": "BRL",
"installments": 1,
"authorization_date": "2026-08-07T13:25:42-03:00",
"authorization_type": "authorization",
"transaction_type": "credit",
"pan_entry_mode": "chip",
"pin_sent": true,
"terminal": {
"country_code": "BRA"
},
"merchant": {
"acquirer_id": "250",
"merchant_id": "123456",
"mcc": "5411"
},
"card": {
"brand": "visa",
"category": "black",
"bin": "498406",
"last4": "1234",
"issuer_country_code": "BRA"
}
}
Resposta:
{
"id": "678",
"fraud_status": "automatically_approved"
}
Os campos opcionais (localização, capacidades do terminal, limites do cartão, endereço do lojista) não são exigidos pela validação, mas alimentam diretamente os modelos e as regras. Uma integração que envia apenas o mínimo funciona, mas tende a produzir mais falsos positivos.
Enviar uma transação para análise
Query parameters
analyze boolean opcional — padrãotrue
Quando true, a transação passa pelos motores de fraude e a resposta traz uma recomendação. Quando false, a transação é apenas registrada no histórico do portador (sem custo de análise) e a resposta retorna not_analyzed. Use analyze=false para transações que você já decidiu por outros meios, mas que devem compor o comportamento histórico do portador.
analyze=falseEnvie também transaction_status e response_code no corpo, informando o desfeito que você já aplicou. Sem isso, a transação fica registrada como pending e o histórico do portador perde informação.
Exemplos de requisição
- Python
- PHP
- Node.js
- Java
- C#
- curl
import requests
BASE_URL = "https://api.sandbox.caas.qitech.app"
API_KEY = "YOUR_API_KEY"
payload = {
"id": "678",
"cardholder_id": "b812da2e-e6be-4712-8e57-6f3f2791625b",
"amount": 13725,
"currency": "BRL",
"installments": 1,
"authorization_date": "2026-08-07T13:25:42-03:00",
"authorization_type": "authorization",
"transaction_type": "credit",
"pan_entry_mode": "chip",
"pin_sent": True,
"terminal": {"country_code": "BRA"},
"merchant": {"acquirer_id": "250", "merchant_id": "123456", "mcc": "5411"},
"card": {
"brand": "visa",
"category": "black",
"bin": "498406",
"last4": "1234",
"issuer_country_code": "BRA",
},
}
response = requests.post(
f"{BASE_URL}/card_issuance/transaction",
params={"analyze": "true"},
json=payload,
headers={"Authorization": API_KEY},
timeout=5,
)
response.raise_for_status()
print(response.json()) # {'id': '678', 'fraud_status': 'automatically_approved'}
<?php
$baseUrl = 'https://api.sandbox.caas.qitech.app';
$apiKey = 'YOUR_API_KEY';
$payload = [
'id' => '678',
'cardholder_id' => 'b812da2e-e6be-4712-8e57-6f3f2791625b',
'amount' => 13725,
'currency' => 'BRL',
'installments' => 1,
'authorization_date' => '2026-08-07T13:25:42-03:00',
'authorization_type' => 'authorization',
'transaction_type' => 'credit',
'pan_entry_mode' => 'chip',
'pin_sent' => true,
'terminal' => ['country_code' => 'BRA'],
'merchant' => [
'acquirer_id' => '250',
'merchant_id' => '123456',
'mcc' => '5411',
],
'card' => [
'brand' => 'visa',
'category' => 'black',
'bin' => '498406',
'last4' => '1234',
'issuer_country_code' => 'BRA',
],
];
$ch = curl_init($baseUrl . '/card_issuance/transaction?analyze=true');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: ' . $apiKey,
],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status !== 200) {
throw new RuntimeException("Antifraude retornou HTTP {$status}: {$body}");
}
$result = json_decode($body, true);
echo $result['fraud_status']; // automatically_approved
const BASE_URL = "https://api.sandbox.caas.qitech.app";
const API_KEY = "YOUR_API_KEY";
const payload = {
id: "678",
cardholder_id: "b812da2e-e6be-4712-8e57-6f3f2791625b",
amount: 13725,
currency: "BRL",
installments: 1,
authorization_date: "2026-08-07T13:25:42-03:00",
authorization_type: "authorization",
transaction_type: "credit",
pan_entry_mode: "chip",
pin_sent: true,
terminal: { country_code: "BRA" },
merchant: { acquirer_id: "250", merchant_id: "123456", mcc: "5411" },
card: {
brand: "visa",
category: "black",
bin: "498406",
last4: "1234",
issuer_country_code: "BRA",
},
};
async function analyzeTransaction() {
const response = await fetch(
`${BASE_URL}/card_issuance/transaction?analyze=true`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: API_KEY,
},
body: JSON.stringify(payload),
signal: AbortSignal.timeout(5000),
},
);
if (!response.ok) {
throw new Error(`Antifraude retornou HTTP ${response.status}`);
}
const result = await response.json();
console.log(result.fraud_status); // automatically_approved
return result;
}
analyzeTransaction();
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class AnalyzeTransaction {
private static final String BASE_URL = "https://api.sandbox.caas.qitech.app";
private static final String API_KEY = "YOUR_API_KEY";
public static void main(String[] args) throws Exception {
String payload = """
{
"id": "678",
"cardholder_id": "b812da2e-e6be-4712-8e57-6f3f2791625b",
"amount": 13725,
"currency": "BRL",
"installments": 1,
"authorization_date": "2026-08-07T13:25:42-03:00",
"authorization_type": "authorization",
"transaction_type": "credit",
"pan_entry_mode": "chip",
"pin_sent": true,
"terminal": { "country_code": "BRA" },
"merchant": {
"acquirer_id": "250",
"merchant_id": "123456",
"mcc": "5411"
},
"card": {
"brand": "visa",
"category": "black",
"bin": "498406",
"last4": "1234",
"issuer_country_code": "BRA"
}
}
""";
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(5))
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(BASE_URL + "/card_issuance/transaction?analyze=true"))
.header("Content-Type", "application/json")
.header("Authorization", API_KEY)
.timeout(Duration.ofSeconds(5))
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response =
client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
throw new IllegalStateException(
"Antifraude retornou HTTP " + response.statusCode() + ": " + response.body());
}
System.out.println(response.body());
// {"id":"678","fraud_status":"automatically_approved"}
}
}
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
public class AnalyzeTransaction
{
private const string BaseUrl = "https://api.sandbox.caas.qitech.app";
private const string ApiKey = "YOUR_API_KEY";
public static async Task Main()
{
var payload = new
{
id = "678",
cardholder_id = "b812da2e-e6be-4712-8e57-6f3f2791625b",
amount = 13725,
currency = "BRL",
installments = 1,
authorization_date = "2026-08-07T13:25:42-03:00",
authorization_type = "authorization",
transaction_type = "credit",
pan_entry_mode = "chip",
pin_sent = true,
terminal = new { country_code = "BRA" },
merchant = new { acquirer_id = "250", merchant_id = "123456", mcc = "5411" },
card = new
{
brand = "visa",
category = "black",
bin = "498406",
last4 = "1234",
issuer_country_code = "BRA"
}
};
using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(5) };
client.DefaultRequestHeaders.Add("Authorization", ApiKey);
var content = new StringContent(
JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
var response = await client.PostAsync(
$"{BaseUrl}/card_issuance/transaction?analyze=true", content);
var body = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
throw new InvalidOperationException(
$"Antifraude retornou HTTP {(int)response.StatusCode}: {body}");
}
Console.WriteLine(body);
// {"id":"678","fraud_status":"automatically_approved"}
}
}
curl -X POST \
'https://api.sandbox.caas.qitech.app/card_issuance/transaction?analyze=true' \
-H 'Content-Type: application/json' \
-H 'Authorization: YOUR_API_KEY' \
-d '{
"id": "678",
"cardholder_id": "b812da2e-e6be-4712-8e57-6f3f2791625b",
"amount": 13725,
"currency": "BRL",
"installments": 1,
"authorization_date": "2026-08-07T13:25:42-03:00",
"authorization_type": "authorization",
"transaction_type": "credit",
"pan_entry_mode": "chip",
"pin_sent": true,
"terminal": { "country_code": "BRA" },
"merchant": { "acquirer_id": "250", "merchant_id": "123456", "mcc": "5411" },
"card": {
"brand": "visa",
"category": "black",
"bin": "498406",
"last4": "1234",
"issuer_country_code": "BRA"
}
}'
Resposta
id que você enviou na requisição.fraud_statusenumA recomendação do motor antifraude. Veja fraud_status.{
"id": "678",
"fraud_status": "automatically_approved"
}
Se os motores de decisão ficarem indisponíveis, a API retorna automatically_approved em vez de erro. Isso é intencional: o antifraude nunca deve derrubar a autorização do cartão. Ainda assim, trate timeouts do seu lado com uma política de fallback definida.
Objeto Transaction
Campos raiz
id repetido retorna HTTP 409.cardholder_idstringobrigatórioIdentificador do portador no seu sistema. Máximo de 200 caracteres. É a chave que agrupa o histórico comportamental — use sempre o mesmo valor para o mesmo portador.amountintegerobrigatórioValor da transação em centavos, na moeda de currency. Entre 0 e 1000000000.currencyenumobrigatórioMoeda da transação em ISO 4217 (BRL, USD, EUR…), correspondente ao ApplicationCurrencyCode da ISO 8583.installmentsintegerobrigatórioNúmero de parcelas. Entre 0 e 24. Use 1 para transações à vista.authorization_datedatetimeobrigatórioData e hora de início da transação, com fuso horário, no formato YYYY-MM-DDThh:mm:ss±hh:mm. Veja a nota sobre o formato.authorization_typeenumobrigatórioTipo de autorização. Veja authorization_type.transaction_typeenumobrigatórioFunção utilizada: credit, debit ou prepaid.pan_entry_modeenumobrigatórioModo de entrada do PAN, derivado do DE 22 (Sub Field 1) da ISO 8583. Veja pan_entry_mode.pin_sentbooleanobrigatórioIndica se uma senha foi inserida no terminal.terminalobjectobrigatórioDados do terminal. Veja Objeto terminal.merchantobjectobrigatórioDados do estabelecimento. Veja Objeto merchant.cardobjectobrigatórioDados do cartão. Veja Objeto card.accountholder_idstringopcionalIdentificador do titular da conta, quando diferente do portador do cartão (cartões adicionais, cartões corporativos). Máximo de 200 caracteres.group_idstringopcionalGrupo ou categoria a que o portador pertence no seu sistema. Máximo de 200 caracteres. Útil para segmentar regras por carteira.brl_converted_amountintegeropcionalValor da transação convertido para reais, em centavos. Você não precisa enviar este campo — quando currency é diferente de BRL, a QI Tech calcula a conversão internamente; quando é BRL, o valor é igual a amount. Se enviado, é sobrescrito.locationobjectopcionalLocalização geográfica da transação. Veja Objeto location.authentication_typestringopcionalMétodo de autenticação aplicado à transação (por exemplo, o resultado de um 3-D Secure). Máximo de 200 caracteres.risk_assessmentenumopcionalClassificação de risco atribuída pela bandeira ou pelo adquirente na mensageria. Veja risk_assessment.cvv_presencebooleanopcionalIndica se o CVV foi informado na transação. Sinal relevante em transações de e-commerce.transaction_statusenumopcionalSituação da transação. Envie no POST apenas quando usar analyze=false e a decisão de autorização já tiver sido tomada. Veja transaction_status.response_codestringopcionalResponse code da transação conforme o campo Response Code da ISO 8583. Exatamente 1 ou 2 caracteres. Assim como transaction_status, faz sentido no POST apenas com analyze=false.{
"id": "678",
"cardholder_id": "b812da2e-e6be-4712-8e57-6f3f2791625b",
"accountholder_id": "0f5e2d1c-4a3b-4c6d-9e8f-1a2b3c4d5e6f",
"group_id": "8507884b-c30f-4b45-951c-f0bf366926fc",
"amount": 13725,
"currency": "BRL",
"installments": 6,
"authorization_date": "2026-08-07T13:25:42-03:00",
"authorization_type": "authorization",
"transaction_type": "credit",
"pan_entry_mode": "chip",
"pin_sent": true,
"source_account": "credit_facility",
"authentication_type": "3ds_authenticated",
"risk_assessment": "low_risk",
"cvv_presence": true,
"location": {
"latitude": -23.5613,
"longitude": -46.6565,
"altitude": 760
},
"terminal": {
"id": "12345678",
"country_code": "BRA",
"terminal_type": "5",
"pin_entry_capability": true,
"magnetic_stripe_capability": true,
"contactless_capability": true,
"chip_capability": true
},
"merchant": {
"acquirer_id": "250",
"merchant_id": "123456",
"payment_facilitator": "PAGSEGURO",
"sub_merchant": "LOJA 042",
"name": "SUPERMERCADO EXEMPLO",
"street": "RUA CMDTE X, 127",
"city": "SAO PAULO",
"region": "SP",
"postal_code": "04570-140",
"mcc": "5411"
},
"card": {
"brand": "visa",
"category": "black",
"holder_id": "b812da2e-e6be-4712-8e57-6f3f2791625b",
"issuing_date": "2025-10-08T07:13:12-03:00",
"unblock_date": "2025-10-12T07:13:12-03:00",
"expiration_date": "2030-12-31",
"bin": "498406",
"last4": "1234",
"total_credit_limit": 2500000,
"used_credit_limit": 732625,
"issuer_country_code": "BRA"
}
}
O schema usa additionalProperties: false em todos os objetos. Qualquer campo fora dos listados aqui faz a requisição retornar HTTP 400, mesmo que o restante do payload esteja correto.
Formato de authorization_date
O validador aceita apenas offsets de fuso terminados em :00 ou :30 (por exemplo -03:00, +05:30, -04:00). Sufixo Z e offsets como -03:15 são rejeitados com HTTP 400. Fração de segundo é opcional e aceita de 1 a 6 dígitos:
2026-08-07T13:25:42-03:00 ✅
2026-08-07T13:25:42.123456-03:00 ✅
2026-08-07T13:25:42Z ❌ use -00:00
2026-08-07T13:25:42-03:15 ❌ offset não permitido
A mesma regra vale para card.issuing_date e card.unblock_date.
Objeto terminal
BRA, USA, PRT…). Campo Terminal Country Code da ISO 8583.idstringopcionalIdentificador do terminal enviado pela adquirente. Máximo de 8 caracteres. String vazia é tratada como ausente.terminal_typestringopcionalTipo de terminal conforme TerminalType da ISO 8583. Máximo de 10 caracteres. Veja terminal_type.pin_entry_capabilitybooleanopcionalO terminal permite inserir senha? Campo TerminalPINEntryCapability da ISO 8583.magnetic_stripe_capabilitybooleanopcionalO terminal lê tarja magnética? Campo TerminalPANEntryCapability (DE 123).contactless_capabilitybooleanopcionalO terminal aceita transações por aproximação? Campo TerminalPANEntryCapability (DE 123).chip_capabilitybooleanopcionalO terminal lê chip EMV? Campo TerminalPANEntryCapability (DE 123).{
"terminal": {
"id": "12345678",
"country_code": "BRA",
"terminal_type": "5",
"pin_entry_capability": true,
"magnetic_stripe_capability": true,
"contactless_capability": true,
"chip_capability": true
}
}
Apenas country_code é obrigatório dentro de terminal. As versões antigas desta página listavam terminal_type, pin_entry_capability e chip_capability como obrigatórios — eles são opcionais.
Objeto merchant
{
"merchant": {
"acquirer_id": "250",
"merchant_id": "123456",
"payment_facilitator": "PAGSEGURO",
"sub_merchant": "LOJA 042",
"name": "SUPERMERCADO EXEMPLO",
"street": "RUA CMDTE X, 127",
"city": "SAO PAULO",
"region": "SP",
"postal_code": "04570-140",
"mcc": "5411"
}
}
Objeto card
cardholder_id possui múltiplos cartões. Máximo de 200 caracteres.issuing_datedatetimeopcionalData e hora de emissão do cartão, com fuso horário. Cartões recém-emitidos são um sinal de risco relevante.unblock_datedatetimeopcionalData e hora em que o portador desbloqueou o cartão, com fuso horário.expiration_datedateopcionalData de vencimento do cartão no formato YYYY-MM-DD (use o último dia do mês).total_credit_limitintegeropcionalLimite total de crédito do portador, em centavos. Para cartões pré-pagos, o saldo disponível.used_credit_limitintegeropcionalLimite já utilizado, em centavos, antes da transação em análise.{
"card": {
"brand": "visa",
"category": "black",
"holder_id": "b812da2e-e6be-4712-8e57-6f3f2791625b",
"issuing_date": "2025-10-08T07:13:12-03:00",
"unblock_date": "2025-10-12T07:13:12-03:00",
"expiration_date": "2030-12-31",
"bin": "498406",
"last4": "1234",
"total_credit_limit": 2500000,
"used_credit_limit": 732625,
"issuer_country_code": "BRA"
}
}
issuing_date e expiration_date não são obrigatórios, ao contrário do que a versão anterior desta página indicava. Os obrigatórios em card são apenas brand, category, bin, last4 e issuer_country_code.
Objeto location
location for enviadoLatitude da transação, entre -90 e 90.longitudenumberobrigatório se location for enviadoLongitude da transação, entre -180 e 180.altitudenumberopcionalAltitude em metros, entre 0 e 100000.{
"location": {
"latitude": -23.5613,
"longitude": -46.6565,
"altitude": 760
}
}
location como um todo é opcional. Mas se você enviar o objeto, latitude e longitude passam a ser obrigatórios dentro dele. Se não tiver a coordenada, omita o objeto inteiro em vez de enviá-lo vazio.
Enumeradores
authorization_type
| Valor | Significado |
|---|---|
authorization | Autorização de compra — MTI x1xx (DMS) e x2xx (SMS). |
pre_authorization | Pré-autorização para reserva de limite (hotel, locação de veículos, postos de combustível) — MTI x1xx (DMS) e Transaction Type 60 nos dois primeiros dígitos do Processing Code. |
reversal | Cancelamento de autorização, para liberar limite antes do Clearing/BASE II — MTI x4xx. |
transaction_type
| Valor | Significado |
|---|---|
credit | Transação na função crédito. |
debit | Transação na função débito. |
prepaid | Transação na função pré-pago. |
pan_entry_mode
Derivado do DE 22 (Sub Field 1) da ISO 8583.
| Valor | ISO 8583 | Significado |
|---|---|---|
unknown | 00 | Modo de entrada desconhecido. |
typed | 01 | PAN digitado manualmente. |
bar_code | 03 | PAN lido por código de barras. |
ocr | 04 | PAN lido por OCR. |
chip | 05 | PAN lido pelo chip EMV. |
track_1 | 06 | PAN lido pela Track 1 da tarja. |
contactless | 07 | PAN lido por aproximação (Contactless EMV). |
fallback_typed | 79 | Falha na leitura de chip/tarja e o PAN foi digitado. Também usado quando a adquirente não está homologada para chip ou tarja. |
fallback_magnetic_stripe | 80 | Falha na leitura do chip e a transação prosseguiu pela tarja magnética. |
ecommerce | 81 | Transação de e-commerce / cartão não presente. |
magnetic_stripe | 90 | Transação por tarja magnética. |
manual | — | Entrada manual dos dados do cartão fora do fluxo de terminal. |
stored_credentials | — | Transação com credenciais armazenadas (assinaturas, cobranças recorrentes, carteiras com cartão tokenizado). |
stored_credentials e recorrênciasTransações recorrentes marcadas como ecommerce tendem a receber mais recusas do que o esperado, porque o modelo as trata como cartão não presente sem contexto. Use stored_credentials sempre que a cobrança usar uma credencial previamente autorizada pelo portador.
source_account
Derivado do Processing Code da ISO 8583. Campo opcional.
| Valor | ISO 8583 | Significado |
|---|---|---|
default | 00 | Padrão ou não especificado. |
saving_account | 10 | Conta poupança. |
checking_account | 20 | Conta corrente. |
credit_facility | 30 | Fatura do cartão. |
universal_account | 40 | Conta universal. |
investment_account | 50 | Conta de investimento. |
electronic_purse | 60 | Saldo armazenado no chip do cartão. |
brand
| Valor | Bandeira |
|---|---|
visa | Visa |
mastercard | Mastercard |
elo | Elo |
diners_club | Diners Club |
american_express | American Express |
category
| Valor | Categoria |
|---|---|
classic | Classic |
gold | Gold |
platinum | Platinum |
black | Black / Infinite |
travel | Travel |
corporate | Corporate / Business |
prepaid | Pré-pago |
postpaid | Pós-pago |
terminal_type
Conforme TerminalType da ISO 8583. Enviado como string.
| Valor | Significado |
|---|---|
0 | Desconhecido |
1 | Nenhum terminal utilizado |
2 | Leitor de tarja magnética |
3 | Código de barras |
4 | OCR |
5 | Leitor de tarja magnética e de chip EMV |
6 | Apenas entrada por teclado |
7 | Leitor de tarja magnética e entrada por teclado |
8 | Leitor de tarja, entrada por teclado e chip EMV |
9 | Leitor de chip EMV |
risk_assessment
Classificação de risco recebida na mensageria (por exemplo, TRA da PSD2 ou avaliação da bandeira).
| Valor | Significado |
|---|---|
not_evaluated | Nenhuma avaliação de risco foi realizada. |
low_risk | A transação foi classificada como de baixo risco. |
non_low_risk | A transação não foi classificada como de baixo risco. |
transaction_status
Situação da transação no ciclo de vida da autorização.
| Valor | Significado |
|---|---|
pending | Autorização pendente. Estado inicial atribuído automaticamente. |
authorized | Autorizada, aguardando captura. |
not_authorized | Não autorizada pelo emissor. |
captured | Capturada. |
cleared | Recebida no Clearing / BASE II. |
cancelled | Cancelada integralmente. |
partially_cancelled | Cancelada parcialmente. |
chargeback | Recebeu chargeback integral. |
partial_chargeback | Recebeu chargeback parcial. |
pending não é enviávelpending é atribuído pela própria API quando a transação é criada sem decisão. Ele não é aceito no corpo do POST nem do PUT.
fraud_status
A recomendação devolvida pelo motor antifraude.
| Valor | Significado | Ação recomendada |
|---|---|---|
automatically_approved | O padrão da transação é compatível com o comportamento do portador. | Gerar o código de autorização. |
automatically_declined | A transação apresenta risco relevante de fraude. | Negar a autorização. |
not_analyzed | A requisição foi enviada com analyze=false. Nenhuma análise foi realizada. | Seguir a sua própria decisão. |
Atualizar o status de uma transação
Informar o desfecho real da transação é o que retroalimenta as regras e o modelo. Sem esse passo, a qualidade das recomendações degrada ao longo do tempo.
O TRANSACTION_ID no path é o mesmo id que você enviou no POST.
Corpo da requisição
O corpo aceita duas formas, escolhidas conforme o status:
- Atualização total
- Atualização parcial
Para qualquer status que afete a transação por inteiro.
authorized, not_authorized, captured, cleared, cancelled, partially_cancelled, chargeback ou partial_chargeback.response_codestringopcionalResponse code da ISO 8583. 1 ou 2 caracteres.{
"transaction_status": "captured",
"response_code": "00"
}
Obrigatória para partially_cancelled e partial_chargeback.
partially_cancelled ou partial_chargeback.partial_amountintegerobrigatórioValor cancelado/estornado em centavos, de 1 a 1000000000. Não pode exceder o valor ainda disponível da transação.response_codestringopcionalResponse code da ISO 8583. 1 ou 2 caracteres.{
"transaction_status": "partially_cancelled",
"partial_amount": 3000,
"response_code": "00"
}
Uma transação que já está em cancelled, partially_cancelled, chargeback ou partial_chargeback é considerada finalizada. Um novo PUT sobre ela retorna HTTP 400 com o título Transaction has a final status.
Consequência prática: você não consegue registrar dois cancelamentos parciais em sequência pela API. Planeje enviar o valor consolidado.
Em caso de sucesso, a resposta é HTTP 200 com corpo vazio ({}).
Exemplos de requisição
- Python
- PHP
- Node.js
- Java
- C#
- curl
import requests
BASE_URL = "https://api.sandbox.caas.qitech.app"
API_KEY = "YOUR_API_KEY"
TRANSACTION_ID = "678"
response = requests.put(
f"{BASE_URL}/card_issuance/transaction/{TRANSACTION_ID}",
json={"transaction_status": "captured", "response_code": "00"},
headers={"Authorization": API_KEY},
timeout=5,
)
response.raise_for_status() # 200 com corpo vazio
<?php
$baseUrl = 'https://api.sandbox.caas.qitech.app';
$apiKey = 'YOUR_API_KEY';
$transactionId = '678';
$payload = [
'transaction_status' => 'captured',
'response_code' => '00',
];
$ch = curl_init("{$baseUrl}/card_issuance/transaction/{$transactionId}");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: ' . $apiKey,
],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status !== 200) {
throw new RuntimeException("Falha ao atualizar status: HTTP {$status} — {$body}");
}
const BASE_URL = "https://api.sandbox.caas.qitech.app";
const API_KEY = "YOUR_API_KEY";
const TRANSACTION_ID = "678";
async function updateStatus() {
const response = await fetch(
`${BASE_URL}/card_issuance/transaction/${TRANSACTION_ID}`,
{
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: API_KEY,
},
body: JSON.stringify({
transaction_status: "captured",
response_code: "00",
}),
signal: AbortSignal.timeout(5000),
},
);
if (!response.ok) {
throw new Error(`Falha ao atualizar status: HTTP ${response.status}`);
}
}
updateStatus();
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class UpdateTransactionStatus {
private static final String BASE_URL = "https://api.sandbox.caas.qitech.app";
private static final String API_KEY = "YOUR_API_KEY";
private static final String TRANSACTION_ID = "678";
public static void main(String[] args) throws Exception {
String payload = """
{ "transaction_status": "captured", "response_code": "00" }
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(BASE_URL + "/card_issuance/transaction/" + TRANSACTION_ID))
.header("Content-Type", "application/json")
.header("Authorization", API_KEY)
.timeout(Duration.ofSeconds(5))
.PUT(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response =
client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
throw new IllegalStateException(
"Falha ao atualizar status: HTTP " + response.statusCode()
+ " — " + response.body());
}
}
}
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
public class UpdateTransactionStatus
{
private const string BaseUrl = "https://api.sandbox.caas.qitech.app";
private const string ApiKey = "YOUR_API_KEY";
private const string TransactionId = "678";
public static async Task Main()
{
var payload = new { transaction_status = "captured", response_code = "00" };
using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(5) };
client.DefaultRequestHeaders.Add("Authorization", ApiKey);
var content = new StringContent(
JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
var response = await client.PutAsync(
$"{BaseUrl}/card_issuance/transaction/{TransactionId}", content);
if (!response.IsSuccessStatusCode)
{
var body = await response.Content.ReadAsStringAsync();
throw new InvalidOperationException(
$"Falha ao atualizar status: HTTP {(int)response.StatusCode} — {body}");
}
}
}
curl -X PUT \
'https://api.sandbox.caas.qitech.app/card_issuance/transaction/678' \
-H 'Content-Type: application/json' \
-H 'Authorization: YOUR_API_KEY' \
-d '{ "transaction_status": "captured", "response_code": "00" }'
Recuperar uma transação
Retorna o estado atual da transação junto com o histórico completo de eventos. Se o id não existir para a sua API Key, a resposta é HTTP 404.
- Python
- PHP
- Node.js
- Java
- C#
- curl
import requests
BASE_URL = "https://api.sandbox.caas.qitech.app"
API_KEY = "YOUR_API_KEY"
TRANSACTION_ID = "678"
response = requests.get(
f"{BASE_URL}/card_issuance/transaction/{TRANSACTION_ID}",
headers={"Authorization": API_KEY},
timeout=5,
)
response.raise_for_status()
transaction = response.json()
print(transaction["fraud_status"], transaction["transaction_status"])
<?php
$baseUrl = 'https://api.sandbox.caas.qitech.app';
$apiKey = 'YOUR_API_KEY';
$transactionId = '678';
$ch = curl_init("{$baseUrl}/card_issuance/transaction/{$transactionId}");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
CURLOPT_HTTPHEADER => ['Authorization: ' . $apiKey],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status === 404) {
throw new RuntimeException("Transação {$transactionId} não encontrada.");
}
$transaction = json_decode($body, true);
echo $transaction['fraud_status'];
const BASE_URL = "https://api.sandbox.caas.qitech.app";
const API_KEY = "YOUR_API_KEY";
const TRANSACTION_ID = "678";
async function getTransaction() {
const response = await fetch(
`${BASE_URL}/card_issuance/transaction/${TRANSACTION_ID}`,
{ headers: { Authorization: API_KEY } },
);
if (response.status === 404) {
throw new Error(`Transação ${TRANSACTION_ID} não encontrada.`);
}
const transaction = await response.json();
console.log(transaction.fraud_status, transaction.transaction_status);
return transaction;
}
getTransaction();
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class GetTransaction {
private static final String BASE_URL = "https://api.sandbox.caas.qitech.app";
private static final String API_KEY = "YOUR_API_KEY";
private static final String TRANSACTION_ID = "678";
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(BASE_URL + "/card_issuance/transaction/" + TRANSACTION_ID))
.header("Authorization", API_KEY)
.timeout(Duration.ofSeconds(5))
.GET()
.build();
HttpResponse<String> response =
client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 404) {
throw new IllegalStateException("Transação " + TRANSACTION_ID + " não encontrada.");
}
System.out.println(response.body());
}
}
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
public class GetTransaction
{
private const string BaseUrl = "https://api.sandbox.caas.qitech.app";
private const string ApiKey = "YOUR_API_KEY";
private const string TransactionId = "678";
public static async Task Main()
{
using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(5) };
client.DefaultRequestHeaders.Add("Authorization", ApiKey);
var response = await client.GetAsync(
$"{BaseUrl}/card_issuance/transaction/{TransactionId}");
if (response.StatusCode == HttpStatusCode.NotFound)
{
throw new InvalidOperationException($"Transação {TransactionId} não encontrada.");
}
Console.WriteLine(await response.Content.ReadAsStringAsync());
}
}
curl 'https://api.sandbox.caas.qitech.app/card_issuance/transaction/678' \
-H 'Authorization: YOUR_API_KEY'
Resposta
A resposta devolve todos os campos que você enviou no POST, acrescidos dos campos abaixo.
Campos de transaction_events[]:
Campos de fraud_events[]:
reason e reason_description explicando por que a transação foi aprovada ou recusada.{
"id": "678",
"cardholder_id": "b812da2e-e6be-4712-8e57-6f3f2791625b",
"amount": 13725,
"brl_converted_amount": 13725,
"currency": "BRL",
"installments": 1,
"authorization_date": "2026-08-07T13:25:42-03:00",
"authorization_type": "authorization",
"transaction_type": "credit",
"pan_entry_mode": "chip",
"pin_sent": true,
"terminal": { "country_code": "BRA" },
"merchant": {
"acquirer_id": "250",
"merchant_id": "123456",
"mcc": "5411"
},
"card": {
"brand": "visa",
"category": "black",
"bin": "498406",
"last4": "1234",
"issuer_country_code": "BRA"
},
"fraud_status": "automatically_approved",
"transaction_status": "captured",
"fraud_events": [
{
"new_status": "automatically_approved",
"event_date": "2026-08-07T16:25:43Z",
"decision_metadata": {
"reason": "automatically_approved",
"reason_description": "O padrão transacional foi normal."
}
}
],
"transaction_events": [
{
"new_status": "authorized",
"event_date": "2026-08-07T16:25:43Z"
},
{
"new_status": "captured",
"event_date": "2026-08-07T18:02:10Z",
"response_code": "00"
}
]
}
Erros
Todos os erros retornam um corpo JSON com o mesmo formato:
{
"title": "Duplicated external_id",
"description": "id: 678 already exists for company 3fa85f64-5717-4562-b3fc-2c963f66afa6"
}
| Status | Situação | Como resolver |
|---|---|---|
| 400 | Payload inválido: campo obrigatório ausente, enum fora da lista, formato de data incorreto ou campo não previsto pelo schema. | Confira a description, que aponta o campo com problema. |
| 400 | Transaction has a final status no PUT. | A transação já está em status final e não aceita novas atualizações. |
| 400 | partial_amount maior que o valor disponível. | Envie um valor menor ou igual ao saldo ainda não cancelado. |
| 401 | Header Authorization ausente ou API Key desativada. | Verifique o header e o status da sua chave. |
| 403 | API Key inválida ou endpoint de uso interno. | Confirme a chave com o suporte. |
| 404 | Transação não encontrada para a sua API Key. | Verifique o id usado no path. |
| 406 | Corpo da requisição não é um JSON válido. | Verifique o Content-Type e a serialização. |
| 409 | id já processado anteriormente. | Gere um id único por processo de autorização. |
| 500 | Erro interno. | Nossos especialistas são notificados automaticamente. |
| 503 | Indisponibilidade de infraestrutura. | Aplique retry com backoff. |
A lista completa está em Status HTTP.
Testando no Sandbox
No Sandbox as análises não são cobradas e a decisão é determinística, baseada apenas no valor da transação:
amount | fraud_status retornado |
|---|---|
>= 10000 (R$ 100,00 ou mais) | automatically_approved |
<= 9999 (até R$ 99,99) | automatically_declined |
Base URL de Sandbox: https://api.sandbox.caas.qitech.app
Não utilize dados reais de pessoas físicas ou jurídicas no ambiente de Sandbox da QI Tech.
Checklist de integração
-
POST /card_issuance/transactioncom o payload mínimo retornando200no Sandbox. -
idúnico garantido por processo de autorização (teste o409reenviando o mesmoid). -
cardholder_idestável para o mesmo portador entre transações. -
authorization_dateno formato com offset:00ou:30. - Valores monetários em centavos, como inteiros.
- Tratamento de timeout com política de fallback definida (aprovar ou negar por conta própria).
-
PUTenviado em todos os desfechos: captura, cancelamento, chargeback. - Webhook de Alertas de Portadores configurado com o suporte.