Transactions API#
Process credit card, ACH, cash, and tokenized payments with the AuxCORE Transactions API.
Overview#
The Transactions API allows you to:
- Process sales — One-step payment authorization and capture
- Authorize payments — Reserve funds for later capture
- Capture authorized payments — Complete a previously authorized transaction
- Void transactions — Cancel a transaction before settlement
- Refund payments — Return funds to customers (full or partial)
- Issue credits — Record a credit against a sale, or push an unlinked credit to a card
- Record cash payments — Log cash transactions with immediate settled status
- Record external SDK payments — Log IPOS/NearPay device payments with the full platform fee breakdown
API Surfaces#
AuxCORE has three paths for processing transactions. Choose based on your integration type:
| Surface | Base Path | Auth | Use Case |
|---|---|---|---|
| Public API | /api/v1/public/ |
x-api-key (tenant + merchant come from the key; tenant/ERP keys also send X-Merchant-ID) |
ERP, server-to-server, plugins |
| Admin API | /api/v1/transactions/ |
Authorization: Bearer JWT + X-Tenant-ID |
Dashboard integrations |
| AuxCORE SDK API (v2.0) | /api/v1/auxvault/ |
Server-side x-api-key; tenant/ERP keys also need X-Merchant-ID; SDK public keys get 403 |
Official AuxCORE SDK namespace |
For ERP and server integrations, use the Public API. The current auxVault.js also uses /api/v1/public/transaction with pciToken. The current /auxvault/transaction adapter drops PCI tokens and always calls sale, even with TransactionType: "0"; use Public API for auth-only. /api/v1/auxvault itself has no root handler. See AuxCORE SDK contracts.
Transaction Types#
| Type | Description | Use Case |
|---|---|---|
sale |
Auth + Capture in one step | Immediate payment |
auth |
Reserve funds only | Hotels, rentals, pre-orders |
capture |
Capture a previously authorized transaction | After service delivered |
void |
Cancel before settlement (the transaction's status becomes voided) |
Order cancelled |
refund |
Return funds (full or partial) — recorded as a new refund row |
Returns, disputes |
credit |
Credit not tied to a captured sale | Store credit, compensation |
Transaction Statuses#
The status field on a transaction record is one of: pending, approved, declined, settled, voided, refunded, error, reversed (ACH return), processing (ACH debit sent to the bank).
Payment Methods#
| Method | Description | Transaction ID Prefix |
|---|---|---|
Card (default) |
Credit/debit card via gateway | TXN- |
ACH |
Bank account transfer | ACH- |
Cash |
Physical cash — no gateway, settled immediately | CASH- |
Refund rows use the prefix REF- and credit rows CREDIT-. Every transaction also has a UUID id; endpoints that take a transaction ID accept either the UUID or the prefixed transactionId.
Process a Sale — Public API#
Endpoint#
Required Headers#
x-api-key: YOUR_API_KEY
Content-Type: application/jsonTenant and merchant are resolved from a merchant-scoped API key. With a tenant-scoped / ERP key (lv_erp_…), also send X-Merchant-ID: <merchantId> (or merchantId in the body).
PCI: On Sandbox and Production, raw card data (
CardNumber/CVV) is rejected with400 PCI_SCOPE_VIOLATION. Collect the card with the PCI SDK (https://vault.auxcore.net/sdk/) and send the returnedpciTokeninstead. Every card example on this page uses apciToken.
Card Payment (PCI token)#
curl -X POST https://uat.auxcore.net/api/v1/public/transaction \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"Amount": 150.75,
"SuggestedMode": "Card",
"pciToken": "pci_tok_8f2c1a9b7e4d",
"BillingCustomerName": "John Doe",
"BillingEmail": "john.doe@example.com",
"BillingAddress": "123 Main Street",
"BillingCity": "New York",
"BillingState": "NY",
"BillingPostalCode": "10001",
"OrderId": "ORDER-2026-001",
"Description": "Widget purchase"
}'Auth-Only Payment (Reserve Funds)#
Use transactionType: "auth" (legacy numeric value "2" is also accepted) to reserve funds without capturing. Follow up with a capture (Admin API or AuxCORE SDK capture route — see Captures) once the service or goods are delivered.
curl -X POST https://uat.auxcore.net/api/v1/public/transaction \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"Amount": 150.75,
"transactionType": "auth",
"SuggestedMode": "Card",
"pciToken": "pci_tok_8f2c1a9b7e4d",
"BillingCustomerName": "John Doe",
"BillingEmail": "john.doe@example.com",
"BillingPostalCode": "10001",
"OrderId": "ORDER-2026-001"
}'A successful authorization is stored with type: "auth" and status: "approved", so the Public API response carries Status: "1" — the same as an approved sale.
ACH Payment#
curl -X POST https://uat.auxcore.net/api/v1/public/transaction \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"Amount": 500.00,
"SuggestedMode": "ACH",
"account_number": "1234567890",
"routing_number": "021000021",
"account_type": "checking",
"account_holder_name": "John Doe",
"BillingCustomerName": "John Doe",
"BillingEmail": "john.doe@example.com"
}'ACH is asynchronous: an accepted debit comes back with HTTP 200, status: "pending", Status: "2" and Settled: false. Watch the transaction.approved / transaction.declined webhooks (or poll the transaction) for the outcome; a later bank return arrives as transaction.returned.
Cash Payment#
Send "SuggestedMode": "Cash" with an Amount to record a cash sale. No gateway is called; the transaction is stored as settled with no convenience fee (see Cash Payment below for the rules).
Request Fields#
Core Fields#
| Field | Type | Required | Description |
|---|---|---|---|
Amount |
number | Yes | Transaction amount in USD (e.g., 125.00). Must be > 0 |
transactionType |
string | No | "sale" (default) or "auth" (TransactionType and the numeric "2" for auth are also accepted) |
SuggestedMode |
string | No | "Card" (default), "ACH" or "Cash" |
BaseAmount |
number | No | Amount before tip, tax and fee |
TipAmount |
number | No | Tip amount. Default 0 |
TaxAmount |
number | No | Tax amount. Default 0 |
ConvenienceFeeActive |
boolean | No | Who pays the technology fee. Omit for the merchant's default payer; true — the customer pays it; false — the merchant absorbs it. Honoured when the merchant's account allows changing who pays; otherwise it is ignored, the merchant's pricing decides, and the response carries the warning payer_change_not_allowed |
Currency |
string | No | ISO 4217 code. Default "USD" |
OrderId |
string | No | Your order reference number |
InvoiceNumber |
string | No | Invoice reference |
Description |
string | No | Transaction description |
BranchId |
string (uuid) | No | Location (branch) the sale belongs to |
saveCard |
boolean | No | With a pciToken, save the card to the customer vault after approval (needs BillingEmail or BillingPhoneNumber) |
ReturnUrl / DeclineUrl / CancelUrl |
string | No | Where to send the payer after a redirect (3DS / hosted page). When supplied, the response includes ReturnLandingUrl |
metadata |
object | No | Free-form key/value data |
Default behavior: If
transactionTypeis omitted, the transaction runs as asale(authorize + capture in one step).
Card Fields (when SuggestedMode = "Card")#
| Field | Type | Required | Description |
|---|---|---|---|
pciToken |
string | Yes* | PCI vault token (pci_tok_…) from the PCI SDK or a saved card |
CardNumber |
string | No | Not accepted: raw card numbers are rejected on Sandbox and Production with 400 PCI_SCOPE_VIOLATION. Send pciToken |
ExpiryMonth |
string | Dev only | 2-digit month ("01"–"12") |
ExpiryYear |
string | Dev only | 4-digit year (e.g., "2027") |
CVV |
string | Dev only | 3-4 digit security code |
cardLast4 / cardBrand |
string | No | Display metadata returned by the PCI iframe |
*token, paymentToken or cardToken holding a pci_tok_… value are accepted as aliases.
ACH Fields (when SuggestedMode = "ACH")#
| Field | Type | Required | Description |
|---|---|---|---|
account_number |
string | Yes | Bank account number (AccountNumber also accepted) |
routing_number |
string | Yes | Bank routing number (RoutingNumber also accepted) |
account_type |
string | No | "checking" (default) or "savings" |
account_holder_name |
string | No | Name on the account. Falls back to BillingCustomerName |
SecCode |
string | No | ACH SEC code. Inferred (WEB) when absent |
CustomerType |
string | No | Account holder type (e.g. business) |
BusinessName |
string | No | Company name for a business bank account |
Billing Fields#
| Field | Type | Required | Description |
|---|---|---|---|
BillingCustomerName |
string | Recommended | Cardholder name (or FirstName + LastName) |
BillingEmail |
string | Recommended | Customer email (for receipts) |
BillingPhoneNumber |
string | No | Customer phone |
BillingAddress |
string | Conditional* | Street address |
BillingCity |
string | Conditional* | City |
BillingState |
string | Conditional* | 2-letter state code |
BillingPostalCode |
string | Conditional* | ZIP/postal code |
BillingCountry |
string | No | Country |
*Required if AVS filtering is enabled for this merchant
Response#
HTTP 200 for an approved or accepted (pending ACH) transaction, 402 for a decline.
{
"success": true,
"status": "success",
"status_code": 200,
"message": "Approved",
"data": {
"TransactionId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"Status": "1",
"Amount": 155.27,
"BaseAmount": 150.75,
"ConvenienceFee": 4.52,
"TipAmount": 0,
"TaxAmount": 0,
"ConvenienceFeeActive": true,
"CardNumber": "****1111",
"BillingEmail": "john.doe@example.com",
"BillingCustomerName": "John Doe",
"ResponseCode": "100",
"ResponseMessage": "Approved",
"AuthCode": "123456",
"AvsResult": "Y",
"CvvResult": "M",
"GatewayTransactionId": "3456789012",
"ProcessedAt": "2026-02-23T14:00:00.000Z",
"otpSent": false,
"watchdog": {}
}
}TransactionIdis the transaction's UUIDid.statusis"success","pending"(accepted, not settled — ACH) or"declined". Readstatus, not justsuccess.Amountis the fee-inclusive total;ConvenienceFee,TipAmountandTaxAmountare always present (0when not applied).warnings(top level) appears only when the fee was not applied as requested: a convenience fee was requested but none was applied, orConvenienceFeeActivewas ignored because the merchant's account does not allow changing who pays (payer_change_not_allowed).customerId/paymentMethodIdare added whensaveCardsaved the card.VelocityReviewStatus: "in_review"is added when one of the merchant's Transaction Rules held an approved payment for review.Statusstays"1", but the payment is not complete: do not fulfil untiltransaction.approvedarrives.transaction.voidedmeans the merchant denied it (see Webhook Events).
Status Codes#
| Status | Meaning |
|---|---|
"1" |
Approved (sale or auth) |
"2" |
Pending (accepted ACH, or awaiting a customer redirect) |
"3" |
Processing |
"9" |
Declined / error |
Redirect Required (3DS / hosted payment page)#
Some gateways need the payer to complete an action first. The response is HTTP 200 with success: false, status: "pending" and requires_action: true:
{
"success": false,
"status": "pending",
"status_code": 200,
"requires_action": true,
"message": "Cardholder authentication required (3DS)",
"data": {
"TransactionId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"Status": "2",
"RequiresAction": true,
"RedirectUrl": "https://acs.example-bank.com/challenge/abc123",
"RedirectType": "three_ds",
"PaymentMode": "card",
"Url3Ds": "https://acs.example-bank.com/challenge/abc123",
"Amount": 150.75
}
}Send the payer to RedirectUrl. RedirectType is three_ds, hosted_checkout or hosted_payment_page. Url3Ds is deprecated (same value). ReturnLandingUrl is included when you sent ReturnUrl / DeclineUrl / CancelUrl.
Void a Transaction — Public API#
Cancel an approved transaction before it settles.
Endpoint#
curl -X POST https://uat.auxcore.net/api/v1/public/void \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"transactionId": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
}'| Field | Required | Description |
|---|---|---|
transactionId |
Yes | Transaction UUID or TXN-… ID (TransactionId / transaction_id also accepted) |
The response is the voided transaction: { "success": true, "data": { ...transaction, "status": "voided" }, "gatewayVoided": true }. A failed void returns 400 with error.code: "VALIDATION_ERROR" and the reason in error.message.
Note: Only
approvedtransactions (andpendingACH debits) can be voided. Once a transaction issettled, use/refundinstead. Cash transactions cannot be voided.
Refund a Transaction — Public API#
Issue a full or partial refund for an approved or settled transaction.
Endpoint#
# Full refund
curl -X POST https://uat.auxcore.net/api/v1/public/refund \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"transactionId": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
}'
# Partial refund
curl -X POST https://uat.auxcore.net/api/v1/public/refund \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"transactionId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"amount": 50.00
}'| Field | Required | Description |
|---|---|---|
transactionId |
Yes | Transaction UUID or TXN-… ID |
amount |
No | Partial refund amount (> 0). Omit for full refund. |
Returns HTTP 201 with the new refund transaction (REF-…) in data. Check data.status: refunded means the gateway accepted it, declined means it was refused (a gateway decline is added to the Refund Decline Queue) — success is true in both cases. Only a lowercase amount makes it partial; a PascalCase Amount is ignored and the full amount is refunded.
Get Transaction — Public API#
Retrieve the full details of a specific transaction.
Endpoint#
curl https://uat.auxcore.net/api/v1/public/transaction/7c9e6679-7425-40de-944b-e07fc1f90ae7 \
-H "x-api-key: YOUR_API_KEY":id is the UUID or the TXN-… / ACH-… / CASH-… ID. The response is { "success": true, "data": { ...transaction } } with the stored transaction fields (camelCase: transactionId, status, type, amount, baseAmount, convenienceFee, cardLast4, …) plus refundedAmount and, when available, merchantName. Returns 404 NOT_FOUND for a transaction outside the key's merchant.
List Transactions — Public API#
Search and filter transactions for the API key's merchant.
Endpoint#
GET /api/v1/public/merchant-transactions is an alias with identical behaviour.
# All recent transactions
curl "https://uat.auxcore.net/api/v1/public/transaction-list" \
-H "x-api-key: YOUR_API_KEY"
# Filter by date range
curl "https://uat.auxcore.net/api/v1/public/transaction-list?dateFrom=2026-02-01&dateTo=2026-02-28" \
-H "x-api-key: YOUR_API_KEY"
# Filter by status
curl "https://uat.auxcore.net/api/v1/public/transaction-list?status=approved" \
-H "x-api-key: YOUR_API_KEY"Query Parameters#
| Parameter | Type | Description |
|---|---|---|
page |
integer | Page number (default: 1) |
limit |
integer | Items per page (default: 50) |
dateFrom |
date | Filter start date (ISO 8601). A plain YYYY-MM-DD dateTo covers the whole day |
dateTo |
date | Filter end date (ISO 8601) |
dateField |
string | settledAt to filter on settlement date instead of creation date |
status |
string | pending, approved, declined, settled, voided, refunded, error, reversed, processing (comma-separated for several) |
excludeStatus |
string | Statuses to leave out (comma-separated) |
type |
string | sale, auth, capture, refund, credit (void matches voided transactions) |
paymentMethod |
string | card, ach, cash, crypto, gift |
q |
string | Free-text search across name, transaction ID, order ID, amount, email, card last 4, auth code |
transactionId / orderId / email / cardLast4 / name / amount |
string | Field filters (ignored when q is sent) |
customerId |
string (uuid) | Transactions for one customer |
sort |
string | asc or desc (default) |
sortColumn |
string | createdAt (default), amount, status, type, transactionId, orderId |
Response#
{
"success": true,
"data": [ { "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "transactionId": "TXN-1771855200000-A1B2C3D4", "status": "approved", "type": "sale", "amount": "150.75" } ],
"meta": {
"page": 1,
"limit": 50,
"total": 1,
"totalPages": 1,
"summary": { "count": 1, "amountTotal": 150.75, "approvedCount": 1, "refundTotal": 0 },
"statusCounts": { "approved": 1 }
}
}Token-Based Transaction — Public API#
Charge a saved card by its PCI vault token. The body is passed to the transaction service as-is (camelCase fields), and the merchant comes from the API key.
Endpoint#
curl -X POST https://uat.auxcore.net/api/v1/public/token-transaction \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"pciToken": "pci_tok_8f2c1a9b7e4d",
"amount": 125.00,
"description": "Monthly renewal",
"billingEmail": "john.doe@example.com"
}'| Field | Required | Description |
|---|---|---|
pciToken |
Yes | Saved PCI vault token (pci_tok_…); cardToken / paymentToken holding a pci_tok_… value also work |
amount |
Yes | Amount (> 0) |
transactionType |
No | sale (default) |
description, orderId, billingEmail, billingCustomerName |
No | Same meaning as on the Admin API sale |
Returns HTTP 201 with { "success": true, "data": { ...transaction } } — the raw transaction record, not the PascalCase shape of /transaction. Check data.status (approved / declined).
Charge a Tokenized Bank Account — Public API#
The ACH counterpart of /token-transaction: charge a pci_ach_… token from /tokenize-ach. Requires a server-side API key — SDK public keys (lpk_live_…) get 403 FORBIDDEN.
Endpoint#
curl -X POST https://uat.auxcore.net/api/v1/public/token-transaction-ach \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"token": "pci_ach_4b7d2e91c0aa",
"amount": 250.00,
"description": "Invoice 1042",
"billingEmail": "john.doe@example.com"
}'| Field | Required | Description |
|---|---|---|
token |
Yes | pci_ach_… token (pciAchToken / tokenId also accepted) |
amount |
Yes | Amount (> 0) |
accountType, accountHolderName |
No | Override what the vault stored |
secCode, customerType, businessName |
No | ACH entry details |
customerId, description, orderId, billingEmail, billingPhoneNumber, billingFirstName, billingLastName |
No | Reference and billing data |
convenienceFeeActive |
No | Who pays the technology fee. Omit for the merchant's default payer; true — the customer pays it; false — the merchant absorbs it. Honoured when the merchant's account allows changing who pays; otherwise it is ignored, the merchant's pricing decides, and the response carries the warning payer_change_not_allowed |
Returns HTTP 201 with the ACH transaction (status: "pending" while the debit settles). A tenant-scoped key without a resolvable merchant gets 400 VALIDATION_ERROR.
Rerun a Declined Transaction — Public API#
Note:
POST /api/v1/public/rerunis not available. The route exists in the gateway but the transaction service has no rerun operation, so it returns404. To retry a declined payment, submit a newPOST /api/v1/public/transaction.
Admin API Routes (Dashboard / JWT Auth)#
These routes are used by the AuxCORE dashboard and require a JWT Bearer token. They accept camelCase request bodies and respond with { success, data }, where data is the transaction record.
Process Sale#
curl -X POST https://uat.auxcore.net/api/v1/transactions/sale \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "X-Tenant-ID: YOUR_TENANT_ID" \
-H "Content-Type: application/json" \
-d '{
"merchantId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"amount": 150.75,
"currency": "USD",
"paymentMethod": "card",
"pciToken": "pci_tok_8f2c1a9b7e4d",
"billingCustomerName": "John Doe",
"billingEmail": "john@example.com"
}'Returns HTTP 201. merchantId and amount (> 0) are required. Use POST /api/v1/transactions/auth with the same body for an authorization only. An optional Idempotency-Key header de-duplicates retries for 24 hours.
Itemised sale (lineItems)#
sale, auth, token-sale, ach-sale and external-payment accept an optional lineItems
array — the cart sold with the payment (catalog products and free-text misc lines):
"lineItems": [
{ "productId": "3f2b8c1e-4d5a-4e6f-8a7b-9c0d1e2f3a4b", "name": "Diesel", "quantity": 2.5, "unit": "gallon", "unitPrice": 4.19 },
{ "type": "misc", "name": "Car wash", "quantity": 1, "unitPrice": 8.00 }
]Each line: type (product | misc), productId (required for product, forbidden for misc),name, quantity (> 0, up to 3 decimals), optional unit, unitPrice (2 decimals), optionallineTotal (= quantity × unitPrice). The lines must add up to baseAmount (amount before tip, tax
and convenience fee) within $0.01, otherwise 400 INVALID_LINE_ITEMS before anything is charged.
A cart holding more of a product than its maxQuantity (summed across lines) is refused with400 QUANTITY_LIMIT_EXCEEDED — also before anything is charged, and not on external-payment; see
Products, section "Per-order quantity limit".
The normalised cart is stored on the transaction and returned by GET /transactions/:id (not by the
list). Product lines count toward the product's soldQuantity once the sale is approved, and come
back out on a void, a full refund or an ACH return. Full contract:
Device Integration, section "Itemised sales (POS cart)".
Optional immutable purchase snapshot#
Mobile card sales authenticated with X-Device-Token may include enhancedData without
sending requestOrigin. The server derives ipos or nearpay from the trusted device
context; portal Take Payment calls continue to use their existing take_payment context.
The field is optional and never reaches a processor.
{
"enhancedData": {
"source": "manual",
"lines": [{
"stableLineId": "mobile-line-1",
"description": "Widget",
"quantity": "1",
"unitPrice": "100.00",
"tax": "8.00"
}]
}
}Use { "source": "invoice", "invoiceId": "…" } for an invoice candidate. The invoice
is reloaded under the device's tenant and merchant scope. It is stored only when its full
server-authoritative total equals the charge excluding tip and customer/convenience fees;
otherwise the sale remains a normal Standard payment with no snapshot.
For manual snapshot lines, quantity may have up to three decimal places and unitPrice may
have up to two. The exact quantity × unit-price calculation must resolve to whole currency
minor units; the API rejects a non-representable line total rather than rounding it.
Capture an Authorization#
curl -X POST https://uat.auxcore.net/api/v1/transactions/7c9e6679-7425-40de-944b-e07fc1f90ae7/capture \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "X-Tenant-ID: YOUR_TENANT_ID"Captures the full authorized amount — the endpoint takes no body (partial capture is not supported). Requires the transactions.capture permission.
Cancel Capture#
curl -X POST https://uat.auxcore.net/api/v1/transactions/7c9e6679-7425-40de-944b-e07fc1f90ae7/cancel-capture \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "X-Tenant-ID: YOUR_TENANT_ID"Cash Payment (Record a Cash Sale)#
Record a cash transaction. No gateway is called — the transaction is immediately created with status: "settled" and convenienceFee: 0.
Note: Cash is not gated by merchant or device configuration — any merchant can record a cash sale.
curl -X POST https://uat.auxcore.net/api/v1/transactions/sale \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "X-Tenant-ID: YOUR_TENANT_ID" \
-H "Content-Type: application/json" \
-d '{
"merchantId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"amount": 55.00,
"tipAmount": 5.00,
"paymentMethod": "Cash",
"currency": "USD",
"billingCustomerName": "Jane Smith",
"billingEmail": "jane.smith@example.com",
"requestOrigin": "virtual-terminal"
}'Request Fields#
| Field | Type | Required | Description |
|---|---|---|---|
merchantId |
string (uuid) | Yes | Merchant ID |
amount |
number | Yes | Total amount including tip and tax. Must be > 0 |
paymentMethod |
string | Yes | "Cash" (case-insensitive; "Check" is treated the same way) |
tipAmount |
number | No | Tip amount. Default: 0 |
taxAmount |
number | No | Tax amount. Default: 0 |
baseAmount |
number | No | Amount before tip and tax. Default: amount - tipAmount - taxAmount |
currency |
string | No | ISO 4217 currency code. Default: "USD" |
deviceId |
string (uuid) | No | Device ID when transaction originates from a device |
branchId |
string (uuid) | No | Location the sale belongs to |
orderId |
string | No | Internal order reference |
requestOrigin |
string | No | Source of the transaction. Default "virtual-terminal" |
description |
string | No | Transaction description |
signature |
string | No | Customer signature, printed on the receipt |
billingCustomerName |
string | No | Customer name (or billingFirstName + billingLastName) |
billingEmail |
string | No | Customer email — used to send receipt if provided |
billingAddress |
string | No | Street address |
billingCity |
string | No | City |
billingState |
string | No | State |
billingPostalCode |
string | No | ZIP/postal code |
billingCountry |
string | No | Country |
billingPhoneNumber |
string | No | Phone number |
Do not send card or ACH fields (
cardNumber,cardExpiry,accountNumber, etc.) — they are ignored for Cash payments.
Response — 201 Created#
{
"success": true,
"data": {
"id": "0b6f3c3e-9a51-4d1e-8f43-2f7b1c9d6e10",
"transactionId": "CASH-1750300000000-A1B2C3D4",
"merchantId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"amount": "55.00",
"baseAmount": "50.00",
"tipAmount": "5.00",
"taxAmount": "0.00",
"convenienceFee": "0.00",
"currency": "USD",
"type": "sale",
"status": "settled",
"paymentMethod": "Cash",
"provider": "Cash",
"gatewayName": "Cash",
"billingCustomerName": "Jane Smith",
"billingEmail": "jane.smith@example.com",
"requestOrigin": "virtual-terminal",
"createdAt": "2026-06-19T10:00:00.000Z",
"updatedAt": "2026-06-19T10:00:00.000Z"
}
}Cash Payment Rules#
| Rule | Behavior |
|---|---|
status |
Always "settled" — no gateway processing |
convenienceFee |
Always 0 — fees do not apply to cash |
type |
Only sale is supported. A Cash auth (/transactions/auth) returns 400 VALIDATION_ERROR |
| Void | Not supported for Cash (400). Use Refund instead |
| Refund | Full refund only — a partial amount returns 400 |
| Settlement batch | Cash transactions are excluded from settlement batches |
| Ledger | Cash transactions are posted to the ledger |
| Receipt email | Sent automatically if billingEmail is provided |
Record a Credit Against a Transaction#
curl -X POST https://uat.auxcore.net/api/v1/transactions/7c9e6679-7425-40de-944b-e07fc1f90ae7/credit \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "X-Tenant-ID: YOUR_TENANT_ID" \
-H "Content-Type: application/json" \
-d '{
"amount": 50.00
}'Creates a credit transaction (CREDIT-…, status: "approved") for the original transaction's merchant, gateway and location. No gateway call is made — this records the credit only. amount must be a positive number. Returns HTTP 201. A reason field is accepted but not stored.
Issue an Unlinked Credit#
Pushes funds to a card through the gateway without referencing a prior sale (the Virtual Terminal "Credit" action). Takes the same body as Process Sale (merchantId, amount, card / pciToken, billing fields) and returns HTTP 201 with the credit transaction.
Record an External SDK Payment (IPOS / NearPay)#
Record a payment the device already completed through an external provider SDK (IPOS or NearPay). The provider SDK only carries total + tip, so the platform-computed fee breakdown (convenienceFee, taxAmount, and the derived baseAmount) never reaches the provider webhook. The device calls this endpoint right after the SDK returns success to push the full breakdown, keyed by the provider's gatewayTransactionId.
The endpoint is idempotent and async-safe with the provider webhook — either side may arrive first, both matched on gatewayTransactionId:
- Webhook not seen yet → a
pendingtransaction is created; the webhook later finalizes the status (approved/declined). - Webhook already created the record → only the platform fee breakdown is filled in; the webhook-owned
status, card, and auth data are left untouched. A later webhook re-delivery will not overwrite the device-supplied fees.
enhancedData is optional immutable purchase context (the same manual-lines or invoice-ID
candidate accepted by mobile card sales). It is resolved after the fee components are
normalized and stored with the local transaction only; it is never submitted to IPOS,
NearPay, or another processor. A webhook-first row receives the snapshot only if it has none.
Repeating the same candidate is idempotent; a different valid candidate returns409 ENHANCED_DATA_SNAPSHOT_CONFLICT and never overwrites the first snapshot.
Auth: JWT Bearer plus a device token. This is a device-only endpoint — X-Device-Token is required; tenantId, merchantId, deviceId, and terminalId are resolved from the device context, never from the body.
Authorization: Bearer YOUR_JWT_TOKEN
X-Device-Token: DEVICE_TOKEN
X-Tenant-ID: YOUR_TENANT_ID
Content-Type: application/jsoncurl -X POST https://uat.auxcore.net/api/v1/transactions/external-payment \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "X-Device-Token: DEVICE_TOKEN" \
-H "X-Tenant-ID: YOUR_TENANT_ID" \
-H "Content-Type: application/json" \
-d '{
"gatewayTransactionId": "85635456265410555120260724032413",
"paymentMode": "IPOS",
"type": "sale",
"amount": 108.00,
"baseAmount": 100.00,
"tipAmount": 5.00,
"convenienceFee": 3.00,
"taxAmount": 0.00,
"currency": "USD",
"cardLast4": "4242",
"cardBrand": "Visa"
}'Request Fields#
| Field | Type | Required | Description |
|---|---|---|---|
gatewayTransactionId |
string | Yes | Transaction ID returned by the IPOS/NearPay SDK — the key the webhook is matched on |
paymentMode |
string | Yes | "IPOS" or "NEARPAY" |
type |
string | No | "sale" (default) or "auth" |
amount |
number | Yes | Total charged (baseAmount + tipAmount + taxAmount + convenienceFee). Must be > 0 |
baseAmount |
number | No | Amount before tip/tax/fee. Default: amount - tipAmount - taxAmount - convenienceFee |
tipAmount |
number | No | Tip amount. Default: 0 |
convenienceFee |
number | No | Platform-computed convenience fee. Default: 0 |
taxAmount |
number | No | Platform-computed tax. Default: 0 |
currency |
string | No | ISO 4217 currency code. Default: "USD" |
cardLast4 |
string | No | Last 4 digits of the card (display only), from the SDK response |
cardBrand |
string | No | Card brand (e.g. "Visa"), from the SDK response |
invoiceNumber |
string | No | Linked invoice number |
enhancedData |
object | No | Immutable purchase candidate: { source: "manual", lines: [...] } or { source: "invoice", invoiceId } |
orderId |
string | No | Internal order reference |
metadata |
object | No | Provider-specific extra data |
Do not send
tenantId,merchantId,deviceId, orstatus— the server sets them (statusis alwayspendingon create). The storedtransactionIdisIPOS-<gatewayTransactionId>for IPOS andNPAY-<gatewayTransactionId>for NearPay.
Response — 201 Created (no webhook yet)#
{
"success": true,
"data": {
"id": "5d1f0c7a-2b8e-4c3a-9e61-7a4f2d8b9c01",
"transactionId": "IPOS-85635456265410555120260724032413",
"status": "pending",
"amount": "108.00",
"baseAmount": "100.00",
"tipAmount": "5.00",
"convenienceFee": "3.00",
"taxAmount": "0.00"
}
}Response — 200 OK (webhook already created it, fees filled in)#
{
"success": true,
"data": {
"id": "5d1f0c7a-2b8e-4c3a-9e61-7a4f2d8b9c01",
"transactionId": "IPOS-85635456265410555120260724032413",
"status": "approved",
"baseAmount": "100.00",
"convenienceFee": "3.00",
"taxAmount": "0.00"
}
}Error Responses#
| HTTP | Code | Cause |
|---|---|---|
400 |
VALIDATION_ERROR |
Missing gatewayTransactionId; paymentMode not in IPOS/NEARPAY; amount ≤ 0; type not in sale/auth |
400 |
DEVICE_CONTEXT_REQUIRED |
Called without a valid X-Device-Token |
401 / 403 |
INVALID_DEVICE_TOKEN / DEVICE_SUSPENDED |
Device token invalid, revoked, or device suspended |
409 |
ENHANCED_DATA_SNAPSHOT_CONFLICT |
Retry supplied different purchase details after a snapshot was stored |
500 |
INTERNAL_ERROR |
Unexpected backend error |
AVS Response Codes#
| Code | Meaning |
|---|---|
Y |
Address and 5-digit ZIP match |
A |
Address matches, ZIP does not |
Z |
ZIP matches, address does not |
N |
Neither address nor ZIP match |
U |
Address information unavailable |
R |
Retry — system unavailable |
S |
Service not supported |
CVV Response Codes#
| Code | Meaning |
|---|---|
M |
CVV matches |
N |
CVV does not match |
P |
CVV not processed |
S |
CVV should be on card but not provided |
U |
Issuer unable to process CVV |
Error Handling#
Declined Transaction#
Public API returns HTTP 402 for card-level declines. Response codes are normalized to the NMI convention (100 = approved, 2xx = issuer decline, 3xx = gateway reject, 4xx = processor error):
{
"success": false,
"status": "declined",
"status_code": 402,
"message": "Insufficient funds",
"data": {
"TransactionId": "9a3e7c21-6f4b-4d8e-a2c5-1b0f9e8d7c6a",
"Status": "9",
"ResponseCode": "202",
"ResponseMessage": "Insufficient funds"
}
}PCI Scope Violation#
{
"success": false,
"error": {
"code": "PCI_SCOPE_VIOLATION",
"message": "PublicAPI.transaction: raw card data is not permitted in this environment. Collect card data via the PCI iframe/SDK and submit a pciToken only."
}
}Validation Error#
Gateway-level checks on /void and /refund return a string error:
{
"success": false,
"error": "Transaction ID required",
"message": "Please provide a transactionId in the request body"
}Errors raised by the transaction service (amount, status rules, not found) use the structured shape:
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Only approved transactions can be voided"
}
}Next Steps#
- Process Refunds →
- Set up Recurring Billing →
- Customer Vault →
- Configure Fraud Filters →
- View Error Codes →
Questions? Contact support@auxcore.net