top of page

Classic: Product management

POST /transact.php · Product management

Classic protocol

This family uses POST /transact.php under the documented sandbox base https://sandbox.nmi.com/api. Send application/x-www-form-urlencoded fields with the private security_key on your server. Do not substitute a REST JSON body or REST Authorization header. Each named variant below has its own action selector and required fields. For maintenance of a Classic integration. Source examples are fixtures, not live credentials; replace their security_key before any authorized test. This reference sends no requests.

Product field discrepancy

The source UpdateProduct example uses description, while the schema field is product_description. The DeleteProduct example also carries an update label. Preserve the schema field name and verify behavior in your configured environment; labels do not change the products selector.

Request language templates

Original transport templates derived from this endpoint’s documented method, server, authentication and media type. Replace path/query/credential placeholders with authorized sandbox values. These examples print the raw status and response; they do not infer business success or retry a request. Save properly URL-encoded name=value pairs for your selected operation as request.form, including its private security_key when required. JSON example objects below describe these form fields; they are not the wire encoding. Node requires a runtime with fetch; PHP requires cURL. Generated source-based examples have not been executed against provider accounts. curl --request POST \ --url 'https://sandbox.nmi.com/api/transact.php' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-binary '@request.form' import { readFile } from 'node:fs/promises'; const body = await readFile('request.form', 'utf8'); const response = await fetch("https://sandbox.nmi.com/api/transact.php", { method: 'POST', headers: { "Content-Type": "application/x-www-form-urlencoded" }, body }); console.log(response.status, await response.text()); from urllib.request import Request, urlopen from urllib.error import HTTPError from pathlib import Path request = Request('https://sandbox.nmi.com/api/transact.php', method='POST', headers={'Content-Type': 'application/x-www-form-urlencoded'}, data=Path('request.form').read_bytes()) try: with urlopen(request, timeout=30) as response: print(response.status, response.read().decode()) except HTTPError as error: print(error.code, error.read().decode()) require 'net/http' require 'uri' uri = URI("https://sandbox.nmi.com/api/transact.php") request = Net::HTTP::Post.new(uri) request["Content-Type"] = "application/x-www-form-urlencoded" request.body = File.binread('request.form') response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https', read_timeout: 30) { |http| http.request(request) } puts response.code puts response.body <?php $curl = curl_init('https://sandbox.nmi.com/api/transact.php'); curl_setopt_array($curl, [ CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30, CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded'], CURLOPT_POSTFIELDS => file_get_contents('request.form') ]); $response = curl_exec($curl); if ($response === false) { throw new RuntimeException(curl_error($curl)); } echo curl_getinfo($curl, CURLINFO_HTTP_CODE), PHP_EOL, $response; curl_close($curl);

Choose the operation variant

Variant Selector fields Required fields AddProductRequest UpdateProductRequest DeleteProductRequest

Request fields

Choose one schema variant. Descriptions retain conditional requirements that are not always included in required arrays. Do not merge all variants into one request. Field Type Required Description Constraints [oneOf 1].[allOf 1].security_key string yes API Security Key assigned to a merchant account. New keys can be generated from the merchant control panel in Settings > Security Keys [oneOf 1].[allOf 1].products string yes Add a product to the Product Manager. enum: ["add_product"] [oneOf 1].[allOf 1].product_sku string yes The unique alpha-numeric SKU for this product. An error will be returned if the SKU is already in use by another product. Examples: `000001` [oneOf 1].[allOf 2].product_description string no The user-facing name of the product. Examples: `1 Gallon Milk` or `Phone Case` [oneOf 1].[allOf 2].product_cost number no The cost of the product before any tax or discounts. Must be greater than `0.00` format: "float" [oneOf 1].[allOf 2].product_currency string no The currency for the product’s price. enum: ["USD", "EUR"] [oneOf 1].[allOf 2].product_unit_of_measure string no The unit of measure for the product. Default - `NAR` enum: ["NAR", "TDK", "MTQ"] [oneOf 1].[allOf 2].product_tax_amount number no The tax that should be added to the product cost. This is a fixed amount, not a percentage. Example: `1.54` format: "float" [oneOf 1].[allOf 2].product_discount_amount number no The discount that will subtracted from the cost of the product. format: "float" [oneOf 1].[allOf 2].product_image_data string no Image for the product, size must be 2MB or smaller. Format: `base64 encoded JPG, PNG, or GIF` `Required` for image upload. [oneOf 1].[allOf 2].product_image_name string no The file name of the image being added with product_image_data. Examples: `product.png` or `sku-1234.jpg` `Required` for image upload. [oneOf 2].[allOf 1].security_key string yes API Security Key assigned to a merchant account. New keys can be generated from the merchant control panel in Settings > Security Keys [oneOf 2].[allOf 1].products string yes Update a product already in the Product Manager. enum: ["update_product"] [oneOf 2].[allOf 1].product_id string yes The automatically generated ID for the product. This was returned in the `add_product` API response, or can be found in the UI under the Product Details page in the Product Manager. Example: `5538585252` [oneOf 2].[allOf 2].product_description string no The user-facing name of the product. Examples: `1 Gallon Milk` or `Phone Case` [oneOf 2].[allOf 2].product_cost number no The cost of the product before any tax or discounts. Must be greater than `0.00` format: "float" [oneOf 2].[allOf 2].product_currency string no The currency for the product’s price. enum: ["USD", "EUR"] [oneOf 2].[allOf 2].product_unit_of_measure string no The unit of measure for the product. Default - `NAR` enum: ["NAR", "TDK", "MTQ"] [oneOf 2].[allOf 2].product_tax_amount number no The tax that should be added to the product cost. This is a fixed amount, not a percentage. Example: `1.54` format: "float" [oneOf 2].[allOf 2].product_discount_amount number no The discount that will subtracted from the cost of the product. format: "float" [oneOf 2].[allOf 2].product_image_data string no Image for the product, size must be 2MB or smaller. Format: `base64 encoded JPG, PNG, or GIF` `Required` for image upload. [oneOf 2].[allOf 2].product_image_name string no The file name of the image being added with product_image_data. Examples: `product.png` or `sku-1234.jpg` `Required` for image upload. [oneOf 3].[allOf 1].security_key string yes API Security Key assigned to a merchant account. New keys can be generated from the merchant control panel in Settings > Security Keys [oneOf 3].[allOf 1].products string yes Update a product already in the Product Manager. enum: ["delete_product"] [oneOf 3].[allOf 1].product_id string yes The automatically generated ID for the product. This was returned in the `add_product` API response, or can be found in the UI under the Product Details page in the Product Manager. Example: `5538585252` { "content": { "application/x-www-form-urlencoded": { "schema": { "oneOf": [ { "$ref": "#/components/schemas/AddProductRequest" }, { "$ref": "#/components/schemas/UpdateProductRequest" }, { "$ref": "#/components/schemas/DeleteProductRequest" } ] }, "examples": { "Add Product": { "$ref": "#/components/examples/AddProduct" }, "Add Product With Image": { "$ref": "#/components/examples/AddProductWithImage" }, "Update Product": { "$ref": "#/components/examples/UpdateProduct" }, "Update Product Image": { "$ref": "#/components/examples/UpdateProductImage" }, "Delete Product": { "$ref": "#/components/examples/DeleteProduct" } } } } } true

Response contract

The Classic methodology describes ampersand-delimited name/value responses. Where this schema advertises JSON media, that declaration is retained below as a source inconsistency; do not assume REST response parsing. For payments, response 1/2/3 distinguishes approval, decline and error. A transport success alone does not prove a payment was approved. { "200": { "description": "Product operation completed successfully", "content": { "application/x-www-form-urlencoded": { "schema": { "oneOf": [ { "$ref": "#/components/schemas/Response" }, { "$ref": "#/components/schemas/ProductResponse" } ] }, "examples": { "Product Added": { "$ref": "#/components/examples/ProductAdded" }, "Product Added Fail": { "$ref": "#/components/examples/ProductAddedFail" }, "Product Updated": { "$ref": "#/components/examples/ProductUpdated" }, "Product Update Failed": { "$ref": "#/components/examples/ProductUpdatedFail" }, "Product Deleted": { "$ref": "#/components/examples/ProductDeleted" }, "Declined Request": { "$ref": "#/components/examples/DeclinedResponse" } } } } } } true

Referenced schema definitions

All schemas and source example objects are preserved here, including descriptions, enums and references. Sample data may be historical. These JSON objects describe form parameters; they are not instructions to send JSON to Classic. { "schemas": { "SecurityKey": { "type": "string", "description": "API Security Key assigned to a merchant account. New keys can be generated from the merchant control panel in Settings > Security Keys" }, "ProductCommon": { "type": "object", "properties": { "product_description": { "type": "string", "description": "The user-facing name of the product.\n\nExamples: `1 Gallon Milk` or `Phone Case`" }, "product_cost": { "type": "number", "format": "float", "description": "The cost of the product before any tax or discounts.\n\nMust be greater than `0.00`" }, "product_currency": { "type": "string", "enum": [ "USD", "EUR" ], "description": "The currency for the product\u2019s price." }, "product_unit_of_measure": { "type": "string", "enum": [ "NAR", "TDK", "MTQ" ], "description": "The unit of measure for the product. Default - `NAR`" }, "product_tax_amount": { "type": "number", "format": "float", "description": "The tax that should be added to the product cost. This is a fixed amount, not a percentage.\nExample: `1.54`" }, "product_discount_amount": { "type": "number", "format": "float", "description": "The discount that will subtracted from the cost of the product." }, "product_image_data": { "type": "string", "description": "Image for the product, size must be 2MB or smaller.\n\nFormat: `base64 encoded JPG, PNG, or GIF`\n\n`Required` for image upload." }, "product_image_name": { "type": "string", "description": "The file name of the image being added with product_image_data.\n\nExamples: `product.png` or `sku-1234.jpg`\n\n`Required` for image upload." } } }, "AddProductRequest": { "title": "Add Product", "allOf": [ { "type": "object", "required": [ "products", "product_sku", "product_description", "product_cost", "product_currency", "security_key" ], "properties": { "security_key": { "$ref": "#/components/schemas/SecurityKey" }, "products": { "type": "string", "enum": [ "add_product" ], "description": "Add a product to the Product Manager." }, "product_sku": { "type": "string", "description": "The unique alpha-numeric SKU for this product. An error will be returned if the SKU is already in use by another product.\n\nExamples: `000001`" } } }, { "$ref": "#/components/schemas/ProductCommon" } ] }, "UpdateProductRequest": { "title": "Update Product", "allOf": [ { "type": "object", "required": [ "products", "product_id", "security_key" ], "properties": { "security_key": { "$ref": "#/components/schemas/SecurityKey" }, "products": { "type": "string", "enum": [ "update_product" ], "description": "Update a product already in the Product Manager." }, "product_id": { "type": "string", "description": "The automatically generated ID for the product. This was returned in the `add_product` API response, or can be found in the UI under the Product Details page in the Product Manager.\n\nExample: `5538585252`" } } }, { "$ref": "#/components/schemas/ProductCommon" } ] }, "DeleteProductRequest": { "title": "Delete Product", "allOf": [ { "type": "object", "required": [ "products", "product_id", "security_key" ], "properties": { "security_key": { "$ref": "#/components/schemas/SecurityKey" }, "products": { "type": "string", "enum": [ "delete_product" ], "description": "Update a product already in the Product Manager." }, "product_id": { "type": "string", "description": "The automatically generated ID for the product. This was returned in the `add_product` API response, or can be found in the UI under the Product Details page in the Product Manager.\n\nExample: `5538585252`" } } } ] }, "Response": { "type": "object", "title": "Response", "properties": { "response": { "type": "string", "enum": [ "1", "2", "3" ], "description": "Status code for the operation. (1) - success, (2) - failed, (3) system error" }, "responsetext": { "type": "string", "description": "Textual description of the operation's result." }, "authcode": { "type": "string", "description": "Authorization code for the operation." }, "amount_authorized": { "type": "string", "description": "(Conditional) This will optionally come back when requesting partial payment. Authorization amount." }, "transactionid": { "type": "string", "description": "(Conditional - Payment) Payment gateway transaction id." }, "invoice_id": { "type": "string", "description": "(Conditional - Invoice) Identifier for the invoice." }, "avsresponse": { "type": "string", "description": "Address Verification Service response code." }, "cvvresponse": { "type": "string", "description": "Card Verification Value response." }, "orderid": { "type": "string", "description": "Identifier for an order related to this invoice." }, "type": { "type": "string", "enum": [ "sale", "auth", "validate", "credit", "offline", "capture", "void", "refund", "complete_partial_payment", "add_invoice", "update_invoice", "send_invoice", "close_invoice", "add_plan", "edit_plan", "add_subscription", "" ], "description": "Type of operation that this response is for." }, "partial_payment_id": { "type": "string", "description": "(Conditional) This will optionally come back when requesting partial payment. A numeric identifier which is used when submitting subsequent transactions." }, "partial_payment_balance": { "type": "string", "description": "(Conditional) This will optionally come back when requesting partial payment. The payment's remaining balance." }, "platform_id": { "type": "string", "description": "Platform ID associated with the transaction." }, "response_code": { "type": "string", "description": "Another status or result code for the operation. See [Response Code Table](#section/Appendixes/Payment-API-Response-Codes)" }, "subscription_id": { "type": "string", "description": "(Conditional - Subscription) The subscription ID that was created" }, "emv_auth_response_data": { "type": "string", "description": "(Conditional) This will optionally come back when any chip card data is provided on the authorization. This data needs to be sent back to the SDK after an authorization." }, "payment_terms": { "type": "string", "description": "(Conditional - Invoice) The terms of payment for the invoice." }, "customer_vault_id": { "type": "string", "description": "(Conditional - Customer Vault) The original customer_vault_id passed in the transaction request or the resulting customer_vault_id created on an approved transaction.\n\nNote: Only returned when the \"Customer Vault\" service is active." }, "kount_score": { "type": "string", "description": "The Kount \"Omniscore\" indicating the level of risk on a given transaction. The higher the score, the lower the risk.\n\nNote: Only returned when the \"Kount\" service is active." } } }, "ProductResponse": { "type": "object", "title": "Response - Products", "properties": { "response": { "type": "string", "enum": [ "1", "2", "3" ], "description": "Status code for the operation. (1) - success, (2) - failed, (3) - system error" }, "responsetext": { "type": "string", "description": "Textual description of the operation's result." }, "product_id": { "type": "string", "description": "Product ID." }, "product_sku": { "type": "string", "description": "(Conditional - returned for create/update requests) The unique alpha-numeric SKU for this product." }, "product_description": { "type": "string", "description": "(Conditional - returned for create/update requests) The user-facing name of the product." }, "product_cost": { "type": "string", "description": "(Conditional - returned for create/update requests) The cost of the product before any tax or discounts." }, "product_currency": { "type": "string", "description": "(Conditional - returned for create/update requests) The currency for the product\u2019s price" }, "product_commodity_code": { "type": "string", "description": "(Conditional - returned for create/update requests) Product commodity code." }, "product_unit_of_measure": { "type": "string", "enum": [ "NAR", "TDK", "MTQ" ], "description": "(Conditional - returned for create/update requests) The unit of measure for the product. Default - `NAR`" }, "product_tax_amount": { "type": "string", "description": "(Conditional - returned for create/update requests) The tax that should be added to the product cost." }, "product_discount_amount": { "type": "string", "description": "(Conditional - returned for create/update requests) The discount that will subtracted from the cost of the product." }, "product_image_name": { "type": "string", "description": "(Conditional - returned for create/update requests) The file name of the image being added with product_image_data." }, "product_category": { "type": "string", "description": "(Conditional - returned for create/update requests) Product category." } } } }, "examples": { "AddProduct": { "summary": "Add Product", "description": "Add new product", "value": { "products": "add_product", "product_sku": "32463230005", "product_description": "Phone Case", "product_cost": 15.5, "product_currency": "USD", "security_key": "6457Thfj624V5r7WUwc5v6a68Zsd6YEm" } }, "AddProductWithImage": { "summary": "Add Product With Image", "description": "Add new product with image", "value": { "products": "add_product", "product_sku": "32463230005", "product_description": "Phone Case", "product_cost": 15.5, "product_currency": "USD", "product_image_data": "base64_encoded_content", "product_image_name": "product-123.png", "security_key": "6457Thfj624V5r7WUwc5v6a68Zsd6YEm" } }, "UpdateProduct": { "summary": "Update Product", "description": "Update product - set new description", "value": { "products": "update_product", "product_id": "5538585252", "description": "1 Gallon Milk", "security_key": "6457Thfj624V5r7WUwc5v6a68Zsd6YEm" } }, "UpdateProductImage": { "summary": "Update Product Image", "description": "Update product image", "value": { "products": "update_product", "product_id": "5538585252", "product_image_data": "base64_encoded_content", "product_image_name": "product-123.jpg", "security_key": "6457Thfj624V5r7WUwc5v6a68Zsd6YEm" } }, "DeleteProduct": { "summary": "Update Product", "description": "Update product - set new description", "value": { "products": "delete_product", "product_id": "5538585252", "security_key": "6457Thfj624V5r7WUwc5v6a68Zsd6YEm" } }, "ProductAdded": { "summary": "Product Added", "description": "Product added successfully", "value": { "response": "1", "responsetext": "Product Added", "product_id": "8610653943", "product_sku": "32463230005", "product_description": "Phone Case", "product_cost": "15.50", "product_currency": "USD", "product_commodity_code": "", "product_unit_of_measure": "NAR", "product_tax_amount": "", "product_discount_amount": "", "product_image_name": "", "product_category": "" } }, "ProductAddedFail": { "summary": "Product Added Fail", "description": "Product not added", "value": { "response": "3", "responsetext": "Product SKU, description, cost, and currency are required.\nREFID:1185534822", "authcode": "", "transactionid": "", "avsresponse": "", "cvvresponse": "", "orderid": "", "type": "", "response_code": "300" } }, "ProductUpdated": { "summary": "Product Updated", "description": "Product updated successfully", "value": { "response": "1", "responsetext": "Product Updated", "product_id": "8610675975", "product_sku": "32463230006", "product_description": "1 Gallon Milk", "product_cost": "15.5000", "product_currency": "USD", "product_commodity_code": "", "product_unit_of_measure": "NAR", "product_tax_amount": "0.00", "product_discount_amount": "0.00", "product_image_name": "", "product_category": "" } }, "ProductUpdatedFail": { "summary": "Product Update Failed", "description": "Product update failed", "value": { "response": "3", "responsetext": "Object not found REFID:1159407847", "authcode": "", "transactionid": "", "avsresponse": "", "cvvresponse": "", "orderid": "", "type": "", "response_code": "300" } }, "ProductDeleted": { "summary": "Product Deleted", "description": "Product deleted successfully", "value": { "response": "1", "responsetext": "Product Deleted", "product_id": "8610675975" } }, "DeclinedResponse": { "summary": "Failed to Create Plan", "description": "Failed to create a new plan", "value": { "response": "3", "responsetext": "There is already a plan using the SKU you have specified. REFID:1203610329", "authcode": "", "transactionid": "", "avsresponse": "", "cvvresponse": "", "orderid": "", "type": "", "response_code": "100" } } } } true

Published operation notes

Additional operation-specific source notes, including legacy outcome tables where published. Read alongside the family guidance above; source marketing claims are not compliance guarantees. <details> <summary>Methodology</summary> **Steps:** 1. The customer sends their payment information to the merchant's web site. 2. The merchant web site posts the payment data to the Payment Gateway. 3. The Payment Gateway responds immediately with the results of the transactions. 4. The merchant web site displays the appropriate message to the customer. The communication method used to send messages to the Payment Gateway's server is the standard HTTP protocol over an SSL connection. In the Payment API method, the communications with the cardholder (Steps 1 and 4) are developed completely by the merchant and therefore are not defined by the Payment Gateway. Step 1 should simply collect the payment data from the cardholder and Step 4 should display the appropriate transaction receipt or declined message. In Step 2, transaction details should be delivered to the Payment Gateway using the POST method with the appropriate variables defined below posted along with the request. In Step 3, the transaction responses are returned in the body of the HTTP response in a query string name/value format delimited by ampersands. For example: `variable1=value1&variable2=value2&variable3=value3` ### Customer Vault The Customer Vault was designed specifically for businesses of any size to address concerns about handling customer payment information. Visa and MasterCard have instituted the Payment Card Industry (PCI) Data Security to protect cardholder data, wherever it resides, ensuring that members, merchants, and service providers maintain the highest information security standards. These associations have also deemed that merchants will be held liable for any breach of cardholder data. This has become a major concern for merchants who handle credit card or electronic check payments. The Customer Vault is designed for these merchants who desire to avoid the tremendous costs and resources involved in becoming PCI compliant under these circumstances. The Customer Vault does this by allowing merchants to transmit their payment information through a Secure Sockets Layer (SSL) connection for storage in our Level 1 PCI certified data facility. Once the customer record has been securely transmitted to the Customer Vault, the merchant can then initiate transactions remotely without having to access cardholder information directly. This process is accomplished without the merchant storing the customer's payment information in their local database or payment application. </details> <details> <summary>Response Code Table</summary> | Code | Description | |:------|:-------------------------------------------------------------------| | 100 | Transaction was approved. | | 200 | Transaction was declined by processor. | | 201 | Do not honor. | | 202 | Insufficient funds. | | 203 | Over limit. | | 204 | Transaction not allowed. | | 220 | Incorrect payment information. | | 221 | No such card issuer. | | 222 | No card number on file with issuer. | | 223 | Expired card. | | 224 | Invalid expiration date. | | 225 | Invalid card security code. | | 226 | Invalid PIN. | | 240 | Call issuer for further information. | | 250 | Pick up card. | | 251 | Lost card. | | 252 | Stolen card. | | 253 | Fraudulent card. | | 260 | Declined with further instructions available. (See response text) | | 261 | Declined-Stop all recurring payments. | | 262 | Declined-Stop this recurring program. | | 263 | Declined-Update cardholder data available. | | 264 | Declined-Retry in a few days. | | 300 | Transaction was rejected by gateway. | | 400 | Transaction error returned by processor. | | 410 | Invalid merchant configuration. | | 411 | Merchant account is inactive. | | 420 | Communication error. | | 421 | Communication error with issuer. | | 430 | Duplicate transaction at processor. | | 440 | Processor format error. | | 441 | Invalid transaction information. | | 460 | Processor feature not available. | | 461 | Unsupported card type. | </details> true

Reconcile outcomes

Persist the returned transaction or object identifier and inspect the operation result before changing application state. Investigate interrupted financial responses before retrying. Saved methods, invoice delivery, schedules and refunds have different side effects; select the corresponding variant explicitly. Account and processor behavior have not been executed in this audit.

Join the community and get the latest biz news & tips

Thanks for submitting!

© 2025 Betterpay. All Rights Reserved.

bottom of page