Specification
AnywhereCommerce Cloud POS API Specification Doc
Contents
- Key Concepts
- Endpoints
- Cloud Entities
- Types of Cloud Entities
- Storing Entities on the cloud server
- Special Case: Storing Merchant and User Details on the Cloud Server
- Accessing and Searching for Objects
- Advanced Queries
- Using the Cloud Server as a Data Store
- Viewing Log Files
- Real-Time Troubleshooting & Logging
- Terminal & Transaction Configuration Basics
- Sending custom fields
- Securing Communication to the Device
- Transaction Flow
- Quick Start Guide
- Device-to-Cloud Methods
- App-to-Cloud Methods
- Appendix A: The configuration object
- Appendix B: The transaction object
Getting Started
Key Concepts
AnyPay Endpoint
Endpoint
https://api.payments.ac/v1
For those using older (pre 1.90.0) versions of AnyPay Cloud or the SDKs of the SDKs, you may be using older endpoints. Support for older endpoints was ENDED as of April 2020. If you are using older endpoints or an SDK version PRIOR to 1.90.0 you MUST update to the current endpoint. Failure to do will result in interruption in service as September 1st 2022. If you do not know how to update your endpoints or SDKs, please contact an integration specialist at Anywhere Commerce using the customer support center.
The cloud system is intended to create 1-1 representations between a physical
entity (such as a POS terminal) and its representation in the cloud. This is
done by posting and retrieving objects from a data model via basic REST. All
objects are stored and returned in JSON format.
Method | Objective |
---|---|
GET | Retrieve a resource at the specified URL. |
POST | Create a resource at the specified URL. If the resource already exists, a 409 CONFLICT response will be returned. |
PUT | Updates a resource at the specified URL. You must provide the entire object. If the resource does not exist, as 404 NOT FOUND response will be returned. |
PATCH | Our implementation updates the specified fields of the provided object at the specified URL. Must be a single object. Batch updates or complex instructions are not currently supported. A 404 NOT FOUND response will be returned if the object does not exist. |
DELETE | Removes a resource at the specified URL |
The standard logic of the resource model URL structure is:
[https://api.payments.ac/v1/{your_company}/{entityType}/{id}]
URL Part | Options | Description |
---|---|---|
your_company | Required | The name given to you by your integrator, which represents all of your company’s resources available on the cloud system. This forms the base URL for all requests. |
entityType | Required | The type of entity you wish to create or retrieve. For example, transactions or terminals |
id | Optional | the id of the specific resource you wish to retrieve. Omitting it will provide a list of all accessible entities, similar to a directory function. Please see Accessing and Searching objects for more details on how to search and filter objects. |
Type | Path | Description |
---|---|---|
company | Part of your base URL | Configuration details for your company during setup, such as permissions, defaults, etc. Singleton |
endpoints | /endpoints | Configuration details for different gateways and hosts your terminal routes transactions to. Examples include prod, sandbox, etc. |
terminal | /terminals | Configuration details for the physical or virtual devices that actually process transactions. |
transaction | /transactions | Payment transactions, such as credit card transactions, etc. |
session | /terminals/{id}/session | Brokers the interactions between a terminal and a host or operator. Singleton |
merchant | /merchants | Configuration details for merchants (optional) |
user | /users | Configuration details for users (optional) |
Storing entities on the cloud server
Entities can be POST’ed to the cloud server, and will exist as living documents
that can be consumed or updated as required by your implementation. However,
sensitive items like transactions and terminals that are consumed by important
services may have some special requirements. For example, transactions become
read-only after they have been processed, and only special operations like tip
adjustments will work.
The REST server is stateless, meaning that any specific details that may be
necessary for the lifecycle of an entity should be sent as part of object that
requires access to them. For example, if you want to bind a particular terminal
to a particular Merchant ID, simply add it as a field to the terminal
configuration (please see the section “Adding Custom Fields to An Object” for
more details on how to do this).
The data model is fully extensible, so you can add any information you like in
whatever format you like to whatever object you like, provided it doesn’t
conflict with existing object keys.
Helpful Tip: For complex objects, or objects that can be frequently updated,
it is helpful to store a reference to the object instead of the object itself.
For example, rather than storing the full Merchant record with a terminal, and
duplicating it for every terminal that merchant may use (which would require
updating each terminal if the merchant record was updated), you can simply store
the information as a URL to the requisite resource.
For example, if you have a merchant configuration for merchant cookies2go
stored as https://api.payments.ac/v1/mycompany/merchants/cookies2go, instead of
storing the whole object in the terminal, you can simply store said URL. Then,
you can dynamically retrieve the merchant details at any time when examining the
terminal record.
Special Case: Storing Merchant and User Details on the Cloud Server
It is not necessary to store merchant or user data on the cloud, but it can be
convenient. We have offered two default resource directories, /merchants and
/users, that have integrated JSON search capabilities. Anything posted there
will be easily searchable using our integrated advanced search functionality.
Just make sure the object you store is in JSON format.
Accessing and Searching for Objects
Individual entities can be accessed by providing the ID parameter as the
parameter in the Url after the requested entity. For example, to fetch a
transaction with id 12345, you can simply call:
GET https://api.payments.ac/v1/mycompany/transactions/12345
The system provides some convenience methods for advanced searches. Advanced
queries are only available on entities. They are not available on custom
uploaded resources.
Query Param | Description |
---|---|
keyword | Searches all the values of the object for the provided keyword. Returns the entire object if a keyword is contained in one of the values. This is useful for partial matching. e.g. ?keyword=blue will match on both { value=”blue” } and { value=”bluebird” } |
exactValue | Searches all the values of the object for the provided keyword. Returns the entire object if the exact word is found. e.g. ?exactValue=blue will match on { value=”blue” } but NOT match on { value=”bluebird” } |
dateFrom | Searches against the dateCreated of the object and returns objects whose dateCreated is greater than or equal to dateFrom. The date format is the W3C standard date format, URL encoded - e.g. YYYY-MM-DDThh:mmTZD (eg 2017-07-16T19:20+01:00). For maximum accuracy, be sure to include the timezone of the origin. |
dateTo | Searches against the dateCreated of the object and returns objects whose dateCreated is less than or equal to dateTo. The date format is the W3C standard date format, URL encoded - e.g. YYYY-MM-DDThh:mmTZD (eg 2017-07-16T19:20+01:00). For maximum accuracy, be sure to include the timezone of the origin. |
Using the Cloud Server as a Data Store
Since the cloud system is a simple REST system, you can also use it to store
other data such as logos, receipts, log files, or any other resource you wish to
use. In order to store a resource on the cloud server, prefix the URL with /res.
Any content-type is accepted, including text files, images, video, documents,
etc.. At this time, the PATCH operation is not supported for custom storage.
Method | URL |
---|---|
GET | /res/{pathToResource} |
POST | /res/{pathToResource} |
PUT | /res/{pathToResource} |
DELETE | /res/{pathToResource} |
Logging is optional, but enabled by default. By default, the cloud API’s stream
log files of important events to the cloud server. This allows for a lightweight
storage of log files without taking up needless resources on the local machine.
These log files are retained for 30 days and then deleted.
Log files stored on the server are typically stored underneath the entity being
logged, and can be accessed by appending /logs to the entity in question.
For example
Note: Alternatively, you can specify a filename instead of a URL to log locally,
in which case no data will be sent to the cloud server.
Logs are controlled by the entity’s configuration object. Specific
properties that control logging are:
Property | Default Value | Possible Values |
---|---|---|
streamLogsTo | https://api.payments.ac/v1/{entity}/{id}/logs | Either a URL (for remote logging) or a filename (for local logging only) Leave empty to disable logging |
logLevel | info | verbose = lots of tedious information debug = useful info for troubleshooting info = logs security events, transaction events, and errors. error = log errors only |
logRetentionDays | 30 | Days to retain logs. Only valid for remote logging. |
maxLogFileSize | 30000 | Maximum log file size (in kb) before truncation. Only valid for local logging. |
Example:
curl https://api.payments.ac/v1/mycompany/terminals/12345
...
200 OK
{
"id": "12345",
"configuration" {
"logging": {
"remoteLoggingEnabled": true,
"logLevel": "DEBUG"
},
"streamLogsTo" : "https://api.payments.ac/v1/mycompany/terminals/12345/logs",
"logLevel":"info",
"logRetentionDays":"30"
}
}
Real-Time Troubleshooting & Logging
A key feature of remote logging is the ability to see – in real time – what
might be happening with a particular terminal. For example, a terminal may be
generating error messages, and your technical support team may want to see what
is going on. You can view the logs generated by the device in real time by
appending /diagnostics?realtime to the terminal resource you wish to review
from inside a web browser such as Chrome.
Example: To view the logs generated in real-time for terminal 12345, simply
navigate in Chrome or Firefox to:
https://api.payments.ac/v1/mycompany/terminals/12345/diagnostics?realtime
Note: To see real-time logs, the streamLogsTo terminal configuration property
must be set to the default value (or omitted). See the section immediately above
for details.
Terminal & Transaction Configuration Basics
Every entity has a special property called configuration which contains
information that describes its configuration parameters. This object is fully
extensible and free to customize as your application requires. (Configuration
properties used by the AnyPay Cloud ecosystem are provided in Appendix B).
The cloud API has been designed for maximum flexibility in mind. You can set a
default configuration for all terminals, override it for certain terminals, and
further override it on a per-transaction basis to enable or disable features
(for example, enabling tip options) on the fly.
There are three types of configuration, each of which overrides the other:
-
The default terminal configuration (applied to all terminals when
initializing) -
The terminal configuration (applied to a specific terminal)
-
The transaction configuration (applied to the transaction only)
Terminals can also inherit from other terminal configurations, creating a highly
configurable flexible hierarchy that can allow you to specify certain
configurations once and then have terminals inherit from them.
For example, consider a restaurant with four terminals. Term1 and term2 are
mobile terminals used by their mobile sales team. Term3 and term4 are
in-store customer facing terminals. For simplicity, assume that there is one
configuration property controlling refunds, which is set to true in the
default configuration. But since refunds aren’t needed by a mobile salesforce,
their parent overrides the value and sets it to false. In this case, the
configuration inheritance would look like the following:
How to set up a configuration hierarchy:
Default configurations are created with a special terminal ID called
default. Every company has a default configuration that should define all
necessary terminal parameters for their organization.
Terminals inherit from other terminals by setting the parentID property of
the object to the ID of the terminal they wish to inherit from.
If you want to apply a specific configuration to a specific device, simply post
that configuration when registering the device, or update the device’s
configuration via the API command. Please see Registering a Device, and
Updating a Device’s Configuration API commands for details on how to
configure the individual device.
Configurations can also be overridden on a per-transaction basis. For example,
if you want to suppress the tip options for takeout orders in a restaurant, you
can simply add the enableTip tag to the transaction’s configuration object,
and set it to false. The tip will be disabled for that transaction and that
transaction only.
The JSON objects can be extended to include any custom fields, which will be
returned when the entity is queried. This can be useful to pass extra control
data between the POS application and the terminal, or to send extra data to the
server when processing a transaction.
The data model is fully extensible, so you can add any information you like in
whatever format you like to whatever object you like, provided it doesn’t
conflict with existing object keys.
To send custom fields, simply extend the JSON object with your field. Be
careful, however, to ensure that there are no name collisions with other fields
named in the API. If there are, it is recommended you rename the field or
include it in a sub-object named extras.
Example of adding custom fields to a transaction object:
"transaction": {
"transactionType": "SALE",
"id": "12345",
"orderId": "abc123",
"subtotal": "10.00",
"totalAmount": "10.00",
"currency": "USD",
"your_field_goes_here": "your value goes here",
"you_can_add_more_fields": {
"they_can_even_be_complex_objects" : ["it", "is", "fine"]
}
}
Securing Communication to the Device
All communication to the device must be done using either a sessionKey, which
pairs the device to a particular POS application, or the adminKey provided as
part of your vendor setup. The sessionKey is generated when a session to the
device is created, and can be set to automatically expire according to your
requirements.
Depending on your security requirements, this may be sufficient. For added
layers of security, you can also provide a SHA-256 hash of the communication
plus a timestamp and a secret_key, which was provided during vendor setup. The
timestamp ensures that no two hashes are ever the same. And because the secret
key is not sent with the message, and known only to you, you can ensure the
authenticity of the message and prove both its origin and its integrity.
Alternatively, OAuth can be used if preferred.
Please contact your integration specialst for more information on enabling these
added security features in your deployment.
Running Transactions
The benefit of the cloud approach is that the terminal device does not require
any physical connection to the POS application. Rather, the terminal is
connected directly to the internet via WiFi or LTE and controlled via standard
HTTPS requests which can be done from any platform connected to the internet,
including a web browser.
In the cloud environment, the terminal communicates directly with the
acquirer/gateway to process transactions. No cardholder data is passed through
the cloud to the POS application.
Here is the basic workflow:
-
The host application submits a transaction request via HTTPS to the cloud
server -
The device polls the cloud server to see if any transaction requests are
queued -
Once a transaction request is found, the device comes to life and prompts
the user to present their card. -
Once the customer presents the card, the device connects directly to the
acquirer/gateway for authorization. -
The device receives the response from the acquirer/gateway, and displays an
approval/decline to the cardholder. -
The approval/decline, and basic details for the receipt (such as auth code,
transaction status, masked PAN, etc..), are passed back to the cloud server. -
The host application receives the response (either via a callback, or
polling) from the terminal, and displays the result to the end user and/or
generates a receipt.
Note: replace “mycompany” with your company name, and “term1” with the terminal
ID you are targeting.
Step 1: GET a session key
A session key locks the terminal to your software and ensures nobody else can
send a transaction to that device until you release the session.
GET https://api.payments.ac/v1/mycompany/terminals/term1/session
Example: Creating a new session
curl https://api.payments.ac/v1/mycompany/terminals/term1/session
...
200 OK
{
"terminalId": "123456",
"sessionKey": “2eyCyPVOYnKU1u64UtckfpxldZIDLQD5”
"sessionKeyExpiry": "2018-05-09 23:59:59"
}
Step 2: POST a transaction to the terminal
Post the transaction directly to the terminal. The terminal will pick up the
transaction and begin processing the transaction. You will need to provide the
session key obtained in Step 1 as an HTTP header.
Optional, but recommended: if you have the capability of receiving HTTP traffic
on your host, add a callbackUrl property to the transaction to receive a
callback when the transaction is processed.
Example:
curl https://api.payments.ac/v1/mycompany/terminals/term1/transaction \
-X POST \
-H "sessionKey: 2eyCyPVOYnKU1u64UtckfpxldZIDLQD5" \
-d '\
{
"transactionType": "SALE", \
"id": "123123", \
"totalAmount": "10.00", \
"currency": "USD", \
"callbackUrl": "https://yourhostgoeshere.com/etc", // Optional \
"configuration": { \
"enableTip": "true", \
}, \
} \
'
}
...
201 CREATED
{
"uuid": "b0c7e012-eb5c-4a21-8f32-5b8e2b16e863",
"id": "123123",
"transactionType": "SALE",
"terminalId": "term1",
"totalAmount": "10.00",
"currency": "USD",
"status": "QUEUED",
"callbackUrl": "https://yourhostgoeshere.com/etc",
"configuration": {
"enableTip": "true",
}
}
Step 3a – If you provided a callbackUrl
When the cloud terminal processes the transaction, the response will be POST’ed
back to the callback URL you provided in Step 2.
(callback from the terminal to callbackUrl) https://yourhostgoeshere.com/etc
{
"uuid": "b0c7e012-eb5c-4a21-8f32-5b8e2b16e863",
"id": "123123",
"terminalId": "term1",
"transactionType": "SALE",
"approvedAmount": "10.00",
"status": "APPROVED",
"approvalCode": "ABC123",
"responseText": "Transaction Approved",
"cardType": "Visa",
"cardNumber": "4012XXXXXXXX1881",
"cardholderName": "John Doe",
"currency": "USD",
}
Note: If you provided the sessionKey as a URL parameter to the callbackUrl in
step 2, you will get all the transaction data necessary to generate a receipt.
If you did not provide a sessionKey, you will get the transaction’s id, status,
and responseText fields. You will need to query the transaction directly to get
the fields necessary to generate a receipt.
Step 3b – If you did not provide a callbackUrl
You will need to poll for the result of the transaction. However, since the
transaction has been consumed by the terminal, it will no longer be in the
queue. You will need to query the transaction record directly to get the status.
Note the URL change below:
Example: Keep polling transaction with ID 123123 until the transaction
processes.
The ?poll parameter instructs the server to only return data if the transaction
has completed processing. This ensures the polling mechanism is lightweight and
keeps bandwidth to a minimum.
$ curl https://api.payments.ac/v1/mycompany/transactions/123123?poll \
-X GET
-H "sessionKey: 2eyCyPVOYnKU1u64UtckfpxldZIDLQD5"
...
304 NOT MODIFIED
You will continue to get a 304 Not Modified response until the transaction
processes, in which case you will get a 200 OK plus the data necessary to
construct a receipt.
Note: To prevent server overload, please ensure the polling requests are three
seconds apart or greater.
curl https://api.payments.ac/v1/mycompany/transactions/123123?poll \
-X GET \
-H "sessionKey: 2eyCyPVOYnKU1u64UtckfpxldZIDLQD5" \
...
200 OK
{
"uuid": "b0c7e012-eb5c-4a21-8f32-5b8e2b16e863",
"id": "123123",
"status": "APPROVED",
"responseText": "Transaction Approved",
}
curl https://api.payments.ac/v1/mycompany/transactions/123123 \
-X GET \
-H "sessionKey: 2eyCyPVOYnKU1u64UtckfpxldZIDLQD5" \
...
200 OK
{
"uuid": "b0c7e012-eb5c-4a21-8f32-5b8e2b16e863",
"id": "123123",
"terminalId": "term1",
"transactionType": "SALE",
"approvedAmount": "10.00",
"status": "APPROVED",
"approvalCode": "ABC123",
"responseText": "Transaction Approved",
"cardType": "Visa",
"cardNumber": "4012XXXXXXXX1881",
"cardholderName": "John Doe",
"currency": "USD",
}
Step 4 (Optional) – Close the session and release the device
It is recommended to close the session when done processing transactions.
However, you can elect to keep the session open as long as you wish, and send as
many transactions as you wish. Just be advised that nobody else will be able to
use that terminal while your session is open (this includes other browser
windows on your same computer).
Example: Delete the session when done
$ curl https://api.payments.ac/v1/mycompany/terminals/term1/session \
-X DELETE \
-H "sessionKey: 2eyCyPVOYnKU1u64UtckfpxldZIDLQD5" \
...
204 NO CONTENT
Device-to-Cloud Methods
Retrieves the next transaction in the queue for the specified device. Only one
transaction will be returned.
Request
HTTP Method | URL |
---|---|
GET | /terminals/{id}/transaction |
The {id} parameter should be replaced with the id of the device you wish
to poll. Please see the device section for details on how to obtain the id.
HTTP Header | Options | Description |
---|---|---|
terminalKey | Required | the authentication key calculated for the terminal. May be substituted for adminKey |
timestamp | Optional | a timestamp for the current request. Any format acceptable provided it is unique. Used to calculate the hash for secured transactions |
hash | Optional | the hash of the sessionKey, timestamp, and secret key. |
Response
HTTP Status Response | Response Explained |
---|---|
200 OK | The transaction object in JSON format, which can optionally include a configuration object which contains configuration information for the current transaction. |
400 BAD REQUEST | Malformed request or missing required field. |
401 UNAUTHORIZED | sessionKey or adminKey missing or invalid. |
403 FORBIDDEN | Device is locked/in use by another host. (i.e. sessionKey mismatch) . |
404 NOT FOUND | There was no transaction found in the queue. This is a normal response if there are no transactions. |
Example: Polling for any transactions targeted for device 123456:
$ curl https://api.payments.ac/v1/mycompany/terminals/123456/transaction \
-X GET \
-H "sessionKey: 2eyCyPVOYnKU1u64UtckfpxldZIDLQD5"
...
200 OK
{
"uuid": "b0c7e012-eb5c-4a21-8f32-5b8e2b16e863",
"id": "88776655",
"terminalId": "123456",
"transactionType": "SALE",
"totalAmount": "10.00",
"currency": "USD",
"configuration": {
"enabledEntryModes": "SWIPE INSERT TAP",
"enableTip": "true",
}
(Note that the “configuration” object is optional and may not always be
present)
Clearing the Transaction Queue
Clears all pending transactions out of the queue. Typically not needed under
normal circumstances. Must be done by the administrator.
Request
Method | URL |
---|---|
DELETE | /terminals/{id}/transaction |
The {id} parameter should be replaced with the id of the device you wish
to poll. Please see the device section for details on how to obtain the id.
HTTP Header | Options | Description |
---|---|---|
adminKey | Required | the administrator authentication key |
timestamp | Optional | a timestamp for the current request. Any format acceptable provided it is unique. Used to calculate the hash for secured transactions. |
hash | Optional | the hash of the adminKey, timestamp, and secret key |
Response
Status | Response |
---|---|
200 OK | Indicates all transactions in the queue have been deleted. The count of transactions in the queue and their IDs will be provided in a JSON response. A count of 0 means there were no transactions in the queue to delete. { “count” : 2, “transactions” : [ “id1”, “id2” … ] } |
400 BAD REQUEST | Malformed request or missing required field |
401 UNAUTHORIZED | adminKey missing or invalid. Note the sessionKey is not sufficient for this command. |
Example: Clearing all queued transactions for device 123456
curl https://api.payments.ac/v1/mycompany/terminals/123456/transaction \
-X DELETE \
-H "AdminKey: tc8fpxldZIDLQD52eyCyPVOYnKU1u64U"
...
200 OK
{
"count": 2,
"transactions": ["12345", "23456"]
}
App-to-Cloud Methods
Sending a Transaction to a Device
Transactions are sent to a terminal by POSTing a transaction object to a
particular device’s transaction queue. The device will be able to poll for the
transaction and process it. Only the device provided by the id parameter will
be able to process the transaction.
Only one transaction can be posted to a device at any given time. If a
transaction already exists for that device, you will receive a 409 CONFLICT
response.
Note: Transactions cannot be modified once they’re queued. They must be deleted
and a new transaction run.
Request
Method | URL |
---|---|
POST | /terminals/{terminalId}/transaction |
The {terminalId} parameter should be replaced with the id of the device
you wish to poll. Please see the device section for details on how to obtain the
id.
The POST body should contain a transaction object with the id,
transactionType and totalAmount fields provided as a minimum. If you do
not provide an id in the transaction object, one will be automatically generated
and returned in the response. Please see the transaction object reference
for a list of acceptable fields.
Optionally, you can provide a configuration object that sets additional
parameters for this transaction (and only this transaction):
Example:
{
"transactionType": "SALE",
"id": "12345",
"totalAmount": "10.00",
"currency": "USD",
"callbackUrl": "https://www.yourdomaingoeshere.com/etc",
"configuration": {
"enableTip": "true",
}
}
Receiving notificaitons when the transaction is processed:
If your host is capable of receiving HTTP requests, you can optionally provide a
callbackUrl property that will be called by the terminal when transaction
processing is complete. Otherwise, you will need to poll for the transaction
status to get the response.
Note: If you provided the sessionKey as a URL parameter to the callbackUrl, you
will get all the transaction data necessary to generate a receipt. If you did
not provide a sessionKey, you will get the transaction’s id, status, and
responseText fields. You will need to query the transaction directly to get the
fields necessary to generate a receipt
HTTP Header | Option | Description |
---|---|---|
sessionKey | Required | the authentication key provided when the session was created. May be substituted for adminKey |
timestamp | Optional | a timestamp for the current request. Any format acceptable provided it is unique. Used to calculate the hash for secured transactions. |
hash | Optional | the hash of the sessionKey, timestamp, post data, and secret key. |
Response
Status | Response |
---|---|
201 CREATED | An echo of the transaction, with the status property set to QUEUED. |
400 BAD REQUEST | Malformed request or missing required field. |
401 UNAUTHORIZED | sessionKey or adminKey missing or invalid. |
403 FORBIDDEN | Device is locked/in use by another host. (i.e. sessionKey mismatch) |
409 CONFLICT | Another transaction is already queued for the device. |
Example: Queueing a transaction for device term1:
curl https://api.payments.ac/v1/mycompany/terminals/term1/transaction \
-X POST \
-H "sessionKey: 2eyCyPVOYnKU1u64UtckfpxldZIDLQD5" \
-d ' \
{
"transactionType": "SALE",
"id": "123123",
"totalAmount": "10.00",
"currency": "USD",
"callbackUrl": "https://yourhostgoeshere.com/etc", // Optional
"configuration": {
"enableTip": "true",
},
}
'
...
201 CREATED
{
"uuid": "b0c7e012-eb5c-4a21-8f32-5b8e2b16e863",
"id": "123123",
"transactionType": "SALE",
"terminalId": "term1",
"totalAmount": "10.00",
"currency": "USD",
"status": "QUEUED",
"callbackUrl": "https://yourhostgoeshere.com/etc",
"configuration": {
"enableTip": "true",
}
}
Polling for Transaction Completion
After your application queues a transaction, you can poll for its status by
requesting the transaction entity directly via its id parameter. The
?poll query parameter instructs the server to only return data if the
transaction has completed processing. This ensures the polling mechanism is
lightweight and keeps bandwidth to a minimum.
Note that the transaction polling is device-independent, and thus does not have
a device part of the URL
You will continue to get a 304 Not Modified response until the transaction
processes, in which case you will get a 200 OK plus the data necessary to
construct a receipt.
Note: To prevent server overload, please ensure the polling requests are three
seconds apart or greater.
Request
Method | URL |
---|---|
GET | /transactions/{id}?poll |
HTTP Header | Options | Description |
---|---|---|
sessionKey | Required | the authentication key provided when the session was created. May be substituted for adminKey. |
timestamp | Optional | a timestamp for the current request. Any format acceptable provided it is unique. Used to calculate the hash for secured transactions. |
hash | Optional | the hash of the sessionKey, timestamp, and secret key. |
Response
Status | Response |
---|---|
200 OK | The transaction object in JSON format. Note that unprocessed transactions will not have an approval status. If you want to see if the transaction has been processed, check for the existence of the Approved field. |
304 NOT MODIFIED | The transaction object exists but has not been processed by the terminal. Only returned if the ?poll query parameter was provided. |
400 BAD REQUEST | Malformed request or missing required field. |
401 UNAUTHORIZED | sessionKey or adminKey missing or invalid. |
403 FORBIDDEN | Device is locked/in use by another host. (i.e. sessionKey mismatch) |
404 NOT FOUND | There was no transaction with the provided id found. |
Example 1: Polling for a transaction that has not yet been completed by the
cardholder.
curl https://api.payments.ac/v1/mycompany/transactions/12345?poll \
-X GET \
-H "sessionKey: 2eyCyPVOYnKU1u64UtckfpxldZIDLQD5"
...
304 NOT MODIFIED
(Note that the Approved field is not yet present, so this transaction is still
queued and awaiting completion)
Example 2: Polling for a transaction that has been completed.
curl https://api.payments.ac/v1/mycompany/transactions/12345 \
-X GET \
-H "sessionKey: 2eyCyPVOYnKU1u64UtckfpxldZIDLQD5"
...
200 OK
{
"uuid": "b0c7e012-eb5c-4a21-8f32-5b8e2b16e863",
"approved": "true",
"approvalCode": "0AB2C3D4",
"status": "APPROVED",
"maskedPAN": "401288XXXXXX1881",
"cardholderName": "JOHN DOE",
"AID": "A0123450000000",
"transactionType": "SALE",
"id": "12345",
"terminalID": "term1",
"subtotal": "10.00",
"tip": "1.00",
"totalAmount": "11.00",
"currency": "USD",
}
(Note that the Approved field is now present, so this transaction has been
completed and the POS application software can move on)
Registers a new device and downloads the configuration file.
Request
Method | URL |
---|---|
POST | /terminals |
The {id} parameter should be replaced with the id of the device. Please
see the device section for details on how to obtain the id.
The body should contain the terminal object with a configuration. If no
configuration object is provided, the default configuration will be used.
HTTP Header | Options | Description |
---|---|---|
adminKey | Required | the administration key provided to the company |
timestamp | Optional | a timestamp for the current request. Any format acceptable provided it is unique. Used to calculate the hash for secured transactions. |
hash | Optional | the hash of the adminKey, timestamp, post data, and secret key. |
Response
Status | Response |
---|---|
201 CREATED | The id and uuid of the device. |
400 BAD REQUEST | Malformed request or missing required field. |
401 UNAUTHORIZED | adminKey missing or invalid |
409 CONFLICT | A device with the specified ID already exists. |
Example: Registering a new device with ID 123456
note, the terminal record you send is a bit different depending on the gateway you use. The examples below include those using the Worldnet Gateway, and those using the ProPay Gateway
curl https://api.payments.ac/v1/mycompany/terminals \
-X POST
-H "adminKey: 2eyCyPVOYnKU1u64UtckfpxldZIDLQD5"
-d ' \
{ \
"status": "ACTIVE", \
"id": "123456", \
"configuration": { \
"enabledPaymentMethods": "CREDIT DEBIT", \
"enabledEntryModes": "SWIPE INSERT TAP PINPAD", \
"supportedCurrencies": "ALL", \
"defaultCurrency": "USD", \
"allowDynamicCurrency": "true", \
"timeoutInterval": "30", \
"forceOnline": "false", \
"enableTip": "true", \
"enableCustomTip": "true", \
"tipOptions": [ \
{ \
"calculationMethod": "PERCENTAGE_SUBTOTAL", \
"displayName": "10%", \
"value": "10" \
}, \
{ \
"calculationMethod": "PERCENTAGE_SUBTOTAL", \
"displayName": "15%", \
"value": "15" \
}, \
{ \
"calculationMethod": "PERCENTAGE_SUBTOTAL", \
"displayName": "20%", \
"value": "20" \
} \
], \
"logging": { \
"remoteLoggingEnabled": true, \
"logLevel": "DEBUG" \
} \
} \
}'
...
201 CREATED
{
"uuid": "b0c7e012-eb5c-4a21-8f32-5b8e2b16e863",
"id": "123456",
}
curl https://api.payments.ac/v1/mycompany/terminals \
-X POST
-H "adminKey: 2eyCyPVOYnKU1u64UtckfpxldZIDLQD5"
-d ' \
{ \
"status": "ACTIVE", \
"id": "123456", \
"configuration": { \
"endpoint": { \
"provider": "propay", \
"xmlApiBaseUrl": "https://xmltest.propay.com/api/", \
"jsonApiBaseUrl": "https://mobileapitest.propay.com/merchant.svc/json/", \
"accountNum": "'.$propayAccountNum.'" \
}, \
"registerCardReaderWhenConnected": true, \
"cloudSyncEnabled": true, \
"terminalMode": "Cloud", \
"defaultCardReader": "Walker C2X", \
"defaultCurrency": "USD", \
"enabledEntryModes": "SWIPE INSERT TAP PINPAD", \
"supportedEntryModes": "SWIPE INSERT", \
"logLevel": "error", \
"logging": { \
"remoteLoggingEnabled": true, \
"logLevel": "DEBUG" \
} \
} \
} \
'
...
201 CREATED
{
"uuid": "b0c7e012-eb5c-4a21-8f32-5b8e2b16e863",
"id": "123456",
}
Updating a Terminal’s Configuration
Updates the configuration file for a specific device.
Request
Method | URL | |
---|---|---|
PUT | /terminals/{id] | Replaces the entire configuration |
PATCH | /terminals/{id} | Updates only the provided fields |
The {id} parameter should be replaced with the id of the device you wish
to poll. Please see the device section for details on how to obtain the id.
Note: The syntax follows the device registration command. Please see the
section above for details on how to implement this.
To replace the existing configuration with a new one, use the PUT command. To
update fields and ignore the other ones, use the PATCH command.
HTTP Header | Options | Description |
---|---|---|
adminKey | Required | the administration key provided to the company. |
timestamp | Optional | a timestamp for the current request. Any format acceptable provided it is unique. Used to calculate the hash for secured transactions. |
hash | Optional | the hash of the sessionKey, timestamp, data, and secret key. |
Response
Status | Response |
---|---|
200 OK | The uuid and deviceId to which the configuration was applied. |
400 BAD REQUEST | Malformed request or missing required field. |
401 UNAUTHORIZED | adminKey missing or invalid. |
403 FORBIDDEN | Device is locked/in use by another host. (i.e. a transaction is underway) |
404 NOT FOUND | There was no device found matching the provided ID |
Example 1: Replacing the configuration of device #123456 with a new
configuration
curl https://api.payments.ac/v1/mycompany/terminals/123456 \
-X PUT \
-H "adminKey: 2eyCyPVOYnKU1u64UtckfpxldZIDLQD5" \
-d '
{ \
"enabledPaymentMethods": "CREDIT DEBIT", \
"enabledEntryModes": "SWIPE INSERT TAP PINPAD", \
"defaultCurrency": "USD", \
"allowDynamicCurrency": "true", \
"timeoutInterval": "30", \
"forceOnline": "false", \
"enableTip": "true", \
"enableCustomTip": "true", \
"tipOptions": [ \
{
"calculationMethod": "PERCENTAGE_SUBTOTAL", \
"displayName": "10%", \
"value": "10" \
}, \
{ \
"calculationMethod": "PERCENTAGE_SUBTOTAL", \
"displayName": "15%", \
"value": "15" \
}, \
{ \
"calculationMethod": "PERCENTAGE_SUBTOTAL", \
"displayName": "20%", \
"value": "20" \
} \
] \
} \
'
...
200 OK
{
"uuid": "b0c7e012-eb5c-4a21-8f32-5b8e2b16e863",
"id": "123456",
}
Example 2: Updating only the tip options field of device #123456’s
configuration.
curl https://api.payments.ac/v1/mycompany/terminals/123456 \
-X PATCH \
-H "adminKey: 2eyCyPVOYnKU1u64UtckfpxldZIDLQD5" \
-d ' \
{
"tipOptions": [
{
"calculationMethod": "PERCENTAGE_SUBTOTAL",
"displayName": "15%",
"value": "15"
},
{
"calculationMethod": "PERCENTAGE_SUBTOTAL",
"displayName": "18%",
"value": "18"
},
{
"calculationMethod": "PERCENTAGE_SUBTOTAL",
"displayName": "20%",
"value": "20"
}
]
}
'
...
200 OK
{
"uuid": "b0c7e012-eb5c-4a21-8f32-5b8e2b16e863",
"id": "123456",
}
In order to send transactions to a device, a session must first be created. This
session ensures that the device terminal has downloaded the latest
configuration. Furthermore, a session locks the device to one particular host,
ensuring no other communication with the device will succeed. This prevents
other POS applications from heisting control of your terminal.
Conceptually, a session is usually equivalent to a worker’s shift. When logging
in, the session is created. When the worker completes their shift, they finish
the session and release the terminal for another worker to use.
When a session is created, it provides a sessionKey which must be used on all
subsequent requests to the device. Note: the universal adminKey can be
substituted for the auth key at any time.
Request
Method | Description |
---|---|
GET | /terminals/{id}/session |
The {id} parameter should be replaced with the id of the terminal you are
creating a session for.
Query Param | Options | Description |
---|---|---|
expires | Optional | A datetime at which time the session automatically expires and the session key can no longer be used. The date format can be either ticks (recommended) or the W3C standard date format, URL encoded - e.g. YYYY-MM-DDThh:mmTZD (eg 2017-07-16T19:20+01:00). For maximum accuracy, be sure to include the timezone of the origin. |
user | Optional | Specifies the user that created the session |
*HTTP Header | Options | Description |
---|---|---|
adminKey | Optional | the administration key provided during vendor setup |
timestamp | Optional | a timestamp for the current request. Any format acceptable provided it is unique. Used to calculate the hash for secured transactions. |
hash | Optional | the hash of the adminKey, timestamp, and secret key. |
Response
Status | Response |
---|---|
200 OK | The sessionKey and sessionKeyExpiry for the device. |
400 BAD REQUEST | Malformed request or missing required field. |
401 UNAUTHORIZED | sessionKey or adminKey missing or invalid |
403 FORBIDDEN | Device is locked/in use by another host. (i.e. sessionKey mismatch or session in progress) |
404 NOT FOUND | There was no matching device. |
Example: Creating a new session
curl https://api.payments.ac/v1/mycompany/terminals/12345/session?expiry=1528788893 \
-X GET \
-H "adminKey: 4UtckfpxldZIDLQD2eyCyPVOYnKU1u65"
...
200 OK
{
"deviceId": "12345",
"sessionKey": “2eyCyPVOYnKU1u64UtckfpxldZIDLQD5”
"sessionKeyExpiry": "2018-05-09 23:59:59",
"configuration": {
"enabledPaymentMethods": "CREDIT DEBIT",
"enabledEntryModes": "SWIPE INSERT TAP PINPAD",
"supportedCurrencies": "ALL",
"defaultCurrency": "USD",
"allowDynamicCurrency": "true",
"timeoutInterval": "30",
//etc...
}
}
After a session has been created, when the device is no longer in use, the
session should be closed to release the device to another host.
Once a session is closed, that sessionKey will no longer work. Subsequent
requests using that auth key will result in 401 errors.
Request
Method | URL |
---|---|
DELETE | /terminals/{id}/session |
The {id} parameter should be replaced with the id of the device you wish
to query. Please see the device section for details on how to obtain the id.
Query Parameters
To forcibly close a session, use the adminKey instead of the sessionKey.
HTTP Headers | Options | Description |
---|---|---|
sessionKey | Required | the sessionKey of the session you wish to close. |
timestamp | Optional | a timestamp for the current request. Any format acceptable provided it is unique. Used to calculate the hash for secured transactions. |
hash | Optional | the hash of the sessionKey, timestamp, and secret key. |
Response
Status | Response |
---|---|
204 NO_CONTENT | Session was deleted. |
400 BAD REQUEST | Malformed request or missing required field. |
401 UNAUTHORIZED | sessionKey or adminKey missing or invalid |
403 FORBIDDEN | Device is locked/in use by another host. (i.e. sessionKey mismatch or session in progress) |
404 NOT FOUND | There was no matching terminal or session. |
Example: Closing a new session
curl https://api.payments.ac/v1/mycompany/terminals/123456?close=true \
-X DELETE
...
204 NO CONTENT
Checking the Status of the Card Reader
To determine whether a card reader is connected to the terminal, simply issue A
GET request for the connectedreader
Once a session is closed, that sessionKey will no longer work. Subsequent
requests using that auth key will result in 401 errors.
Request
Method | URL |
---|---|
GET | /terminals/{id}/connectedreader |
The {id} parameter should be replaced with the id of the device you wish
to query. Please see the device section for details on how to obtain the id.
HTTP Header | Options | Description |
---|---|---|
sessionKey | Optional | the sessionKey of the session you are querying within. |
timestamp | Optional | a timestamp for the current request. Any format acceptable provided it is unique. Used to calculate the hash for secured transactions. |
hash | Optional | the hash of the sessionKey, timestamp, and secret key. |
Response
Status | Response |
---|---|
200 OK | A reader is connected. The response body will contain a JSON object describing the card reader. |
203 NON-AUTHORITATIVE INFORMATION | A reader is connected, but it is either unrecognized or unregistered. The serial number will be returned in the response. |
400 BAD REQUEST | Malformed request or missing required field. |
404 NOT FOUND | A reader is not connected to the terminal (note: it may be in sleep mode). |
All status codes are standard HTTP status codes. The below ones are used in this
API.
2XX - Success of some kind
3XX - Success of some kind, but further action is required
4XX - Error occurred in client’s part (note that 404 is a normal response in
some cases)
5XX - Error occurred in server’s part
200 | OK |
201 | Created |
202 | Accepted (Request accepted, and queued for execution) |
304 | Not Modified |
400 | Bad Request |
401 | Authentication failure |
403 | Forbidden |
404 | Resource not found |
405 | Method is not allowed |
409 | Conflict |
412 | Precondition Failed |
413 | Request Entity Too Large |
500 | Internal Server Error |
501 | Not Implemented |
503 | Service Unavailable |
====================================
Appendix A: The configuration object
The following are a list of default properties for the configuration object in
the stock AnyPay implementation. You can add any other properties not in this
list.
{
"configuration": {
"allowAnonymousUsers": true,
"allowClearTransactions": true,
"allowClearTransactionsEditable": true,
"allowPartialAuthorizations": true,
"allowPartialRefunds": true,
"allowReferencedRefunds": true,
"allowReferencedRefundsEditable": true,
"allowUnreferencedRefunds": true,
"allowUnreferencedRefundsEditable": true,
"chequeColorFormat": "Color",
"chequeColorFormatEditable": true,
"chequeFileFormat": "PNG",
"chequeFileFormatEditable": true,
"customFieldsEnabled": false,
"customFieldsEnabledEditable": false,
"defaultCardReader": "Walker 2.0 BT",
"defaultCardReaderEditable": true,
"defaultCurrency": "USD",
"driversLicenseRequired": false,
"driversLicenseRequiredEditable": false,
"driversLicenseStateRequired": false,
"driversLicenseStateRequiredEditable": false,
"enableAvs": true,
"enableCvv": true,
"enableFirmwareUpdate": false,
"enableForgotPasswordUrl": false,
"enabledCurrency": "USD",
"enabledCurrencyEditable": false,
"enabledEntryModes": "SWIPE INSERT TAP PINPAD",
"enabledEntryModesEditable": false,
"enabledPaymentMethods": "CREDIT DEBIT",
"enabledPaymentMethodsEditable": true,
"enabledReceiptOptions": "Default",
"enabledReceiptOptionsEditable": false,
"allowAdvancedSettings": false,
"enforce": true,
"enforceFirmwareCompliance": false,
"forgotPasswordUrl": "https://payments.anywherecommerce.com/merchant/selfcare",
"geofencingEnabled": false,
"geofencingEnabledEditable": false,
"geolocationEnabled": true,
"geolocationEnabledEditable": false,
"id": "default",
"requireAvs": false,
"requireCardPresentRefunds": false,
"requireCardPresentSales": false,
"requireCvv": false,
"requireTermsAndConditions": false,
"sessionTimeoutEnabled": false,
"sessionTimeoutEnabledEditable": true,
"sessionTimeoutInterval": "30",
"supportedCurrencies": "ALL",
"supportedEntryModes": "SWIPE INSERT TAP PINPAD",
"supportedPaymentMethods": "CREDIT DEBIT CHEQUE",
"supportedReceiptOptions": "Default",
"surchargeEnabled": false,
"surchargeEnabledEditable": true,
"surchargeOptions": [
{
"calculationMethod": "PERCENTAGE_SUBTOTAL",
"displayName": "% of Subtotal",
"rate": {
"decimalPlaces": 3,
"isCurrency": false,
"isPercentage": true,
"value": 0.000
},
"name": "% of Subtotal",
"type": "fee"
},
{
"calculationMethod": "PERCENTAGE_TOTAL",
"displayName": "% of Total",
"rate": {
"decimalPlaces": 3,
"isCurrency": false,
"isPercentage": true,
"value": 0.000
},
"name": "% of Total",
"type": "fee"
},
{
"calculationMethod": "FLAT_RATE",
"displayName": "Fixed",
"rate": {
"decimalPlaces": 2,
"isCurrency": false,
"isPercentage": false,
"value": 0.00
},
"amount": {
"decimalPlaces": 2,
"isCurrency": false,
"isPercentage": false,
"value": 0.00
},
"name": "Fixed",
"type": "fee"
}
],
"surchargeOptionsEditable": true,
"suspendAndResumeEnabled": false,
"suspendAndResumeEnabledEditable": false,
"suspendAndResumeSupportedEntryModes": "SWIPE PINPAD",
"suspendAndResumeSupportedPaymentMethods": "CREDIT",
"taxEnabled": true,
"taxEnabledEditable": true,
"taxRates": [
{
"calculationMethod": "PERCENTAGE_SUBTOTAL",
"displayName": "None",
"rate": {
"decimalPlaces": 3,
"isCurrency": false,
"isPercentage": true,
"value": 0.000
},
"name": "None",
"type": "tax"
}
],
"taxRatesEditable": true,
"terminalEnabled": true,
"termsAndConditionsUrl": "",
"timestamp": "2018-01-01",
"tipEnabled": true,
"tipEnabledEditable": true,
"tipOptions": [
{
"calculationMethod": "PERCENTAGE_SUBTOTAL",
"displayName": "Tip",
"rate": {
"decimalPlaces": 0,
"isCurrency": false,
"isPercentage": true,
"value": 10
},
"name": "Tip",
"type": "tip"
},
{
"calculationMethod": "PERCENTAGE_SUBTOTAL",
"displayName": "Tip",
"rate": {
"decimalPlaces": 0,
"isCurrency": false,
"isPercentage": true,
"value": 15
},
"name": "Tip",
"type": "tip"
},
{
"calculationMethod": "PERCENTAGE_SUBTOTAL",
"displayName": "Tip",
"rate": {
"decimalPlaces": 0,
"isCurrency": false,
"isPercentage": true,
"value": 20
},
"name": "Tip",
"type": "tip"
}
],
"tipOptionsEditable": true,
"transactionReportingMode": "ALL_USERS",
"transactionReportingModeEditable": true,
"unreferencedRefundLimit": 99999.0,
"userAuthenticationMode": "DEFER_UNTIL_REQUIRED",
"verifyCardPresentForKeyedTransactions": false,
"version": "default"
}
}
==================================
Appendix B: The transaction object
The following are a list of reserved properties for the transaction object in
the stock AnyPay implementation. You can add any other properties not in this
list.
{
"id": "123123",
"uuid": "0587FC91-B8E0-4D16-AF8A-9BCA1DB39806",
"status": "ACTIVE",
"terminalID": "term1",
"parentID": "54321",
"subtotal": "10.00",
"taxes": "1.00",
"tip": "1.00",
"totalAmount": "22.00",
"currency": "USD",
"notes": "internal notes",
"description": "external description",
"orderID": "orderIdGoesHere",
"operator": "username",
"paymentID": "8888",
"cardholderName": "JOHN DOE",
"cardExpiryMonth": "10",
"cardExpiryYear": "22",
"maskedPAN": "4012XXXXXXXX1881",
"cardNumber": "401288888881881",
"cvv2": "999",
"accountType": "SAVINGS",
"batchStatus": "",
"entryMode": "TAP",
"cardType": "VISA",
"approvedAmount": "22.00",
"address": "123 Main Street",
"postalCode": "93060",
"approvalCode": "ABC123",
"approved": "true",
"responseText": "Response from Gateway",
"warnings": "Any Warnings",
"onlineTransactionEmvPayload": "",
"offlineTransactionEmvPayload": "",
"selectedApplication": "",
"aid": "",
"ksn": "",
"encTrack1": "",
"encTrack2": "",
"encTrack3": "",
"error": "Error message if something failed",
"gatewayResponse": {},
"terminalResponse": {},
"geolocationData": {
"latitude": "31.761878",
"longitude": "-106.485022",
"description": "El Paso, TX"
},
"configuration": {
"supportedEntryModes": "SWIPE INSERT TAP PINPAD",
"supportedPaymentMethods": "CREDIT DEBIT"
},
"dateCreated": "2017-10-14T18:00:23"
}
Updated about 2 years ago