> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gu1.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Criar transação

> Criar uma nova transação financeira para monitoramento e análise — na API de monitoramento de transações gu1 para fraude e AML, com exemplos para create.

## Visão geral

Cria uma nova transação. Com `executeRules: true` (padrão), o motor de regras roda **de forma síncrona** e a resposta inclui `rulesExecutionSummary` completo quando as regras terminam na mesma request.

Sem enviar `asyncRules` (padrão `false`), o comportamento permanece o mesmo — integrações existentes não mudam.

## Endpoint

```
POST http://api.gu1.ai/transactions
```

## Autenticação

Requer uma API key válida no header Authorization:

```bash theme={null}
Authorization: Bearer YOUR_API_KEY
```

## Parâmetros de query

<ParamField query="asyncRules" type="boolean" default="false">
  Com `true` **e** `executeRules` diferente de `false`, a transação é criada na hora e a avaliação de regras é **enfileirada** em background. A resposta HTTP retorna antes das regras terminarem. O query param tem precedência sobre o mesmo campo no body JSON.

  Valores truthy aceitos: `true`, `1`, `"true"`, `"1"`, `"yes"`.

  **Não se aplica** a endpoints batch — apenas `POST /transactions` (criação unitária).
</ParamField>

## Corpo da requisição

### Campos obrigatórios

<ParamField body="externalId" type="string" required>
  Seu identificador único para esta transação no seu sistema
</ParamField>

<ParamField body="type" type="string" required>
  Tipo da transação. Opções:

  * `PAYMENT` - Pagamento
  * `TRANSFER` - Transferência
  * `WITHDRAWAL` - Saque
  * `DEPOSIT` - Depósito
  * `REFUND` - Reembolso
  * `CHARGEBACK` - Chargeback
  * `REVERSAL` - Estorno
  * `FEE` - Taxa
  * `ADJUSTMENT` - Ajuste
  * `OTHER` - Outro
</ParamField>

<ParamField body="amount" type="number" required>
  Valor (deve ser zero ou positivo)
</ParamField>

<ParamField body="currency" type="string" required>
  Código da moeda (3-4 caracteres, ex.: "USD", "EUR", "BRL")
</ParamField>

<ParamField body="exchangeRate" type="number">
  Taxa de câmbio opcional, usada **somente** quando a conversão automática para a moeda base da organização não está disponível (erro do provedor, timeout ou par não suportado). **Se omitir este campo, o comportamento permanece o mesmo** — o Gueno consulta o serviço de moedas como hoje.

  **Semântica:** unidades da moeda base por **1 unidade** de `currency`. Valor normalizado na moeda base da org: `valorNormalizado = amount × exchangeRate`.

  Ignorada quando a conversão automática tem sucesso (prevalece a taxa do provedor).

  Necessária quando a conversão automática não está disponível para **moedas não conversíveis** (ver abaixo). Ver [Conversão de moeda](#conversão-de-moeda).
</ParamField>

### Campos opcionais

<ParamField body="status" type="string" default="CREATED">
  Status. Opções: `CREATED`, `PROCESSING`, `SUSPENDED`, `SENT`, `EXPIRED`, `DECLINED`, `REFUNDED`, `SUCCESSFUL`
</ParamField>

<ParamField body="paymentMethod" type="string">
  Método de pagamento. Opções: `CARD`, `ACH`, `PIX`, `TED`, `BOLETO`, `WALLET`, `SWIFT`, `IBAN`, `CBU`, `CVU`, `DEBIN`, etc.
</ParamField>

<ParamField body="description" type="string">
  Descrição ou notas
</ParamField>

<ParamField body="category" type="string">
  Categoria da transação
</ParamField>

<ParamField body="transactedAt" type="string">
  Data/hora ISO 8601 do fato (padrão: momento da criação). Gravado em UTC. Use `Z` ou offset `±HH:MM` no string, **ou** datetime sem offset junto com `timeZone` (horário local nesse fuso).
</ParamField>

<ParamField body="executeRules" type="boolean" default="true">
  Se o motor de regras deve rodar. Com `false`, pula regras por completo (sync e async).
</ParamField>

<ParamField body="asyncRules" type="boolean" default="false">
  Mesma semântica do query `asyncRules`. Para ingestão em alto volume: persistir a transação rápido e revisar alertas depois no gu1. Requer `executeRules: true` (padrão). Ignorado se `executeRules` for `false`.
</ParamField>

<ParamField body="configRulesExecution" type="object">
  Ajuste opcional da execução de regras após a criação (sync ou async). **Não** desativa ações `createAlert` nem a consolidação de investigações.

  | Campo           | Tipo      | Padrão                                                                                                                  |
  | --------------- | --------- | ----------------------------------------------------------------------------------------------------------------------- |
  | `notifications` | `boolean` | `true` na maioria das organizações; **`false` na Paytime prod** (`3bc1f621-27d4-423e-9d64-86680bec2388`) quando omitido |

  Com `notifications: false`, o gu1 não envia **notificações in-app** da avaliação de regras (matriz de risco / mudanças de status). Alertas e investigações seguem o fluxo normal.

  **Legacy KYT** `POST /legacy/kyt/verifyTransaction`: mesmo objeto no body Gu2 como `configRulesExecution`; se omitido, Paytime prod recebe `notifications: false` por padrão (igual a `POST /transactions`).
</ParamField>

<ParamField body="validateExistingEntity" type="boolean" default="false">
  Com **`false`** (padrão): se você enviar `originExternalId` / `destinationExternalId` (ou tax na raiz) e não houver entidade, a transação **ainda é criada** (sem vínculo), como antes.

  Com **`true`**: cada lado (origem / destino) só é validado se você enviar pelo menos um identificador daquele lado (`originEntityId`, `originExternalId` ou `originTaxId`; o mesmo para destino). Cada campo enviado deve resolver para uma pessoa/empresa existente na organização; caso contrário a API retorna **400** com `INVALID_ENTITY_REFERENCES` e **não** cria a transação. Se não enviar identificadores de origem (ou destino), esse lado não é validado.
</ParamField>

### Matrizes de risco (opcional)

<ParamField body="riskMatrixId" type="string | string[]">
  Compatível com clientes antigos: um UUID ou um **array de UUIDs** de matrizes da organização. Se enviar lista não vazia, apenas regras ativas ligadas a essas matrizes são avaliadas (sem misturar com regras “soltas” só por triggers). Omita `riskMatrixId` e `riskMatrixIds` para manter o comportamento histórico por triggers.
</ParamField>

<ParamField body="riskMatrixIds" type="string[]">
  Preferido para **várias** matrizes: lista ordenada de UUIDs. Tem precedência sobre `riskMatrixId` quando informado e não vazio.
</ParamField>

### Origem (entidade)

<Info>
  **Como a origem é vinculada no gu1** (em ordem; para no primeiro sucesso):

  1. **ID da entidade** — com `originEntityId`, a transação usa essa entidade (deve existir na org).
  2. **ID externo** — sem `originEntityId`, com `originExternalId`, se houver pessoa/empresa com o mesmo `externalId`, a transação **vincula automaticamente**.
  3. **Terceiro fallback: documento / tax ID (raiz)** — ainda sem vínculo, com `originTaxId` no **raiz** do corpo, o API procura pessoa/empresa cujo `taxId` coincida após **normalizar** (apenas letras e números, ignorando pontuação; comparação em maiúsculas no match).

  Nos passos **2** e **3**, o API preenche `originEntityId` e, se você não enviou, pode preencher **name** e **country** a partir da entidade.

  **Denormalização canônica (origem vinculada):** quando a origem está vinculada a pessoa/empresa — você enviou `originEntityId`, ou o auto-link resolveu por `originExternalId` / `originTaxId` — o gu1 **sincroniza as colunas denormalizadas a partir da entidade** antes do insert:

  | Campo na transação | Origem na entidade     | Valor do cliente é mantido?                                     |
  | ------------------ | ---------------------- | --------------------------------------------------------------- |
  | `originEntityId`   | `entities.id`          | Definido no auto-link; inalterado se você já enviou UUID válido |
  | `originTaxId`      | `entities.tax_id`      | **Não** — sempre sobrescrito pela entidade vinculada            |
  | `originExternalId` | `entities.external_id` | **Não** — sempre sobrescrito pela entidade vinculada            |

  Se a entidade não tem `taxId` ou `externalId`, a coluna correspondente na transação fica **`null`**, mesmo que você tenha enviado valores no body.

  **Nota para integradores:** você pode enviar qualquer combinação de identificadores para vincular (precedência: `originEntityId` → `originExternalId` → `originTaxId`). Após o vínculo, `originTaxId` / `originExternalId` **persistidos** refletem a **entidade no gu1**, não necessariamente o que digitou. Isso alinha regras transacionais com [eventos de usuário](/pt/api-reference/events/create).

  Sem match, a transação **é criada** mesmo assim, com os campos enviados, **sem** vínculo.\
  (`originDetails.taxId` ajuda no **grafo** mas **não** vincula entidade; use `originTaxId` na **raiz** para vincular por documento.)
</Info>

<ParamField body="originEntityId" type="string">
  UUID da entidade de origem no gu1
</ParamField>

<ParamField body="originExternalId" type="string">
  Seu ID externo da entidade de origem. Segundo critério de vínculo sem `originEntityId`. **Após vincular**, o valor gravado é **`entities.external_id`** (valor do cliente não é mantido se diferir).
</ParamField>

<ParamField body="originTaxId" type="string">
  CPF/CNPJ ou outro **tax ID** de origem no **raiz** da requisição. **Terceiro** critério após `originEntityId` e `originExternalId`. Comparação com `entity.taxId` de forma normalizada. Se achar, preenche vínculo, nome e país. **Após vincular**, gravado como **`entities.tax_id`**. Opcional, máx. 50 caracteres.
</ParamField>

<ParamField body="originName" type="string">
  Nome da origem
</ParamField>

<ParamField body="originCountry" type="string">
  Código de país ISO 2 da origem (ex.: "US", "BR", "AR")
</ParamField>

<ParamField body="originDetails" type="object">
  Detalhes da origem (dispositivo, conta, etc.). Ver [Schema de payment details](/pt/api-reference/transactions/payment-details-schema). Campos extras permitidos. Se a origem **não** for uma entidade no gu1, envie identificadores em `originDetails.paymentDetails` para agrupar nós pseudo (`taxId`, `cbu`, `cvu`, `pixKey`, `clabe`, `alias`, `iban`, `holderId`, `debinId`, `cardFingerprint`, `accountNumber` + `bankCode` opcional — ver prioridade no schema).
</ParamField>

### Destino (entidade)

<Info>
  **Vínculo do destino:** mesma precedência da origem: `destinationEntityId` → `destinationExternalId` → `destinationTaxId`.

  Com destino vinculado, o gu1 **sempre sincroniza** `destinationTaxId` e `destinationExternalId` a partir da entidade (mesmas regras da origem). Sem vínculo, mantém os valores enviados.
</Info>

<ParamField body="destinationEntityId" type="string">
  UUID da entidade de destino no gu1
</ParamField>

<ParamField body="destinationExternalId" type="string">
  Seu ID externo da entidade de destino. **Após vincular**, gravado como **`entities.external_id`**.
</ParamField>

<ParamField body="destinationTaxId" type="string">
  Tax / documento do **destino** no **raiz**; **terceiro** fallback depois de `destinationEntityId` e `destinationExternalId`. Mesma regra de `originTaxId`. **Após vincular**, gravado como **`entities.tax_id`**. Opcional, máx. 50 caracteres.
</ParamField>

<ParamField body="destinationName" type="string">
  Nome do destino
</ParamField>

<ParamField body="destinationCountry" type="string">
  Código de país ISO 2 do destino
</ParamField>

<ParamField body="destinationDetails" type="object">
  Detalhes do destino (comerciante, conta, etc.). Campos opcionais; extras permitidos. Se o destino **não** for uma entidade no gu1, envie os mesmos identificadores em `destinationDetails.paymentDetails` para agrupar nós pseudo (mesma prioridade que origem — ver [Payment Details Schema](/pt/api-reference/transactions/payment-details-schema)).
</ParamField>

### Localização e dispositivo

<ParamField body="locationDetails" type="object">
  Localização: `country`, `city`, `region`, `address`, `latitude`, `longitude`, `postalCode`, etc.
</ParamField>

<ParamField body="deviceDetails" type="object">
  Dispositivo: `deviceId`, `platform`, `osName`, `model`, `ipAddress`, `isVpn`, `isTor`, etc.
</ParamField>

<ParamField body="channel" type="string">
  Canal (máx. 50 caracteres): `mobile_app`, `web_browser`, `pos_terminal`, `api`, `atm`, etc.
</ParamField>

<ParamField body="reason" type="string">
  Motivo do resultado (opcional). Ver [Enum de motivos](/pt/api-reference/transactions/reason-enum). Se omitido, usa `WITHOUT_REASON`.
</ParamField>

<ParamField body="timeZone" type="string">
  Fuso horário IANA opcional (independente de `operationalHours` da entidade). Valores de **transaction\_time\_zone**. Se omitido, fica `null`.

  **Normalização de `transactedAt`:** se `transactedAt` tiver `Z` (como exige o validador deste endpoint), esse instante é gravado em UTC; `timeZone` é metadata opcional e não entra no parse. Com datetime local + `timeZone` (ferramentas internas/lote), a API pode converter horário local para UTC. Integrações que não enviam `timeZone` continuam como antes. Regras de horário operacional usam o instante gravado + `operationalHours.timezone` da entidade, não `transaction.timeZone`.

  **Lista completa:** [Enum fuso horário](/pt/api-reference/transactions/time-zone-enum).
</ParamField>

<ParamField body="metadata" type="object">
  Metadados adicionais: `tags`, `purpose`, `enhanced_due_diligence`, `block_reason`, `compliance_alert`, etc.
</ParamField>

## Resposta

<ResponseField name="transaction" type="object">
  A transação criada (objeto). Inclui: `id`, `externalId`, `organizationId`, `type`, `amount` (string), `currency`, `status`, `riskScore` (string), `flagged`, `channel`, `reason`, `timeZone` (`string | null`), `originDetails`, `destinationDetails`, `locationDetails`, `deviceDetails`, `processingTimeMs`, `processedAt`, `transactedAt`, `createdAt`, `updatedAt`.
</ResponseField>

<ResponseField name="rulesExecutionSummary" type="object">
  Presente quando **executeRules** é true.

  **Síncrono (padrão):** completo após as regras terminarem na mesma request.

  **Async (`asyncRules=true`):** placeholder com `success: true`, `rulesHit` / `rulesNoHit` vazios e `matchedRulesCount: 0`. Alertas e score atualizam quando o processamento em background termina.

  Omitido se `executeRules` for `false`. Ver [Resumo de Execução de Regras](/pt/api-reference/rules-execution-summary).
</ResponseField>

<ResponseField name="asyncRules" type="boolean">
  Presente e `true` apenas quando as regras foram **enfileiradas**. Omitido no fluxo síncrono padrão.
</ResponseField>

<ResponseField name="rulesEvaluationStatus" type="string">
  No modo async: `"queued"`. Omitido quando as regras rodaram de forma síncrona.
</ResponseField>

## Exemplo básico

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST http://api.gu1.ai/transactions \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "externalId": "txn_12345",
      "type": "PAYMENT",
      "amount": 150.50,
      "currency": "USD",
      "originExternalId": "customer_001",
      "destinationExternalId": "merchant_456",
      "description": "Compra online"
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('http://api.gu1.ai/transactions', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      externalId: 'txn_12345',
      type: 'PAYMENT',
      amount: 150.50,
      currency: 'USD',
      originExternalId: 'customer_001',
      destinationExternalId: 'merchant_456',
      description: 'Compra online'
    })
  });
  const data = await response.json();
  console.log(data.transaction);
  ```

  ```python Python theme={null}
  import requests
  response = requests.post(
      'http://api.gu1.ai/transactions',
      headers={
          'Authorization': 'Bearer YOUR_API_KEY',
          'Content-Type': 'application/json'
      },
      json={
          'externalId': 'txn_12345',
          'type': 'PAYMENT',
          'amount': 150.50,
          'currency': 'USD',
          'originExternalId': 'customer_001',
          'destinationExternalId': 'merchant_456',
          'description': 'Compra online'
      }
  )
  transaction = response.json()['transaction']
  print(transaction)
  ```
</CodeGroup>

### Regras async (ingestão em alto volume)

Para respostas rápidas e revisar alertas depois no gu1. As regras rodam em background; `rulesExecutionSummary.rulesHit` vem vazio na resposta HTTP.

```bash theme={null}
curl -X POST "http://api.gu1.ai/transactions?asyncRules=true" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "externalId": "txn_nightly_001",
    "type": "PAYMENT",
    "amount": 150.50,
    "currency": "BRL",
    "destinationExternalId": "merchant_456"
  }'
```

```json theme={null}
{
  "transaction": { "id": "...", "externalId": "txn_nightly_001", "status": "SUCCESSFUL" },
  "rulesExecutionSummary": {
    "success": true,
    "rulesHit": [],
    "rulesNoHit": [],
    "totalScore": 0,
    "matchedRulesCount": 0,
    "executionTimeMs": 0
  },
  "asyncRules": true,
  "rulesEvaluationStatus": "queued"
}
```

<Warning>
  Não use a resposta síncrona para aprovar ou bloquear pagamentos quando `asyncRules=true`. Não há segundo webhook ao terminar as regras em background — monitore alertas no gu1 ou consulte APIs de transação/investigação.
</Warning>

## Conversão de moeda

Quando `currency` difere da **moeda base** da organização (padrão USD), o Gueno busca a taxa automaticamente. O comportamento **não muda** se você omitir `exchangeRate`.

### Ordem de resolução

| Etapa | Condição                                         | Resultado                                                                 |
| ----- | ------------------------------------------------ | ------------------------------------------------------------------------- |
| 1     | `currency` igual à base                          | `rateSource: no-conversion`, `exchangeRate: 1`                            |
| 2     | Conversão automática com sucesso                 | Taxa do provedor (`ms-provider`, cache, etc.)                             |
| 3     | Conversão falha **e** você enviou `exchangeRate` | `rateSource: client-provided`                                             |
| 4     | Conversão falha, sem `exchangeRate`              | `rateSource: conversion-unavailable`; sem valor normalizado na moeda base |

### Semântica de `exchangeRate`

* **Direção:** unidades da moeda base por **1 unidade** de `currency` (igual às taxas do provedor).
* **Fórmula:** `valorNormalizado = amount × exchangeRate` (persistido na moeda base da org).
* **Não é override:** se a etapa 2 tiver sucesso, `exchangeRate` do cliente é ignorado.

### Moedas não conversíveis (conversão automática)

O Gueno **não** obtém taxa de câmbio automática para estes códigos hoje. A conversão automática fica indisponível salvo se você enviar `exchangeRate`:

| Moeda     | Código | Notas                                                               |
| --------- | ------ | ------------------------------------------------------------------- |
| Worldcoin | `WLD`  | O cliente deve enviar `exchangeRate` para valor normalizado na base |
| Ethereum  | `ETH`  | O cliente deve enviar `exchangeRate` para valor normalizado na base |

Demais códigos ISO seguem o fluxo automático usual (provedor ou histórico com `transactedAt`).

Envie `exchangeRate` se precisar de valor normalizado na base para regras e relatórios.

### Exemplo — WLD com taxa do cliente

```json theme={null}
{
  "externalId": "txn-wld-001",
  "type": "PAYMENT",
  "amount": 26.16,
  "currency": "WLD",
  "exchangeRate": 2.41,
  "destinationExternalId": "merchant_001"
}
```

Resposta (base USD — valor normalizado `63.05`, `rateSource: client-provided`):

```json theme={null}
{
  "transaction": {
    "amount": "26.16",
    "currency": "WLD",
    "exchangeRate": "2.41",
    "rateSource": "client-provided",
    "currenciesExchange": [
      { "currency": "USD", "exchangeRate": 2.41, "value": 63.05 }
    ]
  }
}
```

<Note>
  O batch (`POST /transactions/batch`, upload, JSON) aceita o mesmo `exchangeRate` opcional em **cada linha**, com a mesma semântica.
</Note>

<Note>
  Com **Redis** configurado, os jobs vão para a fila `transaction-rules-eval` (workers dedicados se `DISABLE_INPROCESS_BULL_WORKERS=true`). Se Redis não existir ou o enqueue falhar, a API ainda responde **200** com `asyncRules: true` e executa as regras **no processo dessa instância** (adequado para dev ou instância única; alto volume multi-instância: Redis + workers).
</Note>

## Exemplo de resposta

```json theme={null}
{
  "transaction": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "externalId": "txn_67890",
    "organizationId": "8e2f89ab-c216-4eb4-90eb-ca5d44499aaa",
    "type": "TRANSFER",
    "status": "CREATED",
    "amount": "1000.00",
    "currency": "BRL",
    "amountInUsd": "1000.00",
    "paymentMethod": "PIX",
    "riskScore": "15",
    "flagged": false,
    "channel": "mobile_app",
    "reason": "WITHOUT_REASON",
    "originDetails": {},
    "destinationDetails": {},
    "processingTimeMs": "120",
    "processedAt": "2024-10-03T14:30:00.000Z",
    "createdAt": "2024-10-03T14:30:00.000Z",
    "updatedAt": "2024-10-03T14:30:00.000Z"
  },
  "rulesExecutionSummary": {
    "rulesHit": [],
    "rulesNoHit": [],
    "actionsExecuted": {},
    "totalScore": 15
  }
}
```

## Erros

### 400 - Dados inválidos

```json theme={null}
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Validation failed",
    "details": ["Amount must be zero or a positive number", "Currency must be at least 3 characters"]
  }
}
```

### 409 - Transação duplicada

```json theme={null}
{
  "success": false,
  "error": {
    "code": "DUPLICATE_TRANSACTION",
    "message": "Transaction with this external_id already exists",
    "details": { "field": "external_id", "value": "txn_12345" }
  }
}
```

### 429 - Limite de taxa

```json theme={null}
{
  "error": "Rate limit exceeded",
  "code": "RATE_LIMIT_EXCEEDED",
  "retryAfter": 3600
}
```

## Próximos passos

* [Obter transação](/pt/api-reference/transactions/get) - Por ID ou external ID
* [Criar transações em lote](/pt/api-reference/transactions/create-batch) - Carga em massa
* [Alterar status da transação](/pt/use-cases/transaction-monitoring/change-status-api) - Alterar status
* [Monitoramento de transações](/pt/use-cases/transaction-monitoring/overview) - Detecção de fraude
