Create Transaction
curl --request POST \
--url http://api.gu1.ai/transactions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"externalId": "<string>",
"type": "<string>",
"amount": 123,
"currency": "<string>",
"exchangeRate": 123,
"status": "<string>",
"paymentMethod": "<string>",
"description": "<string>",
"category": "<string>",
"transactedAt": "<string>",
"executeRules": true,
"asyncRules": true,
"configRulesExecution": {},
"linkEntityStrict": true,
"validateExistingEntity": true,
"riskMatrixId": [
"<string>"
],
"riskMatrixIds": [
"<string>"
],
"originEntityId": "<string>",
"originExternalId": "<string>",
"originTaxId": "<string>",
"originName": "<string>",
"originCountry": "<string>",
"originDetails": {},
"destinationEntityId": "<string>",
"destinationExternalId": "<string>",
"destinationTaxId": "<string>",
"destinationName": "<string>",
"destinationCountry": "<string>",
"destinationDetails": {},
"locationDetails": {},
"deviceDetails": {},
"channel": "<string>",
"reason": "<string>",
"timeZone": "<string>",
"metadata": {}
}
'import requests
url = "http://api.gu1.ai/transactions"
payload = {
"externalId": "<string>",
"type": "<string>",
"amount": 123,
"currency": "<string>",
"exchangeRate": 123,
"status": "<string>",
"paymentMethod": "<string>",
"description": "<string>",
"category": "<string>",
"transactedAt": "<string>",
"executeRules": True,
"asyncRules": True,
"configRulesExecution": {},
"linkEntityStrict": True,
"validateExistingEntity": True,
"riskMatrixId": ["<string>"],
"riskMatrixIds": ["<string>"],
"originEntityId": "<string>",
"originExternalId": "<string>",
"originTaxId": "<string>",
"originName": "<string>",
"originCountry": "<string>",
"originDetails": {},
"destinationEntityId": "<string>",
"destinationExternalId": "<string>",
"destinationTaxId": "<string>",
"destinationName": "<string>",
"destinationCountry": "<string>",
"destinationDetails": {},
"locationDetails": {},
"deviceDetails": {},
"channel": "<string>",
"reason": "<string>",
"timeZone": "<string>",
"metadata": {}
}
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({
externalId: '<string>',
type: '<string>',
amount: 123,
currency: '<string>',
exchangeRate: 123,
status: '<string>',
paymentMethod: '<string>',
description: '<string>',
category: '<string>',
transactedAt: '<string>',
executeRules: true,
asyncRules: true,
configRulesExecution: {},
linkEntityStrict: true,
validateExistingEntity: true,
riskMatrixId: ['<string>'],
riskMatrixIds: ['<string>'],
originEntityId: '<string>',
originExternalId: '<string>',
originTaxId: '<string>',
originName: '<string>',
originCountry: '<string>',
originDetails: {},
destinationEntityId: '<string>',
destinationExternalId: '<string>',
destinationTaxId: '<string>',
destinationName: '<string>',
destinationCountry: '<string>',
destinationDetails: {},
locationDetails: {},
deviceDetails: {},
channel: '<string>',
reason: '<string>',
timeZone: '<string>',
metadata: {}
})
};
fetch('http://api.gu1.ai/transactions', 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",
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([
'externalId' => '<string>',
'type' => '<string>',
'amount' => 123,
'currency' => '<string>',
'exchangeRate' => 123,
'status' => '<string>',
'paymentMethod' => '<string>',
'description' => '<string>',
'category' => '<string>',
'transactedAt' => '<string>',
'executeRules' => true,
'asyncRules' => true,
'configRulesExecution' => [
],
'linkEntityStrict' => true,
'validateExistingEntity' => true,
'riskMatrixId' => [
'<string>'
],
'riskMatrixIds' => [
'<string>'
],
'originEntityId' => '<string>',
'originExternalId' => '<string>',
'originTaxId' => '<string>',
'originName' => '<string>',
'originCountry' => '<string>',
'originDetails' => [
],
'destinationEntityId' => '<string>',
'destinationExternalId' => '<string>',
'destinationTaxId' => '<string>',
'destinationName' => '<string>',
'destinationCountry' => '<string>',
'destinationDetails' => [
],
'locationDetails' => [
],
'deviceDetails' => [
],
'channel' => '<string>',
'reason' => '<string>',
'timeZone' => '<string>',
'metadata' => [
]
]),
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"
payload := strings.NewReader("{\n \"externalId\": \"<string>\",\n \"type\": \"<string>\",\n \"amount\": 123,\n \"currency\": \"<string>\",\n \"exchangeRate\": 123,\n \"status\": \"<string>\",\n \"paymentMethod\": \"<string>\",\n \"description\": \"<string>\",\n \"category\": \"<string>\",\n \"transactedAt\": \"<string>\",\n \"executeRules\": true,\n \"asyncRules\": true,\n \"configRulesExecution\": {},\n \"linkEntityStrict\": true,\n \"validateExistingEntity\": true,\n \"riskMatrixId\": [\n \"<string>\"\n ],\n \"riskMatrixIds\": [\n \"<string>\"\n ],\n \"originEntityId\": \"<string>\",\n \"originExternalId\": \"<string>\",\n \"originTaxId\": \"<string>\",\n \"originName\": \"<string>\",\n \"originCountry\": \"<string>\",\n \"originDetails\": {},\n \"destinationEntityId\": \"<string>\",\n \"destinationExternalId\": \"<string>\",\n \"destinationTaxId\": \"<string>\",\n \"destinationName\": \"<string>\",\n \"destinationCountry\": \"<string>\",\n \"destinationDetails\": {},\n \"locationDetails\": {},\n \"deviceDetails\": {},\n \"channel\": \"<string>\",\n \"reason\": \"<string>\",\n \"timeZone\": \"<string>\",\n \"metadata\": {}\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")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"externalId\": \"<string>\",\n \"type\": \"<string>\",\n \"amount\": 123,\n \"currency\": \"<string>\",\n \"exchangeRate\": 123,\n \"status\": \"<string>\",\n \"paymentMethod\": \"<string>\",\n \"description\": \"<string>\",\n \"category\": \"<string>\",\n \"transactedAt\": \"<string>\",\n \"executeRules\": true,\n \"asyncRules\": true,\n \"configRulesExecution\": {},\n \"linkEntityStrict\": true,\n \"validateExistingEntity\": true,\n \"riskMatrixId\": [\n \"<string>\"\n ],\n \"riskMatrixIds\": [\n \"<string>\"\n ],\n \"originEntityId\": \"<string>\",\n \"originExternalId\": \"<string>\",\n \"originTaxId\": \"<string>\",\n \"originName\": \"<string>\",\n \"originCountry\": \"<string>\",\n \"originDetails\": {},\n \"destinationEntityId\": \"<string>\",\n \"destinationExternalId\": \"<string>\",\n \"destinationTaxId\": \"<string>\",\n \"destinationName\": \"<string>\",\n \"destinationCountry\": \"<string>\",\n \"destinationDetails\": {},\n \"locationDetails\": {},\n \"deviceDetails\": {},\n \"channel\": \"<string>\",\n \"reason\": \"<string>\",\n \"timeZone\": \"<string>\",\n \"metadata\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("http://api.gu1.ai/transactions")
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 \"externalId\": \"<string>\",\n \"type\": \"<string>\",\n \"amount\": 123,\n \"currency\": \"<string>\",\n \"exchangeRate\": 123,\n \"status\": \"<string>\",\n \"paymentMethod\": \"<string>\",\n \"description\": \"<string>\",\n \"category\": \"<string>\",\n \"transactedAt\": \"<string>\",\n \"executeRules\": true,\n \"asyncRules\": true,\n \"configRulesExecution\": {},\n \"linkEntityStrict\": true,\n \"validateExistingEntity\": true,\n \"riskMatrixId\": [\n \"<string>\"\n ],\n \"riskMatrixIds\": [\n \"<string>\"\n ],\n \"originEntityId\": \"<string>\",\n \"originExternalId\": \"<string>\",\n \"originTaxId\": \"<string>\",\n \"originName\": \"<string>\",\n \"originCountry\": \"<string>\",\n \"originDetails\": {},\n \"destinationEntityId\": \"<string>\",\n \"destinationExternalId\": \"<string>\",\n \"destinationTaxId\": \"<string>\",\n \"destinationName\": \"<string>\",\n \"destinationCountry\": \"<string>\",\n \"destinationDetails\": {},\n \"locationDetails\": {},\n \"deviceDetails\": {},\n \"channel\": \"<string>\",\n \"reason\": \"<string>\",\n \"timeZone\": \"<string>\",\n \"metadata\": {}\n}"
response = http.request(request)
puts response.read_body{
"transaction": {},
"rulesExecutionSummary": {},
"asyncRules": true,
"rulesEvaluationStatus": "<string>"
}API Reference
Create Transaction
Create a new financial transaction for monitoring and analysis β in the gu1 transaction monitoring API for fraud and AML, with examples for create use cases.
POST
/
transactions
Create Transaction
curl --request POST \
--url http://api.gu1.ai/transactions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"externalId": "<string>",
"type": "<string>",
"amount": 123,
"currency": "<string>",
"exchangeRate": 123,
"status": "<string>",
"paymentMethod": "<string>",
"description": "<string>",
"category": "<string>",
"transactedAt": "<string>",
"executeRules": true,
"asyncRules": true,
"configRulesExecution": {},
"linkEntityStrict": true,
"validateExistingEntity": true,
"riskMatrixId": [
"<string>"
],
"riskMatrixIds": [
"<string>"
],
"originEntityId": "<string>",
"originExternalId": "<string>",
"originTaxId": "<string>",
"originName": "<string>",
"originCountry": "<string>",
"originDetails": {},
"destinationEntityId": "<string>",
"destinationExternalId": "<string>",
"destinationTaxId": "<string>",
"destinationName": "<string>",
"destinationCountry": "<string>",
"destinationDetails": {},
"locationDetails": {},
"deviceDetails": {},
"channel": "<string>",
"reason": "<string>",
"timeZone": "<string>",
"metadata": {}
}
'import requests
url = "http://api.gu1.ai/transactions"
payload = {
"externalId": "<string>",
"type": "<string>",
"amount": 123,
"currency": "<string>",
"exchangeRate": 123,
"status": "<string>",
"paymentMethod": "<string>",
"description": "<string>",
"category": "<string>",
"transactedAt": "<string>",
"executeRules": True,
"asyncRules": True,
"configRulesExecution": {},
"linkEntityStrict": True,
"validateExistingEntity": True,
"riskMatrixId": ["<string>"],
"riskMatrixIds": ["<string>"],
"originEntityId": "<string>",
"originExternalId": "<string>",
"originTaxId": "<string>",
"originName": "<string>",
"originCountry": "<string>",
"originDetails": {},
"destinationEntityId": "<string>",
"destinationExternalId": "<string>",
"destinationTaxId": "<string>",
"destinationName": "<string>",
"destinationCountry": "<string>",
"destinationDetails": {},
"locationDetails": {},
"deviceDetails": {},
"channel": "<string>",
"reason": "<string>",
"timeZone": "<string>",
"metadata": {}
}
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({
externalId: '<string>',
type: '<string>',
amount: 123,
currency: '<string>',
exchangeRate: 123,
status: '<string>',
paymentMethod: '<string>',
description: '<string>',
category: '<string>',
transactedAt: '<string>',
executeRules: true,
asyncRules: true,
configRulesExecution: {},
linkEntityStrict: true,
validateExistingEntity: true,
riskMatrixId: ['<string>'],
riskMatrixIds: ['<string>'],
originEntityId: '<string>',
originExternalId: '<string>',
originTaxId: '<string>',
originName: '<string>',
originCountry: '<string>',
originDetails: {},
destinationEntityId: '<string>',
destinationExternalId: '<string>',
destinationTaxId: '<string>',
destinationName: '<string>',
destinationCountry: '<string>',
destinationDetails: {},
locationDetails: {},
deviceDetails: {},
channel: '<string>',
reason: '<string>',
timeZone: '<string>',
metadata: {}
})
};
fetch('http://api.gu1.ai/transactions', 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",
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([
'externalId' => '<string>',
'type' => '<string>',
'amount' => 123,
'currency' => '<string>',
'exchangeRate' => 123,
'status' => '<string>',
'paymentMethod' => '<string>',
'description' => '<string>',
'category' => '<string>',
'transactedAt' => '<string>',
'executeRules' => true,
'asyncRules' => true,
'configRulesExecution' => [
],
'linkEntityStrict' => true,
'validateExistingEntity' => true,
'riskMatrixId' => [
'<string>'
],
'riskMatrixIds' => [
'<string>'
],
'originEntityId' => '<string>',
'originExternalId' => '<string>',
'originTaxId' => '<string>',
'originName' => '<string>',
'originCountry' => '<string>',
'originDetails' => [
],
'destinationEntityId' => '<string>',
'destinationExternalId' => '<string>',
'destinationTaxId' => '<string>',
'destinationName' => '<string>',
'destinationCountry' => '<string>',
'destinationDetails' => [
],
'locationDetails' => [
],
'deviceDetails' => [
],
'channel' => '<string>',
'reason' => '<string>',
'timeZone' => '<string>',
'metadata' => [
]
]),
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"
payload := strings.NewReader("{\n \"externalId\": \"<string>\",\n \"type\": \"<string>\",\n \"amount\": 123,\n \"currency\": \"<string>\",\n \"exchangeRate\": 123,\n \"status\": \"<string>\",\n \"paymentMethod\": \"<string>\",\n \"description\": \"<string>\",\n \"category\": \"<string>\",\n \"transactedAt\": \"<string>\",\n \"executeRules\": true,\n \"asyncRules\": true,\n \"configRulesExecution\": {},\n \"linkEntityStrict\": true,\n \"validateExistingEntity\": true,\n \"riskMatrixId\": [\n \"<string>\"\n ],\n \"riskMatrixIds\": [\n \"<string>\"\n ],\n \"originEntityId\": \"<string>\",\n \"originExternalId\": \"<string>\",\n \"originTaxId\": \"<string>\",\n \"originName\": \"<string>\",\n \"originCountry\": \"<string>\",\n \"originDetails\": {},\n \"destinationEntityId\": \"<string>\",\n \"destinationExternalId\": \"<string>\",\n \"destinationTaxId\": \"<string>\",\n \"destinationName\": \"<string>\",\n \"destinationCountry\": \"<string>\",\n \"destinationDetails\": {},\n \"locationDetails\": {},\n \"deviceDetails\": {},\n \"channel\": \"<string>\",\n \"reason\": \"<string>\",\n \"timeZone\": \"<string>\",\n \"metadata\": {}\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")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"externalId\": \"<string>\",\n \"type\": \"<string>\",\n \"amount\": 123,\n \"currency\": \"<string>\",\n \"exchangeRate\": 123,\n \"status\": \"<string>\",\n \"paymentMethod\": \"<string>\",\n \"description\": \"<string>\",\n \"category\": \"<string>\",\n \"transactedAt\": \"<string>\",\n \"executeRules\": true,\n \"asyncRules\": true,\n \"configRulesExecution\": {},\n \"linkEntityStrict\": true,\n \"validateExistingEntity\": true,\n \"riskMatrixId\": [\n \"<string>\"\n ],\n \"riskMatrixIds\": [\n \"<string>\"\n ],\n \"originEntityId\": \"<string>\",\n \"originExternalId\": \"<string>\",\n \"originTaxId\": \"<string>\",\n \"originName\": \"<string>\",\n \"originCountry\": \"<string>\",\n \"originDetails\": {},\n \"destinationEntityId\": \"<string>\",\n \"destinationExternalId\": \"<string>\",\n \"destinationTaxId\": \"<string>\",\n \"destinationName\": \"<string>\",\n \"destinationCountry\": \"<string>\",\n \"destinationDetails\": {},\n \"locationDetails\": {},\n \"deviceDetails\": {},\n \"channel\": \"<string>\",\n \"reason\": \"<string>\",\n \"timeZone\": \"<string>\",\n \"metadata\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("http://api.gu1.ai/transactions")
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 \"externalId\": \"<string>\",\n \"type\": \"<string>\",\n \"amount\": 123,\n \"currency\": \"<string>\",\n \"exchangeRate\": 123,\n \"status\": \"<string>\",\n \"paymentMethod\": \"<string>\",\n \"description\": \"<string>\",\n \"category\": \"<string>\",\n \"transactedAt\": \"<string>\",\n \"executeRules\": true,\n \"asyncRules\": true,\n \"configRulesExecution\": {},\n \"linkEntityStrict\": true,\n \"validateExistingEntity\": true,\n \"riskMatrixId\": [\n \"<string>\"\n ],\n \"riskMatrixIds\": [\n \"<string>\"\n ],\n \"originEntityId\": \"<string>\",\n \"originExternalId\": \"<string>\",\n \"originTaxId\": \"<string>\",\n \"originName\": \"<string>\",\n \"originCountry\": \"<string>\",\n \"originDetails\": {},\n \"destinationEntityId\": \"<string>\",\n \"destinationExternalId\": \"<string>\",\n \"destinationTaxId\": \"<string>\",\n \"destinationName\": \"<string>\",\n \"destinationCountry\": \"<string>\",\n \"destinationDetails\": {},\n \"locationDetails\": {},\n \"deviceDetails\": {},\n \"channel\": \"<string>\",\n \"reason\": \"<string>\",\n \"timeZone\": \"<string>\",\n \"metadata\": {}\n}"
response = http.request(request)
puts response.read_body{
"transaction": {},
"rulesExecutionSummary": {},
"asyncRules": true,
"rulesEvaluationStatus": "<string>"
}Overview
Creates a new transaction. WithexecuteRules: true (default), the rules engine runs synchronously and the response includes a populated rulesExecutionSummary at the root when rules finish in the same request.
Omitting asyncRules (default false) preserves this behavior β existing integrations are unchanged.
Endpoint
POST http://api.gu1.ai/transactions
Authentication
Requires a valid API key in the Authorization header:Authorization: Bearer YOUR_API_KEY
Query Parameters
boolean
default:"false"
When
true and executeRules is not false, the transaction is created immediately and rules evaluation is enqueued for background processing. The HTTP response returns before rules finish. Query param takes precedence over the same field in the JSON body.Accepted truthy values: true, 1, "true", "1", "yes".Not supported on batch create endpoints β only POST /transactions (single create).Request Body
Required Fields
string
required
Your unique identifier for this transaction in your system
string
required
Type of transaction. Options:
PAYMENT- Payment transactionTRANSFER- Money transferWITHDRAWAL- Cash withdrawalDEPOSIT- Cash or check depositREFUND- Refund transactionCHARGEBACK- ChargebackREVERSAL- Transaction reversalFEE- Service feeADJUSTMENT- Balance adjustmentOTHER- Other transaction type
number
required
Transaction amount (must be zero or positive)
string
required
Currency code (3β4 characters, for example
USD, EUR, BRL). Automatic conversion applies only to the codes on Currencies with automatic conversion.number
Optional custom exchange rate, used only when automatic conversion to your organizationβs base currency is unavailable (provider error, timeout, or unsupported pair). Omit this field to keep the existing behavior β Gueno calls the currency service as today.Semantics: base-currency units per 1 unit of
currency. Normalized amount in your organizationβs base currency: normalizedAmount = amount Γ exchangeRate.Ignored when automatic conversion succeeds (provider rate wins).Required when automatic conversion is unavailable because the code is not on Currencies with automatic conversion. See Currency conversion.Optional Fields
string
default:"CREATED"
Transaction status. Options:
CREATED- Transaction created (default)PROCESSING- Being processedSUSPENDED- Suspended for reviewSENT- Successfully sentEXPIRED- Transaction expiredDECLINED- Declined/rejectedREFUNDED- RefundedSUCCESSFUL- Completed successfully
string
Payment method used. Options:
CARD- Credit/debit cardACH- ACH transferPIX- Brazilian PIXTED- Brazilian TEDBOLETO- Brazilian BoletoWALLET- Digital walletSWIFT- SWIFT transferIBAN- IBAN transferCBU- Argentine CBUCVU- Argentine CVUDEBIN- Argentine DEBINGENERIC_BANK_ACCOUNT- Generic bank accountMPESA- M-PesaUPI- UPI (India)CHECK- Check paymentECHECK- Electronic checkQR_CODE- QR code paymentONLINE_PAYMENT- Online paymentWITHDRAWAL_ORDER- Withdrawal orderCASH- Cash (physical cash / efectivo)
string
Transaction description or notes
string
Transaction category for classification
string
ISO 8601 datetime when the transaction occurred (defaults to creation time). Stored as UTC. Use
Z or Β±HH:MM in the string, or send a naive datetime together with timeZone (local wall time in that zone).boolean
default:"true"
Whether to run the rules engine for this transaction. Set to
false to skip rules entirely (sync and async).boolean
default:"false"
Same semantics as the query param
asyncRules. Use for high-volume ingestion when you need the transaction persisted quickly and can review alerts later in gu1. Requires executeRules: true (default). Ignored when executeRules is false.object
Optional tuning for how rules run after create (sync or async). Does not disable
When
createAlert actions or investigation consolidation.| Field | Type | Default |
|---|---|---|
notifications | boolean | true for most organizations; false for Paytime prod (3bc1f621-27d4-423e-9d64-86680bec2388) when omitted |
notifications is false, gu1 skips in-app notifications from rules evaluation (risk matrix / status change toasts). Alerts and investigations still behave normally.Legacy KYT POST /legacy/kyt/verifyTransaction accepts the same object on the Gu2 body as configRulesExecution; if omitted, Paytime prod gets notifications: false by default (same as POST /transactions).boolean
default:"false"
With
false (default): Gu1 still auto-links when identifiers match an entity. If nothing matches, the transaction is still created (unlinked). An explicit *EntityId UUID that does not exist is cleared (no 404). Also as query ?linkEntityStrict=true.With true: each side is validated when you send at least one identifier; unresolved refs β 400 INVALID_ENTITY_REFERENCES and no create.boolean
default:"false"
Legacy alias for
linkEntityStrict: true. Prefer linkEntityStrict.Risk Matrices (Optional)
string | string[]
Legacy-compatible: one UUID or an array of UUIDs of risk matrices owned by your organization. When non-empty, only rules assigned to those matrices run for this transaction (no mixing with βlooseβ trigger-only rules). Omit both
riskMatrixId and riskMatrixIds to keep the historical trigger-based behavior.string[]
Preferred for multiple matrices: ordered UUID list. Takes precedence over
riskMatrixId when provided and non-empty.Origin Entity Fields
How the origin is linked in gu1 (tried in order; stop at first success):
If the entity has no
(For graph visualization only, you can also send a tax in
- Direct ID β if you send
originEntityId, the transaction is tied to that entity (must exist in your org). - External ID β if you did not send
originEntityIdbut you sendoriginExternalIdand a person/company exists with the sameexternalId, the row is auto-linked to that entity. - Tax / document ID (third fallback) β if the transaction is still not linked, but you send
rootoriginTaxId, the API looks up a person/company whosetaxIdin gu1 matches after normalization (only letters and digits, ignoring punctuation, spaces, and case for comparison).
originEntityId and, when you did not provide them, enriches originName and originCountry from the matched entity.Canonical denormalization (linked origin): whenever the origin side is linked to a person/company β you sent originEntityId, or auto-link succeeded via originExternalId / originTaxId β gu1 syncs denormalized columns from the entity row before insert:| Transaction field | Source on entity | Client value kept? |
|---|---|---|
originEntityId | entities.id | Set on auto-link; unchanged if you already sent a valid UUID |
originTaxId | entities.tax_id | No β always overwritten from the linked entity |
originExternalId | entities.external_id | No β always overwritten from the linked entity |
taxId or externalId, the corresponding transaction column is stored as null, even when you sent values in the request body.Integrator note: you can send any mix of identifiers to establish the link (precedence: originEntityId β originExternalId β originTaxId). After linking, persisted originTaxId / originExternalId reflect the entity in gu1, not necessarily what you typed. This keeps transaction monitoring rules aligned with user events (entityId, entityExternalId, taxId on the event row).If the tax/external value does not match any entity, the transaction is still created; the fields you sent are stored, but there is no entity link.(For graph visualization only, you can also send a tax in
originDetails β that path does not auto-link; use originTaxId at the root when you want a real link by document.)string
UUID of the origin entity (sender) in gu1. Archived entities (
deletedAt set) cannot be used as origin or destination: the API returns 403 ENTITY_ARCHIVED.string
Your external ID for the origin entity. Used as the second linking key when
originEntityId is omitted. After a successful link, the stored value is entities.external_id (client value is not kept if it differs).string
Tax or national document ID of the origin counterparty (e.g. CPF, CNPJ, CUIT), at the root of the transaction. Used only as the third way to find and link a person/company, after
originEntityId and originExternalId. The value is compared to each entityβs taxId using a normalized form (alphanumeric only). If a match is found, originEntityId is set and name/country can be filled. After a successful link, the stored value is entities.tax_id. Max length: 50 characters. Optional.string
Name of the origin entity
string
ISO 2-letter country code of origin (e.g., βUSβ, βBRβ, βARβ)
object
Detailed information about the origin (sender/device). These fields match the API schema; you can also send additional custom fields and they will be stored.Gu1 adds the reserved
linkedEntityGu1 field when the transaction is created: linked means the origin was linked to an entity, unresolved means at least one root reference (originEntityId, originExternalId, or originTaxId) was provided but did not resolve in soft-link mode, and not_requested means no origin reference was provided. This field is server-owned; any value sent by the integrator is ignored and overwritten.Schema fields (all optional):Device/Technical:deviceId(string) - Unique device identifierdeviceFingerprint(string) - Device fingerprint hashdeviceType(enum) - βmobileβ, βdesktopβ, βtabletβ, βposβ, βatmβuserAgent(string) - Browser user agentipAddress(string) - IP address (validated format)
country(string) - ISO 2-letter country codecity(string),region(string),latitude(number),longitude(number),timezone(string)
accountNumber(string),accountType(enum: βcheckingβ, βsavingsβ, βbusinessβ, βpersonalβ),bankCode(string),bankName(string)
isVpn(boolean),isTor(boolean),isProxy(boolean),governmentAccount(boolean)
originEntityId or originExternalId), you can still improve network graph visualization by sending identifying data in originDetails.paymentDetails. The graph groups pseudo nodes by the first match in this order: taxId, cbu, cvu, pixKey, clabe, alias, iban, holderId, debinId, cardFingerprint, then accountNumber (+ optional bankCode). See Payment Details Schema β Unknown party. Optional and internal only.Destination Entity Fields
Destination linking follows the same precedence as origin:
destinationEntityId β destinationExternalId β destinationTaxId.When the destination is linked, gu1 always syncs destinationTaxId and destinationExternalId from the matched entity (same rules as origin). Unlinked sides keep the values you sent.string
UUID of the destination entity (recipient) in gu1 system
string
Your external ID for the destination entity. After a successful link, stored as
entities.external_id.string
Tax or document ID of the destination counterparty at the root of the request. Third linking fallback: used only if
destinationEntityId and destinationExternalId did not resolve. Same matching rules as originTaxId. When a match is found, destinationEntityId is set and name/country can be enriched. After a successful link, stored as entities.tax_id. Max: 50 characters. Optional.string
Name of the destination entity
string
ISO 2-letter country code of destination (e.g., βUSβ, βBRβ, βARβ)
object
Detailed information about the destination (merchant/receiver). These fields match the API schema; you can also send additional custom fields and they will be stored.Gu1 adds the reserved
linkedEntityGu1 field when the transaction is created: linked means the destination was linked to an entity, unresolved means at least one root reference (destinationEntityId, destinationExternalId, or destinationTaxId) was provided but did not resolve in soft-link mode, and not_requested means no destination reference was provided. This field is server-owned; any value sent by the integrator is ignored and overwritten.Schema fields (all optional):Merchant:mcc(string) - Merchant Category Code (3 or 4 digits)mccDescription(string),merchantId(string),merchantName(string),merchantType(string)
deviceId(string),deviceType(enum: βposβ, βonlineβ, βmobileβ, βatmβ),ipAddress(string)
country(string, ISO 2),city(string),region(string)
accountNumber(string),accountType(enum: βcheckingβ, βsavingsβ, βbusinessβ, βmerchantβ),bankCode(string),bankName(string)
cryptoExchange(boolean),highRisk(boolean),privateSector(boolean)
destinationEntityId or destinationExternalId), you can still improve network graph visualization by sending identifying data in destinationDetails.paymentDetails (same priority order as origin: taxId, cbu, cvu, pixKey, clabe, alias, iban, holderId, debinId, cardFingerprint, then accountNumber + optional bankCode). See Payment Details Schema β Unknown party. Optional and internal only.Location Details
object
Physical location information for the transaction. Useful for fraud detection and geographic analysis.Address Information:
country(string) - ISO 2-letter country codecountryName(string) - Full country namecity(string) - City nameregion(string) - State/Provinceaddress(string) - Full addressstreet(string) - Street namestreetNumber(string) - Street numberpostalCode(string) - Postal/ZIP codeneighborhood(string) - Neighborhood/district
latitude(number) - GPS latitude (-90 to 90)longitude(number) - GPS longitude (-180 to 180)
timezone(string) - Timezone identifierplaceId(string) - Google Places ID or similar
Device Details
object
Detailed device information for fraud detection and device fingerprinting.Device Identification:
deviceId(string) - Unique device identifierexternalId(string) - Your external device ID
platform(enum) - Platform: βandroidβ, βiosβ, βwebβ, βdesktopβ, βmobileβ, βtabletβ, βposβ, βatmβosName(string) - OS name (e.g., βAndroidβ, βiOSβ, βWindowsβ, βmacOSβ)osVersion(string) - OS version
manufacturer(string) - Device manufacturermodel(string) - Device modelbrand(string) - Device branddeviceName(string) - Device name/nickname
browser(string) - Browser namebrowserVersion(string) - Browser versionuserAgent(string) - Full user agent string
isEmulator(boolean) - Device is an emulatorisRooted(boolean) - Android device is rootedisJailbroken(boolean) - iOS device is jailbroken
ipAddress(string) - IP address (validated format)isVpn(boolean) - Connection via VPNisTor(boolean) - Connection via Tor networkisProxy(boolean) - Connection via proxy
deviceFingerprint(string) - Unique device fingerprint hash
screenResolution(string) - Screen resolution (e.g., β1920x1080β)language(string) - Device languagetimezone(string) - Device timezone
Channel
string
Channel through which the transaction originated (max 50 characters).Common values:
mobile_app- Mobile applicationweb_browser- Web browserpos_terminal- Point of sale terminalapi- Direct API integrationatm- ATM machinephone_banking- Phone bankingbranch- Physical branchchatbot- Chatbot interfacethird_party- Third-party integration
Reason
string
Optional reason for the transaction outcome (e.g. decline, failure, limit exceeded). Send any value from the transaction_reason_type enum. If omitted, the system uses
WITHOUT_REASON. Not required β existing integrations remain valid.Full list: See Transaction Reason Enum for all 60+ allowed values.Time Zone
string
Optional IANA time zone for transaction-local context (independent of entity
operationalHours). Send a value from transaction_time_zone (same enum values as operationalHours.timezone). Omit for null.transactedAt normalization: If transactedAt includes Z (as required by this endpointβs datetime validator), that instant is stored in UTC; timeZone is optional metadata and is not used for parsing. If you also send timeZone together with a local datetime (internal/batch tooling), the API can interpret naive wall time in that zone. Existing integrations that omit timeZone behave as before. KYT operational-hours rules use the stored UTC instant plus the entityβs operationalHours.timezone, not transaction.timeZone.Full list: See Transaction Time Zone Enum.Metadata
object
Additional metadata for the transaction. Optional fields:Tags:
tags(object) - Key-value pairs for categorization (values can be string, number, or boolean)
purpose(string) - Purpose of the transactionfrequency(string) - Transaction frequencycontract_number(string) - Associated contract number
enhanced_due_diligence(boolean) - EDD flagblock_reason(string) - Reason for blockingcompliance_alert(boolean) - Compliance alert flag
passthrough behavior.Response
object
The created transaction object. Includes:
id- gu1βs internal transaction IDexternalId- Your external IDorganizationId- Your organization IDtype- Transaction typeamount- Transaction amount (string)currency- Currency codestatus- Transaction statusriskScore- Calculated risk score 0-100 (string)flagged- Whether transaction is flaggedchannel- Channel informationreason- Outcome reason (e.g. WITHOUT_REASON, INSUFFICIENT_FUNDS)timeZone- IANA time zone (string | null)originDetails/destinationDetails- Origin/destination detailslocationDetails- Location datadeviceDetails- Device informationprocessingTimeMs,processedAt,transactedAt,createdAt,updatedAt- Timestamps
object
Present when executeRules is true.Synchronous (default): populated after rules finish in the same request (
rulesHit, rulesNoHit, scores, etc.).Async (asyncRules=true): placeholder with success: true, empty rulesHit / rulesNoHit, and matchedRulesCount: 0. Alerts and risk updates appear after background processing completes.Omitted when executeRules is false.See Rules Execution Summary for the full structure and a complete example.boolean
Present and
true only when rules were queued (asyncRules=true). Omitted in the default synchronous flow.string
When async:
"queued". Omitted when rules ran synchronously.Examples
Basic Transaction
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": "Online purchase"
}'
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: 'Online purchase'
})
});
const data = await response.json();
console.log(data.transaction);
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': 'Online purchase'
}
)
transaction = response.json()['transaction']
print(transaction)
Async Rules (High-Volume Ingestion)
Use when you need fast201 responses and will review alerts in gu1 later. Rules run in the background; rulesExecutionSummary.rulesHit is empty in the HTTP response.
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"
}'
{
"transaction": { "id": "...", "externalId": "txn_nightly_001", "status": "SUCCESSFUL" },
"rulesExecutionSummary": {
"success": true,
"rulesHit": [],
"rulesNoHit": [],
"totalScore": 0,
"matchedRulesCount": 0,
"executionTimeMs": 0
},
"asyncRules": true,
"rulesEvaluationStatus": "queued"
}
Do not use the synchronous response to block or approve payments when
asyncRules=true. There is no second webhook when background rules finish β monitor alerts in gu1 or poll transaction/investigation APIs.Currency Conversion
Whencurrency differs from your organizationβs base currency (default USD) and the code is on Currencies with automatic conversion, Gu1 fetches an exchange rate automatically. Behavior is unchanged if you omit exchangeRate.
Resolution Order
| Step | Condition | Result |
|---|---|---|
| 1 | currency equals base currency | rateSource: no-conversion, exchangeRate: 1 |
| 2 | Automatic conversion succeeds | Provider rate (ms-provider, cache, etc.) |
| 3 | Automatic conversion fails and you sent exchangeRate | rateSource: client-provided |
| 4 | Automatic conversion fails, no exchangeRate | rateSource: conversion-unavailable; no normalized base-currency amount |
exchangeRate Semantics
- Direction: base-currency units per 1 unit of
currency(same as provider rates). - Formula:
normalizedAmount = amount Γ exchangeRate(stored on the transaction in your org base currency). - Not an override: if step 2 succeeds, a client
exchangeRateis ignored.
Currencies with automatic conversion
Automatic conversion runs only for the codes on Currencies with automatic conversion. Any other 3β4 character code (for exampleETH, USDT, USDC, SOL, WLD) is stored on the transaction, and the automatic rate is unavailable unless you send exchangeRate.
BTC is on that list. Other crypto codes are not.
Send exchangeRate when you need a normalized amount in the base currency for rules and reporting.
Example β WLD with Client Rate
{
"externalId": "txn-wld-001",
"type": "PAYMENT",
"amount": 26.16,
"currency": "WLD",
"exchangeRate": 2.41,
"destinationExternalId": "merchant_001"
}
63.05, rateSource: client-provided):
{
"transaction": {
"amount": "26.16",
"currency": "WLD",
"exchangeRate": "2.41",
"rateSource": "client-provided",
"currenciesExchange": [
{ "currency": "USD", "exchangeRate": 2.41, "value": 63.05 }
]
}
}
Batch create (
POST /transactions/batch, upload, JSON) accepts the same optional exchangeRate on each row with identical semantics.When Redis is configured, jobs go to the shared
transaction-rules-eval queue (dedicated workers if DISABLE_INPROCESS_BULL_WORKERS=true). If Redis is missing or enqueue fails, the API still returns 200 with asyncRules: true and runs rules in-process on that server (best for single-instance or dev; high-volume multi-instance deployments should use Redis + workers).Response Example
{
"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": {},
"locationDetails": {},
"deviceDetails": {},
"processingTimeMs": "120",
"processedAt": "2024-10-03T14:30:00.000Z",
"transactedAt": "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
}
}
Error Responses
400 Bad Request - Validation
{
"error": "TRANSACTION_VALIDATION_ERROR",
"message": "The request body does not match the schema required to create a transaction.",
"summary": "amount: Required",
"issues": [
{
"path": "amount",
"code": "invalid_type",
"message": "Required",
"expected": "number",
"received": "undefined"
}
],
"details": "Validation failed: [...]"
}
400 Bad Request - Invalid entity references
WhenlinkEntityStrict / validateExistingEntity is true and a side cannot be resolved:
{
"error": "INVALID_ENTITY_REFERENCES",
"message": "One or more entity references could not be resolved to a person or company in this organization.",
"summary": "origin: β¦",
"issues": []
}
400 Bad Request - Invalid risk matrix
When you sendriskMatrixId or riskMatrixIds and one or more matrices are not usable for the organization:
{
"success": false,
"error": {
"code": "INVALID_RISK_MATRIX",
"message": "One or more risk matrices are not usable for this organization"
}
}
403 Forbidden - Archived entity
{
"success": false,
"error": {
"code": "ENTITY_ARCHIVED",
"message": "β¦",
"details": { "entityIds": ["β¦"] }
}
}
409 Conflict - Duplicate Transaction
{
"error": "DUPLICATE_TRANSACTION_EXTERNAL_ID",
"message": "A transaction with this externalId already exists in the organization",
"externalId": "txn_12345"
}
429 Too Many Requests - Creation quota
{
"success": false,
"error": {
"code": "CREATION_CONTRACT_QUOTA_EXCEEDED",
"message": "Creation quota exceeded for module transactions: β¦",
"module": "transactions",
"requested": 1,
"remainingTotal": 0
}
}
500 Internal Server Error - Create failed
Unexpected failure while creating the transaction (no structuredcode field):
{
"error": "Failed to create transaction",
"details": "β¦"
}
503 Service Unavailable - Async rules queue
WhenexecuteRules is true, asyncRules is true, and the rules queue cannot accept the job. The transaction was already created; the response includes the transaction object:
{
"success": false,
"error": {
"code": "ASYNC_RULES_QUEUE_UNAVAILABLE",
"message": "Could not enqueue rules evaluation"
},
"transaction": { }
}
Error code summary
| HTTP | Code | When |
|---|---|---|
| 400 | TRANSACTION_VALIDATION_ERROR | Body fails schema validation |
| 400 | INVALID_ENTITY_REFERENCES | Strict entity link cannot be resolved |
| 400 | INVALID_RISK_MATRIX | riskMatrixId / riskMatrixIds not usable for the org |
| 403 | ENTITY_ARCHIVED | Origin or destination entity is archived |
| 409 | DUPLICATE_TRANSACTION_EXTERNAL_ID | Same externalId already exists in the org |
| 429 | CREATION_CONTRACT_QUOTA_EXCEEDED | Creation quota exceeded |
| 500 | (no code) | Unexpected create failure (Failed to create transaction) |
| 503 | ASYNC_RULES_QUEUE_UNAVAILABLE | Async rules enqueue failed after insert |
Sandbox error simulation
In sandbox only, you can force these (and other) create failures without writing a row β see Sandbox error simulation.Next Steps
- Get transaction - Fetch by ID or external ID
- Create Batch Transactions - Bulk transaction creation
- Change transaction status - Change status
- Sandbox error simulation - Force create errors in sandbox
- Transaction Monitoring - Learn about fraud detection
Was this page helpful?