Report a transaction
Reports one card or QR transaction. Call it after each transaction, approved or declined.
A 202 means Narya has accepted the transaction; it is stored shortly
afterwards.
Resubmitting an id is always safe: it never creates a second
transaction. After a 500 or 503, or if the connection drops,
resend the same body with the same id.
DeviceAuthAuthorizationBearer <dvc_<prefix>_<secret>>The terminal's device token, returned once by POST /device/v1/activations.
Send it as Authorization: Bearer <token> on every request except
activation.
application/json- body
One transaction. channel selects the variant, card or qr. Each
variant accepts only its own fields, so a card field on a QR
transaction is refused with 400 rather than ignored.
Whether original_transaction_id is required depends on type. A
missing or forbidden one is reported in invalid_params.
id*stringA UUIDv7 your terminal generates. Submitting the same id again updates
that transaction instead of creating another.
uuiddevice_assignment_id?stringOptional. The assignment the transaction was made under. Omit it on a
terminal that runs one product: Narya finds the assignment from the terminal
and captured_at. Send it on a terminal that runs several products at once.
Without it Narya cannot tell which product a transaction belongs to, and the
transaction is accepted with 202 but not recorded.
uuidchannel*"card""card"type*string"sale""refund""void_sale""void_refund""pre_auth""completion"status*string"approved""declined"captured_at*stringThe terminal's clock when the transaction started.
date-timecurrency*stringThe cardholder's currency (ISO 4217). Anything other than MYR means the cardholder accepted a dynamic currency conversion (DCC) offer.
^[A-Z]{3}$amount_total*integerIn minor units: 1250 is MYR 12.50. With DCC, the amount in the cardholder's currency.
int640 <= valueamount_local*integerAlways MYR, in minor units. Equal to amount_total without DCC.
int640 <= valuetid?stringTerminal ID (ISO 8583 field 41), as sent to the host.
length <= 16mid?stringMerchant ID (field 42), as sent to the host.
length <= 32acquirer_ref?stringRetrieval reference number (field 37). A void has its own. Absent on offline sales.
length <= 32response_code?stringHost response code (field 39).
length <= 8invoice_no?stringThe terminal's invoice number (field 62).
length <= 32batch_no?stringThe settlement batch number. Batch numbers repeat across settlement cycles.
length <= 16dcc_offered?booleanWhether DCC was offered, including when the cardholder chose MYR.
dcc_conversion_rate?stringDecimal string, for example "4.4213", so the quoted rate stays exact. Up to 10 digits before the point and 8 after.
^-?[0-9]{1,10}(\.[0-9]{1,8})?$dcc_margin_pct?stringDecimal string, like dcc_conversion_rate. 3.15 means 3.15 per cent. Up to 3 digits before the point and 3 after.
^-?[0-9]{1,3}(\.[0-9]{1,3})?$dcc_reference?stringlength <= 32card_scheme?string"visa""mastercard""mydebit""jcb""upi""amex"card_pan_first6?stringThe first six digits of the card number.
^[0-9]{6}$card_pan_last4?stringThe last four digits of the card number.
^[0-9]{4}$card_entry_mode?string"chip""contactless""magstripe""manual""fallback""card_not_present"card_cvm?stringThe cardholder verification method used. none means no verification was required; omit the field when the terminal cannot report one.
"pin""offline_pin""signature""cdcvm""none"card_approved_offline?booleanApproved offline: voice-approved or below the floor limit. Independent of type completion.
card_approval_code?stringAuthorisation code (field 38).
length <= 12card_stan?stringSystem trace audit number (field 11). A reversal reuses the original value.
length <= 12original_transaction_id?stringThe id of the transaction this one refers to. Required for void_sale,
void_refund and completion; optional for refund; not allowed for
sale and pre_auth.
uuidAccepted. The transaction is stored shortly afterwards.
application/json- response
Returned with 202. The transaction is accepted and is stored shortly
afterwards.
event_id*stringNarya's reference for this submission. Record it, and quote it if an accepted transaction later appears to be missing.
uuidid*stringThe id you submitted, returned unchanged.
uuidreceived_at*stringWhen Narya accepted the submission. A large gap from the captured_at you
sent suggests the terminal's clock has drifted. Reports group transactions
by captured_at, so a wrong clock files them under the wrong day.
date-timecurl -X POST 'https://device-narya-staging.pmadvisors.my/device/v1/transactions' \ -H 'Content-Type: application/json' \ -d '{ "id": "01a01e96-4153-7925-997c-38e69a23650c", "device_assignment_id": "01a01e96-4153-7974-ad6f-ad9c974010d6", "channel": "card", "type": "sale", "status": "approved", "captured_at": "2026-08-20T09:15:04Z", "currency": "MYR", "amount_total": 1250, "amount_local": 1250, "tid": "70012345", "mid": "000000012345678", "acquirer_ref": "422612345678", "response_code": "00", "invoice_no": "000137", "batch_no": "000012", "card_scheme": "visa", "card_pan_first6": "411111", "card_pan_last4": "1111", "card_entry_mode": "contactless", "card_approval_code": "T12345", "card_stan": "001374"}'{ "event_id": "a7a26ff2-e851-45b6-9634-d595f45458b7", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "received_at": "2019-08-24T14:15:22Z"}