Create Transaction
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
Create Transaction
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
Authentication
Requires a valid API key in the Authorization header:Query Parameters
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
Your unique identifier for this transaction in your system
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
Transaction amount (must be zero or positive)
Currency code (3-4 characters, e.g., βUSDβ, βEURβ, βBRLβ)
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 for non-convertible currencies (see below). See Currency conversion.Optional Fields
Transaction status. Options:
CREATED- Transaction created (default)PROCESSING- Being processedSUSPENDED- Suspended for reviewSENT- Successfully sentEXPIRED- Transaction expiredDECLINED- Declined/rejectedREFUNDED- RefundedSUCCESSFUL- Completed successfully
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 order
Transaction description or notes
Transaction category for classification
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).Whether to run the rules engine for this transaction. Set to
false to skip rules entirely (sync and async).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.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).With
false (default): if you send originExternalId / destinationExternalId (or root-level tax ids) and no entity matches, the transaction is still created (unlinked), same as before.With true: each side (origin / destination) is validated only when you send at least one identifier for that side (originEntityId, originExternalId, or originTaxId; same for destination). Every identifier you send must resolve to an existing person/company in your organization; otherwise the API returns 400 with INVALID_ENTITY_REFERENCES and does not create the transaction. If you send no origin (or destination) identifiers, that side is not validated.Risk Matrices (Optional)
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.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.)UUID of the origin entity (sender) in gu1 system
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).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.Name of the origin entity
ISO 2-letter country code of origin (e.g., βUSβ, βBRβ, βARβ)
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.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.UUID of the destination entity (recipient) in gu1 system
Your external ID for the destination entity. After a successful link, stored as
entities.external_id.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.Name of the destination entity
ISO 2-letter country code of destination (e.g., βUSβ, βBRβ, βARβ)
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.Schema fields (all optional):Merchant:
mcc(string) - Merchant Category Code (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
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
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
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
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
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
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
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
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.Present and
true only when rules were queued (asyncRules=true). Omitted in the default synchronous flow.When async:
"queued". Omitted when rules ran synchronously.Examples
Basic 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.
Currency Conversion
Whencurrency differs from your organizationβs base currency (default USD), Gueno 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.
Non-Convertible Currencies (Automatic Conversion)
Gueno does not obtain exchange rates automatically for these codes today. Automatic conversion returns unavailable unless you sendexchangeRate:
| Currency | Code | Notes |
|---|---|---|
| Worldcoin | WLD | Client must supply exchangeRate for normalized base amount |
| Ethereum | ETH | Client must supply exchangeRate for normalized base amount |
transactedAt is set).
Send exchangeRate when you need a normalized amount in base currency for rules and reporting.
Example β WLD with Client Rate
63.05, rateSource: client-provided):
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
Error Responses
400 Bad Request - Invalid Data
400 Bad Request - Invalid IP Address
409 Conflict - Duplicate Transaction
429 Too Many Requests
Next Steps
- Get transaction - Fetch by ID or external ID
- Create Batch Transactions - Bulk transaction creation
- Change transaction status - Change status
- Transaction Monitoring - Learn about fraud detection