Data Models#
Complete data model reference for all API objects.
Transaction#
The transaction record returned by GET /api/v1/transactions/:id, GET /api/v1/public/transaction/:id and the transaction lists. Ids are UUIDs; transactionId is the human-readable reference. The Public API POST /api/v1/public/transaction answers with a PascalCase summary instead (see Transactions).
{
"id": "550e8400-e29b-41d4-a716-446655440020",
"transactionId": "TXN-1776037573138-56123064",
"merchantId": "550e8400-e29b-41d4-a716-446655440000",
"type": "sale",
"status": "approved",
"amount": "153.75",
"baseAmount": "150.00",
"tipAmount": "0.00",
"taxAmount": "0.00",
"convenienceFee": "3.75",
"currency": "USD",
"paymentMethod": "Card",
"cardBrand": "visa",
"cardLast4": "1111",
"authCode": "123456",
"responseCode": "100",
"responseText": "Approved",
"avsResponse": "Y",
"cvvResponse": "M",
"gatewayName": "NMI",
"gatewayTransactionId": "8812734455",
"originalTransactionId": null,
"billingCustomerName": "John Doe",
"billingEmail": "john@example.com",
"billingAddress": "123 Main St",
"billingCity": "New York",
"billingState": "NY",
"billingPostalCode": "10001",
"billingCountry": "US",
"orderId": "1042",
"invoiceNumber": null,
"requestOrigin": "api",
"branchId": null,
"batchId": null,
"createdAt": "2026-01-28T12:00:00.000Z",
"updatedAt": "2026-01-28T12:00:00.000Z"
}| Field | Type | Description |
|---|---|---|
id |
string (UUID) | Use in /transactions/:id paths |
type |
string | sale, auth, void, refund, capture, cancel_capture, credit |
status |
string | pending, approved, declined, settled, voided, refunded, error, reversed (ACH return), processing (ACH in flight) |
amount |
string (decimal) | Total charged: baseAmount + tipAmount + taxAmount + convenienceFee. All money fields on a read are decimal strings such as "153.75" — parse them before doing arithmetic |
paymentMethod |
string | Card, ACH, Cash, GiftCard |
responseCode |
string | NMI-style code; 100 = approved (see Error Codes) |
originalTransactionId |
string | null | For void, refund and capture rows, the sale / auth they act on |
requestOrigin |
string | Where it came from: vt, api, ipos, amp, woocommerce and others |
The record also holds shipping fields, 3DS results, chargeback fields (chargeback, resolution) and fee-breakdown fields; card numbers and CVV are never stored or returned.
Subscription#
A recurring subscription (/api/v1/recurring). The response is the stored record.
{
"id": "550e8400-e29b-41d4-a716-446655440040",
"merchantId": "550e8400-e29b-41d4-a716-446655440000",
"customerId": "550e8400-e29b-41d4-a716-446655440010",
"description": "Gold membership",
"status": "active",
"recurringAmount": "99.00",
"period": "Monthly",
"recurringDate1": "2026-01-01",
"recurringDate2": null,
"maximumOccurrence": "NoExpire",
"suggestedMode": "Card",
"nextPaymentDate": "2026-02-01",
"lastPaymentDate": "2026-01-01",
"successCount": 1,
"failedPaymentCount": 0,
"maxRetryAttempts": 3,
"totalCollectedAmount": "99.00",
"createdAt": "2026-01-01T00:00:00.000Z"
}| Field | Type | Description |
|---|---|---|
status |
string | active, scheduled, processing, paused, cancelled, expired, pending (awaiting authorization), completed |
period |
string | Weekly, BiWeekly, SemiMonthly, Monthly, Quarterly, Annually, Custom |
maximumOccurrence |
string | 1-999 or NoExpire |
suggestedMode |
string | Card or ACH |
Installment plans (/api/v1/billing/payment-plans) use a different model: planName, totalAmount, paymentFrequency, and the statuses draft, pending_approval, active, paused, completed, cancelled, defaulted. See Payment Plans.
Invoice#
{
"id": "550e8400-e29b-41d4-a716-446655440050",
"invoiceNumber": "INV-2026-000042",
"linkId": "k3v9x2m7q1",
"shortLink": "https://short.example.com/k3v9x2",
"merchantId": "550e8400-e29b-41d4-a716-446655440000",
"customerId": "550e8400-e29b-41d4-a716-446655440010",
"customerName": "John Doe",
"customerEmail": "john@example.com",
"customerPhone": "+12125550123",
"status": "sent",
"lineItems": [
{
"id": "li_1",
"name": "Web Design Services",
"quantity": 1,
"unitPrice": 500.00,
"amount": 500.00
}
],
"subtotal": "500.00",
"taxAmount": "0.00",
"discountAmount": "0.00",
"convenienceFee": "0.00",
"totalAmount": "500.00",
"amountPaid": "0.00",
"amountDue": "500.00",
"currency": "USD",
"allowPartialPayment": false,
"issueDate": "2026-01-28",
"dueDate": "2026-02-15",
"paidAt": null,
"createdAt": "2026-01-28T12:00:00.000Z"
}| Field | Type | Description |
|---|---|---|
status |
string | draft, sent, viewed, partial, paid, overdue, cancelled, pending, expired (legacy; invoices no longer expire) |
subtotal, taxAmount, discountAmount, convenienceFee, totalAmount, amountPaid, amountDue |
string (decimal) | Decimal strings on reads (GET, list); the create and payment responses return them as numbers |
discountAmount |
string (decimal) | The only discount applied to the total. Line-item discount values are not subtracted by the server, so sum them into discountAmount yourself |
lineItems[] |
array | id, name, description, quantity, unit, unitPrice, discount, discountType, taxRate, amount |
paymentHistory[] |
array | transactionId, amount, paidAt, paymentMethod, notes, isExternal, balanceAfter |
metadata |
object | Includes location (the branch name), acceptCards, acceptAch |
Customer#
{
"id": "550e8400-e29b-41d4-a716-446655440010",
"merchantId": "550e8400-e29b-41d4-a716-446655440000",
"customerName": "John Doe",
"customerType": "individual",
"email": "john@example.com",
"phoneNumber": "+12125550123",
"address": "123 Main St",
"city": "New York",
"state": "NY",
"postalCode": "10001",
"country": "US",
"blockAch": false,
"paymentMethodCount": 1,
"createdAt": "2026-01-01T00:00:00.000Z",
"updatedAt": "2026-01-01T00:00:00.000Z"
}| Field | Type | Description |
|---|---|---|
customerName |
string | Required. The Public API also accepts firstName + lastName and joins them |
customerType |
string | individual or business |
phoneNumber |
string | The Public API also accepts phone |
Payment method#
Returned by GET /customers/:id/payment-methods.
{
"id": "550e8400-e29b-41d4-a716-446655440060",
"methodType": "card",
"cardBrand": "visa",
"last4Digits": "1111",
"expirationMonth": "12",
"expirationYear": "2027",
"cardholderName": "John Doe",
"isDefault": true,
"isVerified": true,
"paymentMethodStatus": "active"
}ACH methods carry bankName, accountLast4 and routingLast4 instead of the card fields. Full account numbers are never returned.
Status Values#
| Object | Values |
|---|---|
Transaction status |
pending, approved, declined, settled, voided, refunded, error, reversed, processing |
Transaction type |
sale, auth, void, refund, capture, cancel_capture, credit |
Subscription status |
active, scheduled, processing, paused, cancelled, expired, pending, completed |
Invoice status |
draft, sent, viewed, partial, paid, overdue, cancelled, pending, expired |
Merchant status |
active, closed, refund_only, restricted |
Device status |
PENDING, REGISTERED, ACTIVE, INACTIVE, SUSPENDED, ARCHIVED |
Settlement status |
calculating, calculated, reconciling, reconciled, discrepancy, approved, payout_processing, paid, failed |
Batch payout status |
draft, pending_review, approved, processing, completed, cancelled |
Refund queue status |
See Refund Queue |
UserMerchant#
One entry of the merchant picker returned by GET /api/v1/auth/my-merchants.
{
"merchantId": "550e8400-e29b-41d4-a716-446655440000",
"companyName": "Acme Coffee",
"role": "merchant_admin",
"status": "active",
"deviceRegistration": {
"hasActiveDevice": true,
"activeDeviceCount": 1,
"device": {
"deviceId": "550e8400-e29b-41d4-a716-446655440001",
"deviceLabel": "Counter 1",
"tpnLast4": "4651",
"status": "ACTIVE",
"lastActiveAt": "2026-08-10T09:14:02.000Z"
}
}
}| Field | Type | Description |
|---|---|---|
status |
string | Merchant status — active, closed, refund_only, restricted |
deviceRegistration |
object | absent | Omitted when the caller passed includeDeviceStatus=false |
deviceRegistration.hasActiveDevice |
boolean | This user has at least one ACTIVE device registered at this merchant |
deviceRegistration.activeDeviceCount |
number | How many, counting only devices this user registered |
deviceRegistration.device |
object | null | Most recently active of those devices; null when there are none |
device.tpnLast4 |
string | Last 4 digits of the TPN — display only; the full TPN is never returned here |
Devices registered by other staff at the same merchant are never counted or returned.
Device (ownership fields)#
Selected fields of the device object relevant to app pairing — full model in Devices.
| Field | Type | Description |
|---|---|---|
registeredByUserId |
string | null | Merchant user who registered the app against this device. Only this user may re-register it while ACTIVE. null for devices registered before the field existed |
registeredAt |
string | null | First registration timestamp; preserved across re-registrations |
lastActiveAt |
string | null | Last authenticated call from the device |
createdBy / updatedBy |
string | null | Portal admin who provisioned or edited the record — not the app user |
Pagination#
List endpoints return a page descriptor next to data. The exact shape differs by service; the common form is meta:
{
"page": 1,
"limit": 50,
"total": 1234
}Subscriptions return total, page, perPage and totalPages beside data. The refund queue returns data: { entries, total, page, limit }.
Error#
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid card number"
}
}There is no field or details member; the message names the field. API-key failures on the Public API use a string error, and a few services return only message. See Error Codes.
Next: View all endpoints →