Criar transações em lote
curl --request POST \
--url http://api.gu1.ai/transactions/batch \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"transactions": [
{}
],
"executeRules": true,
"skipDuplicates": true,
"linkEntityStrict": true,
"validateExistingEntity": true,
"sources": [
{}
]
}
'import requests
url = "http://api.gu1.ai/transactions/batch"
payload = {
"transactions": [{}],
"executeRules": True,
"skipDuplicates": True,
"linkEntityStrict": True,
"validateExistingEntity": True,
"sources": [{}]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
transactions: [{}],
executeRules: true,
skipDuplicates: true,
linkEntityStrict: true,
validateExistingEntity: true,
sources: [{}]
})
};
fetch('http://api.gu1.ai/transactions/batch', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "http://api.gu1.ai/transactions/batch",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'transactions' => [
[
]
],
'executeRules' => true,
'skipDuplicates' => true,
'linkEntityStrict' => true,
'validateExistingEntity' => true,
'sources' => [
[
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "http://api.gu1.ai/transactions/batch"
payload := strings.NewReader("{\n \"transactions\": [\n {}\n ],\n \"executeRules\": true,\n \"skipDuplicates\": true,\n \"linkEntityStrict\": true,\n \"validateExistingEntity\": true,\n \"sources\": [\n {}\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("http://api.gu1.ai/transactions/batch")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"transactions\": [\n {}\n ],\n \"executeRules\": true,\n \"skipDuplicates\": true,\n \"linkEntityStrict\": true,\n \"validateExistingEntity\": true,\n \"sources\": [\n {}\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("http://api.gu1.ai/transactions/batch")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"transactions\": [\n {}\n ],\n \"executeRules\": true,\n \"skipDuplicates\": true,\n \"linkEntityStrict\": true,\n \"validateExistingEntity\": true,\n \"sources\": [\n {}\n ]\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"created": 123,
"skipped": 123,
"failed": 123,
"transactions": [
{}
],
"errors": [
{}
],
"processingTime": "<string>",
"jobId": "<string>",
"status": "<string>",
"message": "<string>",
"fileCount": 123
}Referência API
Criar transações em lote
Criar múltiplas transações em uma única chamada para cenários de alto volume — na API de monitoramento de transações gu1 para fraude e AML.
POST
/
transactions
/
batch
Criar transações em lote
curl --request POST \
--url http://api.gu1.ai/transactions/batch \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"transactions": [
{}
],
"executeRules": true,
"skipDuplicates": true,
"linkEntityStrict": true,
"validateExistingEntity": true,
"sources": [
{}
]
}
'import requests
url = "http://api.gu1.ai/transactions/batch"
payload = {
"transactions": [{}],
"executeRules": True,
"skipDuplicates": True,
"linkEntityStrict": True,
"validateExistingEntity": True,
"sources": [{}]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
transactions: [{}],
executeRules: true,
skipDuplicates: true,
linkEntityStrict: true,
validateExistingEntity: true,
sources: [{}]
})
};
fetch('http://api.gu1.ai/transactions/batch', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "http://api.gu1.ai/transactions/batch",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'transactions' => [
[
]
],
'executeRules' => true,
'skipDuplicates' => true,
'linkEntityStrict' => true,
'validateExistingEntity' => true,
'sources' => [
[
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "http://api.gu1.ai/transactions/batch"
payload := strings.NewReader("{\n \"transactions\": [\n {}\n ],\n \"executeRules\": true,\n \"skipDuplicates\": true,\n \"linkEntityStrict\": true,\n \"validateExistingEntity\": true,\n \"sources\": [\n {}\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("http://api.gu1.ai/transactions/batch")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"transactions\": [\n {}\n ],\n \"executeRules\": true,\n \"skipDuplicates\": true,\n \"linkEntityStrict\": true,\n \"validateExistingEntity\": true,\n \"sources\": [\n {}\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("http://api.gu1.ai/transactions/batch")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"transactions\": [\n {}\n ],\n \"executeRules\": true,\n \"skipDuplicates\": true,\n \"linkEntityStrict\": true,\n \"validateExistingEntity\": true,\n \"sources\": [\n {}\n ]\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"created": 123,
"skipped": 123,
"failed": 123,
"transactions": [
{}
],
"errors": [
{}
],
"processingTime": "<string>",
"jobId": "<string>",
"status": "<string>",
"message": "<string>",
"fileCount": 123
}Visão geral
Cria múltiplas transações em uma única operação em lote. Este endpoint é otimizado para alto volume. Limites:- Um único lote: até 100.000 transações por requisição; corpo da requisição não deve exceder 50 MB.
- Múltiplos arquivos em uma chamada: use
POST /transactions/batch/background-multicom arraysources(até 5 arquivos, 100.000 transações cada); limite do corpo 150 MB. - Carga por arquivos (multipart): use
POST /transactions/batch/uploadpara enviar arquivos CSV, Excel ou JSON diretamente; máx. 5 arquivos por requisição. O limite por arquivo depende do seu plano.
- A API mantém a conexão aberta por até 30 segundos.
- Se o lote terminar em 30 segundos, retorna 200 com o resumo completo (criadas, ignoradas, regras executadas, tempo, etc.).
- Se ultrapassar 30 segundos, retorna 202 com um
jobIde continua processando em segundo plano. Ao terminar, o cliente é notificado no dashboard (e via socket em tempo real se conectado).
POST /transactions/batch/background— Um único lote; retorna 202 imediatamente e notifica via socket ao terminar.POST /transactions/batch/background-multi— Múltiplos arquivos em uma requisição (máx. 5); retorna 202 e uma notificação quando todos forem processados.POST /transactions/batch/upload— Multipart form-data: envie um ou mais arquivos (CSV, Excel, JSON) no campofile; o servidor faz o parse e executa o mesmo fluxo. Ideal quando você tem arquivos em vez de JSON.
Endpoints
POST http://api.gu1.ai/transactions/batch
POST http://api.gu1.ai/transactions/batch/background
POST http://api.gu1.ai/transactions/batch/background-multi
POST http://api.gu1.ai/transactions/batch/upload (multipart/form-data)
Carga por arquivos (multipart)
UsePOST /transactions/batch/upload quando tiver arquivos CSV, Excel ou JSON e quiser que o servidor faça o parse. A requisição deve ser multipart/form-data (FormData), não JSON.
- Máx. 5 arquivos por requisição.
- Formatos aceitos: CSV (
.csv), Excel (.xlsx,.xls), JSON (.json). - Limite de transações por arquivo conforme o plano da organização (ver Limites por plano).
- Query:
validateGap(padrãofalse). Se você enviarvalidateGap=truecom vários arquivos, a API verifica se não há intervalo de 30 minutos ou mais entre o fim de um arquivo e o início do próximo (portransactedAt). Se houver, retorna 400 comcode: "GAP_VALIDATION_REQUIRED"e a lista de intervalos. Por padrão a validação está desativada; use?validateGap=truepara ativá-la.
Campos do form
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
file | File | Sim | Um ou mais arquivos (CSV, Excel, JSON). Repita o campo file para vários arquivos. |
executeRules | string | Não | "true" (padrão) ou "false" |
skipDuplicates | string | Não | "true" (padrão) ou "false" |
linkEntityStrict | string | Não | Override opcional: "true" hard-fail / "false" soft-link. Omitir → validateExistingEntity |
validateExistingEntity | string | Não | "true" (padrão se omitido) ou "false" |
Exemplo: envio com FormData (JavaScript)
const form = new FormData();
form.append('file', fileInput.files[0]);
form.append('executeRules', 'true');
form.append('skipDuplicates', 'true');
form.append('validateExistingEntity', 'true'); // padrão do lote se omitido
const response = await fetch('http://api.gu1.ai/transactions/batch/upload', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
body: form // Não defina Content-Type; o navegador define o boundary multipart
});
const data = await response.json();
Exemplo: cURL
curl -X POST http://api.gu1.ai/transactions/batch/upload \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "file=@transacoes.csv" \
-F "executeRules=true" \
-F "skipDuplicates=true"
Limites por plano
O máximo de transações por arquivo (tanto no upload quanto no background-multi) depende do plano da organização:| Plano | Máx. transações por arquivo |
|---|---|
| Freemium | 4.000 |
| Startup | 12.000 |
| Growth | 30.000 |
| Enterprise | 100.000 |
| Por uso (pay-as-you-go) | 100.000 |
Concorrência
Um lote de transações vivo (queued ou running) por organização. Um segundo upload de transações enquanto outro de transações está em andamento retorna 409 JOB_IN_PROGRESS. Se a org já tem um lote de entidades na fila, este POST retorna 409 JOB_ALREADY_WAITING (no máximo um job em espera por organização). Se um lote de entidades está running e ninguém espera, este POST retorna 202 queued (code: "QUEUED_WAITING_PREVIOUS_JOB", queue.waitingForOrgJob: true) e começa quando esse job termina. No máximo 2 organizações processam lotes de transações ao mesmo tempo; as demais recebem 202 com code: "QUEUED_WAITING_SLOT", status: "queued" e um snapshot queue (não 409). O job permanece running até terminar a avaliação de regras enfileirada quando executeRules é true. Veja Importações em lote — Concorrência.
Modelos (templates)
Para montar arquivos CSV, Excel ou JSON que atendam ao esquema:- Dashboard: Em Monitoramento de transações, abra o modal Carga em lote. Use os botões Baixar CSV, Baixar Excel ou Baixar JSON para obter modelos com os cabeçalhos corretos e uma linha de exemplo. É a forma mais fácil de começar.
- Campos obrigatórios por linha: Cada transação deve incluir pelo menos
externalId,type,amountecurrency. Recomendados:transactedAt,status,originName,destinationName,description. Esquema completo em Criar transação. - CSV/Excel: Os nomes das colunas podem ser camelCase (
externalId,transactedAt) ou snake_case (external_id,transacted_at); o servidor normaliza. Data em ISO 8601 (ex.2025-01-15T10:30:00.000Z).
Autenticação
Authorization: Bearer YOUR_API_KEY
Corpo (sync e background)
array
required
Array de objetos de transação (mín. 1, máx. 100.000 por requisição). Mesma estrutura de Criar transação. Corpo máx. 50 MB.
exchangeRate opcional por linha: somente quando a conversão automática falha. A taxa automática existe só para os códigos de Moedas com conversão automática. Ordem de resolução: Conversão de moeda.boolean
default:"true"
Se as regras são executadas para todas as transações do lote
boolean
default:"true"
Ignorar transações com
externalId duplicado em vez de falhar todo o loteboolean
Override opcional.
true: hard-fail. false: soft-link. Se omitido, segue validateExistingEntity. Também ?linkEntityStrict=true|false.boolean
default:"true"
Padrão do lote
true (sem mudança para quem omite o campo): refs não resolvidas → 400. Com false: auto-vincula se encontrar e segue sem vínculo se não.*EntityId e pode preencher nome/país a partir da entidade, como no create único.
Com lado vinculado (inclusive quando você já enviou *EntityId), originTaxId / originExternalId e destinationTaxId / destinationExternalId são sempre sincronizados a partir da entidade antes do insert — mesma denormalização canônica de Criar transação — origem.
Cada linha criada também recebe o campo linkedEntityGu1, controlado pelo servidor, dentro de originDetails e destinationDetails. O valor é linked, unresolved ou not_requested. Gu1 ignora e sobrescreve qualquer valor incluído no arquivo.
Corpo (apenas background-multi)
array
required
Array de objetos:
{ "fileName": "opcional", "transactions": [ ... ] }. Mín. 1, máx. 5 fontes. Cada transactions: máx. 100.000 (ou o limite do seu plano por arquivo). Corpo total máx. 150 MB.Resposta 200 (concluído em 30 s)
boolean
Se a operação em lote foi concluída com sucesso
number
Número de transações criadas
number
Ignoradas (duplicados ou erros de validação)
number
Falhas
array
Transações criadas
array
Erros por transação:
index, externalId, error, codestring
Tempo total de processamento
Resposta 202 (processamento > 30 s ou background)
string
Identificador do job; correlacione com a notificação em tempo real ao concluir
string
"processing"string
Mensagem indicando que o processo continua em segundo plano e será notificado no dashboard
number
(Apenas background-multi.) Número de arquivos em processamento
Exemplo de uso
curl -X POST http://api.gu1.ai/transactions/batch \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"transactions": [
{
"externalId": "txn_001",
"type": "PAYMENT",
"amount": 50.00,
"currency": "USD",
"originExternalId": "customer_001",
"destinationExternalId": "merchant_100",
"channel": "web_browser"
}
],
"executeRules": true,
"skipDuplicates": true
}'
import requests
response = requests.post(
'http://api.gu1.ai/transactions/batch',
headers={'Authorization': f'Bearer {API_KEY}', 'Content-Type': 'application/json'},
json={
'transactions': transactions,
'executeRules': True,
'skipDuplicates': True
}
)
result = response.json()
print(f"Criadas: {result['created']}, Ignoradas: {result['skipped']}, Falhas: {result['failed']}")
Erros
- 400 - Lote vazio ou tamanho excedido (máx. 100.000 por requisição)
- 413 - Corpo > 50 MB (ou 150 MB no multi). Dividir em lotes menores.
Boas práticas
- Respeitar limites: 100.000 por requisição, 50 MB (150 MB no multi).
- Sempre usar
skipDuplicates: true. - Para importação histórica:
executeRules: falsee opcionalmentevalidateExistingEntity: false. - Tratar 200 vs 202: 200 = resultado no corpo; 202 = job em background, aguardar notificação.
- Validar campos obrigatórios conforme Criar transação.
- Usar background-multi para muitos arquivos (até 10 em uma chamada).
Próximos passos
- Criar transação - Uma transação
- Alterar status da transação - Alterar status
- Monitoramento de transações - Detecção de fraude
Was this page helpful?