Process Classic cloud-terminal payments
Use the Classic payment request and its asynchronous status contract without mixing v5 schemas or SDK amount formats.
Send the payment from your backend
POST https://secure.nmi.com/api/transact.php uses form encoding (application/x-www-form-urlencoded or multipart/form-data), with security_key in the request. Device management and async polling use Bearer authentication instead. Do not send username/password in place of security_key. Field Contract poi_device_id Registered terminal GUID for sale, auth, credit or validate. type sale, auth, credit or validate. amount Decimal x.xx; validate omits it or uses0.00. response_method synchronous(default) or asynchronous. orderid / ponumber Order and purchase-order correlation. customer_vault add_customer or update_customer after successful processing. customer_vault_id Existing/chosen identifier; gateway generates one if omitted. processor_id Explicit routing for multiple-MID accounts.
Choose synchronous or asynchronous response
Synchronous waits for customer interaction and final response, with the documented 300-second terminal timeout. Asynchronous returns response_code 101 and async_status_guid for polling; Request Accepted is not a financial approval. Vault ID is not in the initial asynchronous acceptance response. Confirm the outcome before considering a replacement after a timeout. curl --request POST \ --header "Content-Type: application/x-www-form-urlencoded" \ --data-urlencode "security_key=$MERCHANT_API_KEY" \ --data-urlencode "poi_device_id=$POI_DEVICE_ID" \ --data-urlencode "type=sale" \ --data-urlencode "amount=1.00" \ --data-urlencode "response_method=asynchronous" \ "https://secure.nmi.com/api/transact.php" Request example only. It initiates a payment if executed against an enabled live account. Use your approved test setup; this portal has not executed it.
Poll the retained reference
GET /api/asyncstatus/{asyncStatusGuid} returns JSON. Its query field is responseMethod, not response_method. The default asynchronous option returns current progress; synchronous waits for a terminal outcome. Preserve the original GUID throughout. asyncStatus Meaning inFlight Interaction unfinished; success=false is not yet a decline. poiDeviceInUse Another GUID currently owns this terminal. cancelled / cancelledAtTerminal General or terminal cancellation; source says no transaction created. cancelledByApi / cancelledByTimeout Cancelled through API or inactivity. interactionComplete Interaction finished; inspect transaction.success, condition and any error.
Read the financial result
Successful sales/credits report pendingsettlement; auths remain pending until capture; validate is complete without a charge. Failed is the decline condition. Retain transaction.id, authCode and customerVaultId when returned. Error code 300 can reflect difficulty obtaining status; HTTP 400/401/404 distinguish missing input, invalid key and unknown platform ID.
Capture or reverse by transaction ID
Classic capture, void and refund use transactionid, without poi_device_id or response_method because no device interaction is involved. Capture/refund may specify amount; omission requests the documented full amount. Unlinked credit is a different operation from refunding an existing payment.
Retain receipt metadata
EMV responses include verification method, application ID/labels and terminal status information. Signature verification requires operator confirmation. Do not rename the v2/Classic response fields into SDK names. The source examples disagree on transactionStatusInformation versus transactionStatusInfo inside EMV metadata; retain the actual returned payload and verify against the chosen contract.
Add optional transaction data carefully
The source includes cardholder name/company, billing address/country/phone/email, order description, tax included in amount, up to 20 merchant_defined_field_# values and processor-dependent descriptor overrides. Descriptor fields use the source’s restricted 0–60-character pattern; do not copy a v5 HTTPS-URL constraint onto this legacy descriptor_url. Source HTML merges order_description into the email description, so confirm that field in the Classic reference before using it.