# Home

## Embedded Payments Starts Here

Embedded payments are at the heart of everything we do, enabling ISVs and SaaS providers to integrate tailored payment solutions directly and elegantly into their platforms.

<figure><img src="/files/ljs2AErnp7qNeb7jbwzM" alt=""><figcaption></figcaption></figure>

We understand the critical nature of payment processing and are committed to maintaining seamless operations. Our dedicated support team is available around the clock to provide immediate assistance and resolve any issues, ensuring your business can operate without disruption.

{% content-ref url="/pages/kj6DExa5bIpmWMzygpvr" %}
[Customer Support](/help/customer-support)
{% endcontent-ref %}

### Ease of integration

Number prioritizes straightforward and efficient integration. Check our quickstart guide and integration checklist to see how you can get started.

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Developer Quickstart</strong></td><td><a href="/files/zfkzX1NGLN8O1YKFS5rH">/files/zfkzX1NGLN8O1YKFS5rH</a></td><td><a href="/pages/1p6qR2WVeUcz3P2yasEV">/pages/1p6qR2WVeUcz3P2yasEV</a></td></tr><tr><td><strong>Integration Checklist</strong></td><td><a href="/files/Vm0Uu4nqGfU7ocGqssHO">/files/Vm0Uu4nqGfU7ocGqssHO</a></td><td><a href="/pages/8YzdX7McGPhcNg2RjBrX">/pages/8YzdX7McGPhcNg2RjBrX</a></td></tr></tbody></table>

### Integrate Number

Use our API, PayForm, Verifone service or mobile SDK to integrate Number into your system.

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>REST API Reference</strong></td><td><a href="/files/pRbjTO5bQP7eItTNkvSK">/files/pRbjTO5bQP7eItTNkvSK</a></td><td><a href="/pages/v6Vkw2Uiz3OiJVh3EcKP">/pages/v6Vkw2Uiz3OiJVh3EcKP</a></td></tr><tr><td><strong>Verifone Win Service &#x26; SDK</strong></td><td><a href="/files/K5DA4tqEAkhKngwhiEIk">/files/K5DA4tqEAkhKngwhiEIk</a></td><td><a href="/pages/BK3mUZUmMtSSNUopk6Wy">/pages/BK3mUZUmMtSSNUopk6Wy</a></td></tr><tr><td><strong>Android Mobile SDK</strong></td><td><a href="/files/yjxrXtPVCJB9MOgZtx13">/files/yjxrXtPVCJB9MOgZtx13</a></td><td><a href="/pages/iE4JAbx6RM93pLM1UEuz">/pages/iE4JAbx6RM93pLM1UEuz</a></td></tr><tr><td> <strong>iOS Mobile SDK</strong></td><td><a href="/files/AbJQTqZoNqgUjAzIdDcj">/files/AbJQTqZoNqgUjAzIdDcj</a></td><td><a href="/pages/UDfr2U9uWMEiomNiA642">/pages/UDfr2U9uWMEiomNiA642</a></td></tr></tbody></table>

### Serv﻿ices

Our comprehensive range of services is designed to meet various needs, ensuring users can find tailored solutions for every requirement.

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>REST API</strong></td><td><a href="/pages/g0s2SOjVSbGR7BXOxF78">/pages/g0s2SOjVSbGR7BXOxF78</a></td></tr><tr><td><strong>SOAP API</strong></td><td><a href="/pages/7X3I8lD6ps3Qz9vF1exm">/pages/7X3I8lD6ps3Qz9vF1exm</a></td></tr><tr><td><strong>Android Mobile SDK</strong></td><td><a href="/pages/iE4JAbx6RM93pLM1UEuz">/pages/iE4JAbx6RM93pLM1UEuz</a></td></tr><tr><td> <strong>iOS Mobile SDK</strong></td><td><a href="/pages/UDfr2U9uWMEiomNiA642">/pages/UDfr2U9uWMEiomNiA642</a></td></tr><tr><td><strong>PayForm Widget</strong></td><td><a href="/pages/lex90vp462I6tTL2RJvc">/pages/lex90vp462I6tTL2RJvc</a></td></tr><tr><td><strong>Verifone Win Service &#x26; SDK</strong></td><td><a href="/pages/BK3mUZUmMtSSNUopk6Wy">/pages/BK3mUZUmMtSSNUopk6Wy</a></td></tr><tr><td><strong>Virtual Terminal</strong></td><td><a href="/pages/UOlTsAJ4SQUaN7oY9Csw">/pages/UOlTsAJ4SQUaN7oY9Csw</a></td></tr><tr><td><strong>Custom Desktop Application</strong></td><td><a href="/pages/0GtA9h1fCfCkWInDaiv0#our-custom-desktop-application">/pages/0GtA9h1fCfCkWInDaiv0#our-custom-desktop-application</a></td></tr></tbody></table>

{% hint style="info" %}
Visit our [Services and Supported Features](/readme/services-and-supported-features) page to compare our services and learn more about the supported features and payment methods.
{% endhint %}

### Supported features

Our diverse payment features include:

* Online payments
* Card present payments
* Storing a card on file
* Surcharge payments
* Recurring payments
* Authorizing payments
* Voiding (reversals)
* Crediting (refunds)
* Settlements
* Reporting
* Manual keyed transactions

### Get your business started

Adoption is crucial for maximizing the benefits of any payment solution, and Number is designed with this in mind. Our platform emphasizes easy user adoption and streamlined customer onboarding, ensuring a smooth transition for both end-users and merchants.

See how you can [Get Your Business Started](/readme/get-your-business-started).


# Get Your Business Started

Find out how long it takes to get started with Number

At Number, we know that running a business means juggling countless tasks. That's why we've made our payment integration as simple and efficient as possible, so you can focus on what really matters—growing your business.

### Implementation timeline

Before you start using our services, you might want to gain more insight into the work required to integrate. We've prepared a rough implementation timeline to help guide you in your decision-making.

{% hint style="info" %}
You can find a detailed integration guide by visiting the [Integration Checklist](/documentation/getting-started/integration-checklist) section.
{% endhint %}

To get your business started with Number, follow these general steps for implementation:

<table><thead><tr><th width="260">Phase</th><th width="127">Duration</th><th>Task</th></tr></thead><tbody><tr><td>Obtain Sandbox credentials</td><td>1 day</td><td><a href="/pages/kj6DExa5bIpmWMzygpvr">Contact the Number team</a> to obtain sandbox credentials for integration testing.</td></tr><tr><td>Choose integration options</td><td>1-2 days</td><td>Decide on <a href="/pages/0GtA9h1fCfCkWInDaiv0">integration options</a> that best suit your business needs.</td></tr><tr><td>Develop a payment workflow</td><td>1-2 days</td><td>Outline all interaction points in your current workflow where payments might be collected.</td></tr><tr><td>Develop your integration</td><td>1-2 weeks<br><br><br>1 week<br>(optional)<br><br><br>2-3 weeks<br><br><br><br>1 week<br><br></td><td>Create the front-end components necessary for user interactions.<br><br>If you want to support Verifone card chip readers, implement EMV functionality provided by our Windows service or SDK.<br><br>Write the server-side logic to handle payment processing, invoking our services. Develop data management.<br><br>Setup logging according to our guides. Consult us to set up reporting and reconciliation processes.</td></tr><tr><td>Test your integration</td><td>1-2 weeks</td><td>Conduct unit testing to validate the integration functionality before going live.</td></tr><tr><td>Number inspection</td><td>1-2 meetings</td><td>The Number team always inspects our clients workflows prior to going live.</td></tr><tr><td>Go live</td><td>1 day</td><td>Switch to the production environment and update configuration as necessary.</td></tr><tr><td><strong>Total integration tme</strong></td><td><strong>6-10 weeks</strong></td><td><strong>If you have multiple teams working on developing the integration, it can all be completed in as little as four weeks.</strong></td></tr></tbody></table>


# Services and Supported Features

A short compilation of Number services and supported features

### REST API

**Characteristics:** \
Enables integration of payment systems with external applications, allowing for full automation.

**Use Cases:**\
Perfect for companies developing custom applications with embedded payment functionality that are adaptable to various programming environments.

{% hint style="info" %}
To learn how to use the API, see the [REST API](/documentation/getting-started/integration-options/rest-api) integration guide.
{% endhint %}

**Supported features:**

| Feature                            | Description                                                                                                                                                                                                            |
| ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Online payments                    | Enables businesses to accept payments through their web applications or platforms.                                                                                                                                     |
| Surcharge payments                 | Allows businesses to add a surcharge or an extra fee to the transaction amount.                                                                                                                                        |
| Store card on file                 | Facilitates storing a customer's card details securely for future transactions.                                                                                                                                        |
| Recurring payments (payment plans) | Supports setting up automatic, recurring transactions, ideal for subscriptions or installment plans.                                                                                                                   |
| Authorizing payments               | Authorizes transactions and verifies funds with the card issuer.                                                                                                                                                       |
| Voiding                            | Cancels authorized transactions pre-settlement, stopping fund transfers.                                                                                                                                               |
| Crediting (refunds)                | <p>Return funds to a customer's account after a transaction has been completed. </p><p></p><p>Occurs when a customer returns a product or disputes a charge, and the merchant agrees to reimburse the amount paid.</p> |
| Settlements                        | Finalizing a transaction by transferring funds from the buyer to the seller.                                                                                                                                           |
| Reporting                          | Involves generating summaries and analyses of transaction data to help merchants track financial activities, manage cash flow, and ensure compliance.                                                                  |

***

### Android/iOS Mobile SDK

**Characteristics:** \
Provides tools and libraries for integrating payment processing into mobile apps, with pre-built UI components and security features for Android and iOS.

**Use Cases:**\
Ideal for developers aiming to offer seamless in-app payments, especially in e-commerce and subscription-based mobile applications.

{% hint style="info" %}
To learn to use mobile SDKs, see the [Android SDK](/documentation/getting-started/integration-options/android-sdk) and [iOS SDK](/documentation/getting-started/integration-options/ios-sdk) integration guides.
{% endhint %}

**Supported features:**

| Feature                                               | Description                                                                                                                    |
| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| Online payments                                       | Processes payments without needing a physical point-of-sale system, using a mobile interface (card not present transactions).  |
| Surcharge payments                                    | Allows businesses to add a surcharge or an extra fee to the transaction amount.                                                |
| Store card on file (after collecting cardholder data) | Allows merchants to securely store and reuse cardholder information for future transactions if the user saves their card data. |

***

### PayForm

**Characteristics:** \
A plug-and-play payment form that can be easily embedded on websites without advanced technical setup. Requires simple API integration to initiate the form.

**Use Cases:**\
Ideal for businesses seeking a quick, simple way to accept online payments without extensive integration. Can be rendered in IFrame or as a top-level page.

{% hint style="info" %}
To learn to use the PayForm, see the [PayForm](/documentation/getting-started/integration-options/payform) configuration guide.
{% endhint %}

**Supported features:**

| Feature                                               | Description                                                                                                                                |
| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| Online payments                                       | Provides a quick and simple way to accept payments directly through a highly configurable embedded form which can be used on your website. |
| Store card on file (after collecting cardholder data) | Allows merchants to securely store and reuse cardholder information for future transactions.                                               |
| Surcharge payments                                    | Allows businesses to add a surcharge or an extra fee to the transaction amount.                                                            |
| Multiple payment types                                | PayForm supports a range of payment options, including credit cards, ACH, Apple Pay, and Google Pay.                                       |

***

### Virtual Terminal

**Characteristics:** \
Web application that provides comprehensive credit card processing functionality, including authorizations, credits, voids, and reporting, while supporting card swipers and chip readers for secure transactions.

**Use Cases:**\
It is ideal for in-person/card-present transactions, allowing merchants to efficiently process payments directly at the point of sale with the Windows service installed.&#x20;

{% hint style="info" %}
To learn to use the Virtual Terminal, see the [Virtual Terminal](/documentation/getting-started/integration-options/virtual-terminal) user guide.
{% endhint %}

{% hint style="success" %}
You can also use our **custom desktop application** as an alternative to the Virtual Terminal. The desktop application supports much of the same features. &#x20;

It can be installed on user's computer, and it's beneficial for businesses who would rather not log into a browser application.

To learn more about our custom desktop application, [contact the Number support team](/help/customer-support).
{% endhint %}

**Supported features:**

| Feature                             | Description                                                                                                                                                                                                            |
| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Online payments                     | Processes payments without needing a physical point-of-sale system, using a web interface.                                                                                                                             |
| Card present                        | Accepts card present payments using Verifone or a different USB card reader.                                                                                                                                           |
| Manual entry                        | Accepts payments by manually entering card details.                                                                                                                                                                    |
| Surcharge payments                  | Allows businesses to add a surcharge or an extra fee to the transaction amount.                                                                                                                                        |
| Store card on file (annual consent) | Allows storing customer card information with their consent for recurring use                                                                                                                                          |
| Recurring payments (payment plans)  | Facilitates the automated scheduling of regular payments over time.                                                                                                                                                    |
| Authorizing payments                | Verifies cardholder information and checks funds to approve transactions securely.                                                                                                                                     |
| Voiding                             | Cancels authorized transactions pre-settlement, stopping fund transfers.                                                                                                                                               |
| Crediting (refunds)                 | <p>Return funds to a customer's account after a transaction has been completed. </p><p></p><p>Occurs when a customer returns a product or disputes a charge, and the merchant agrees to reimburse the amount paid.</p> |
| Settlements                         | Finalizing a transaction by transferring funds from the buyer to the seller.                                                                                                                                           |
| Reporting                           | Involves generating summaries and analyses of transaction data to help merchants track financial activities, manage cash flow, and ensure compliance.                                                                  |

***

### Win Service and DLL

**Characteristics:** \
Used by your application and a Verifone card reader to integrate Number payment functions.

**Use Cases:**\
For developers integrating payment functionalities into card readers and custom applications.

{% hint style="info" %}
Learn more about integrating with Verifone in the [Verifone](/documentation/getting-started/integration-options/verifone) integration guide.
{% endhint %}

**Supported features:**

| Functionality                                 | Description                                                                                                              |
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| Card present (via Verifone device)            | Processes physical or keyed card transactions using Verifone devices with the Windows service running in the background. |
| Online payments (via browser-based interface) | Supports transaction processing through a web interface, utilizing the Windows service for continuous operation.         |
| Manually keyed transactions                   | Supports chip/tap/swipe and keyed card data.                                                                             |
| Surcharge payments                            | Allows businesses to add a surcharge or an extra fee to the transaction amount.                                          |
| Authorizing payments                          | Verifies cardholder information and checks funds to approve transactions securely.                                       |
| Store card on file                            | Allows secure storage of card details for future transactions.                                                           |
| Recurring payments (automated payment plans)  | Automate payment plans.                                                                                                  |


# Developer Quickstart

Partnership isn’t just a word—it’s how we power payments.

<figure><img src="/files/NoiZOdfSMarFJ7vyHs1E" alt=""><figcaption></figcaption></figure>

Integrating payment services into your system is a complex task, and it grows all the more complex  the more ideas and customization needs you have. We want to make that process as easy to follow as possible—from one developer to another.&#x20;

{% hint style="info" %}
See our [Vocabulary](/documentation/resources/vocabulary) to help you get started if you are new to payment services.
{% endhint %}

We've prepared this quickstart section to help you get started. We recommend going through all of the sections in order and then moving onto the [Getting Started](/documentation/getting-started) section to find out which integration option makes the most sense for you and how to implement it in your system.

Now, if you are ready to explore...

{% content-ref url="/pages/eEYRporM50P0fxqY53Vh" %}
[Authentication](/documentation/developer-quickstart/authentication)
{% endcontent-ref %}


# Authentication

A quickstart guide to authenticating with Number services

<figure><img src="/files/5jugAlcLtVwWXt9q2k1b" alt=""><figcaption></figcaption></figure>

## Basics

To authenticate to our services, depending on your integration of choice, you might need the following:

{% stepper %}
{% step %}

#### An account code and token

Using your unique key representing the Number account and the token generated from the Client Admin Portal, you'll be able to authenticate to the REST API.&#x20;
{% endstep %}

{% step %}

#### API key

When initializing either of the mobile SDKs, you'll need an API key provided by Number.&#x20;
{% endstep %}

{% step %}

#### HMAC secret

If you are PCI Compliant and want to use our REST API to collect cardholder data, some endpoints will require you to append additional data to the session header. You'll be able to generate this header using an HMAC secret provided by us.
{% endstep %}

{% step %}

#### Username and password

When logging into the Virtual Terminal you'll need a username and password. When logging into the Client Admin Portal this will also require two-factor authentication using a text message to your mobile phone.
{% endstep %}
{% endstepper %}

***

## REST API

Here's a basic step-by-step guide on how to authenticate with our APIs:

{% stepper %}
{% step %}

#### Find your account code

This will be provided by Number when you create an account with us.
{% endstep %}

{% step %}

#### Create a new token

Use the Client Admin Portal to create a token. If you don't have access to the Client Admin Portal, contact the [Number support team](https://number-development-portal.gitbook.io/number-development-portal/kmuHipzA8ZCcM2LLePFe/help/customer-support).
{% endstep %}

{% step %}

#### Send a request to authenticate and store the session key

You'll need to provide your account code as `AcctCode` and token as `Token`.

REST API: [/pages/fsxIL8vsPTRNOus4JvYk#apicardprocrest-v1.0.0-authenticate](https://docs.number.tech/documentation/developer-quickstart/pages/fsxIL8vsPTRNOus4JvYk#apicardprocrest-v1.0.0-authenticate "mention")

Handle the response and store the `SessKey` value.
{% endstep %}

{% step %}

#### Include the session key in your requests

**If you don't encounter a PCI Level 1 compliance warning in API reference page:**

For REST API, include a `SessKey` header with the stored value.

**In case you encounter the compliance warning in API reference page, as seen below:**

You'll need to prepare a secured header and use its value in place of the original `SessKey`.&#x20;

If the HMAC secret was not provided to you previously or you don't know how to find the value of `UserID` or `DeviceID`, [contact Number](/help/customer-support).&#x20;

The format for the key is as follows: [`SessKey`](#user-content-fn-1)[^1]\_[`Epoch`](#user-content-fn-2)[^2]\_[`DeviceID`](#user-content-fn-3)[^3]\_[`Hash`](#user-content-fn-4)[^4]. Include this key in the same way as you would include the `SessKey` (see case above).
{% endstep %}
{% endstepper %}

{% hint style="info" %}
If you want to read more about authentication, see the [Authentication](/documentation/getting-started/basics/authentication) guide&#x20;
{% endhint %}

***

## Android and iOS SDK

Authenticating with the mobile SDKs is very simple. [Contact Number](/help/customer-support) to get an API key, HMAC secret, and an optional Sentry DSN.&#x20;

After installing the SDK of your choice, you can configure and initialize the `EasyPay` class.

#### Android

#### iOS

***

## Virtual Terminal

To log in and use the features of Virtual Terminal, you'll first need to create accounts for your users through the Client Admin Portal.&#x20;

To access the portal, [Contact Number](/help/customer-support). You will be asked to provide the full name, e-mail address, and cell phone number for every individual you wish to have access to the portal. Those individuals will then be able to enter the portal and create new Virtual Terminal users through the portal by entering *Manage Accounts* > *Users* through the navigation on the left.

Now, those users will be able to access the Virtual Terminal using the link below.

[^1]: This key is generated upon successful authentication.

[^2]: Seconds since 1970 UTC

[^3]: UserID or DeviceID

[^4]: The HMAC hash created using the secret value which we will provide.


# Card Sales and Consent

Learn to make credit card sales and collect consent with Number

<figure><img src="/files/IWzHSHa1HOEl9QUoVhqn" alt=""><figcaption></figcaption></figure>

## Card present sales and consent

To make sales or collect consent when a card is present using Number, you have several options:

{% stepper %}
{% step %}

#### **Integration with a Verifone card reader**

You can use Verifone card readers. They are secure devices that connect to your computer via USB. They encrypt cardholder data during transmission to ensure security.
{% endstep %}

{% step %}

#### USB card reader through the Virtual Terminal or our desktop app

When you have a USB card reader connected to your machine, you can log into the Virtual Terminal to make card present sales and to collect consent.&#x20;

We also have a custom desktop application which can be convenient in an office setting to collect card present payments. It offers similar functionality to the Virtual Terminal.
{% endstep %}

{% step %}

#### Custom integration with our REST API

Our REST API offers methods for handling card present transactions.

If you have your own PCI level one compliance program, you may write your own custom code calling our APIs to collect card present payments and consent. You can read more about PCI compliance in the short [Integration Options](/documentation/getting-started/integration-options#pci-compliance) section of our [Integration Options](/documentation/getting-started/integration-options) guide.
{% endstep %}
{% endstepper %}

### Verifone integration

There are a few approaches to integration, You can either use the browser-based interface option or the Desktop integration with SDK .

{% hint style="info" %}
For an in-depth tutorial on how to integrate and use your Verifone card reader with Number, see our [Verifone](/documentation/getting-started/integration-options/verifone) integration guide.
{% endhint %}

Before you start, you'll need to download the Verifone Windows service to your machine, connect your card reader device to a free USB port, allow it to initialize, extract the archive with the service and run the EXE as an administrator. After the installation is complete, reboot the system.

You can issue commands to the service by calling `https://localhost:8031` from your website.&#x20;

#### Verifone card present sales

Here's an simplified example of how you can invoke the service for a card present sale:

#### Verifone card present annual consent

Here's an simplified example of how you can invoke the service to collect annual consent:

### Virtual Terminal or desktop application

When you want to use your Verifone with the Virtual Terminal, you have to first install the very same Windows service that is used when doing a Verifone browser-based integration. After installation, [contact the Number support team](/help/customer-support) to get the card reader features activated.

{% hint style="info" %}
To learn more about using the Virtual Terminal, see the [Virtual Terminal](/documentation/getting-started/integration-options/virtual-terminal) user guide.
{% endhint %}

{% hint style="info" %}
Read more about using our custom desktop application for sales in the [Integration Options](/documentation/getting-started/integration-options) guide or [contact Number](/help/customer-support) to get access.
{% endhint %}

#### Virtual Terminal card present sales

When you visit the Virtual Terminal, log in and expand *Credit Cards* in the navigation on the left. You'll see options for a sale, an EMV sale, authorization, forced auth, and adjustments.&#x20;

<figure><img src="/files/GpNb0qFfWoSUHbMEWiRP" alt=""><figcaption></figcaption></figure>

As long as your USB card reader is connected to your machine, it will seamlessly integrate with the Virtual Terminal for card present transactions.

#### Virtual Terminal card present consent

When you visit the Virtual Terminal, log in and expand *Consents* in the navigation on the left. You'll see options for annual consent, EMV annual consent, and one-time consent. You can also expand the *Recurring* tab to find options to create recurring consent, EMV recurring consent, and subscription consent.

<figure><img src="/files/E3gPTg48H1AagD4eiva1" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/cNZBGJ5T2Ib3ZlRDh6S8" alt=""><figcaption></figcaption></figure>

As long as your USB card reader is connected to your machine, it will seamlessly integrate with the Virtual Terminal for card present transactions.

### REST API integration

Our APIs are useful for any Integration as you can apply a credit, void, query, charge a stored card etc. For integrators who are PCI Level one compliant you may also pass cardholder data directly through the API. Most integrations will use our PayForms to collect Cardholder data while the API will be used for all remaining activity.

{% hint style="info" %}
To learn more about our APIs, see the [REST API](/documentation/getting-started/integration-options/rest-api) integration guide.
{% endhint %}

When you scan the credit card and collect the track data alongside the other payment details, if using the REST API, prepare the HMAC secured header like shown in [Authentication](/documentation/developer-quickstart/authentication) quickstart guide, and encrypt the card number using our RSA certificate.&#x20;

Follow the instructions in the API reference to prepare and handle the request.

#### API card present sales

You can use the following API operations:

* For the REST API, use [/pages/w4UMtcF7UfD7pNPTiZF7#apicardprocrest-v1.0.0-cardsale-cardpresent](https://docs.number.tech/documentation/developer-quickstart/pages/w4UMtcF7UfD7pNPTiZF7#apicardprocrest-v1.0.0-cardsale-cardpresent "mention")

#### API card present consent

You can use the following API operations:

* For the REST API, you can use [/pages/2Pdm0t88TPo3URCjHoXS#apicardprocrest-v1.0.0-consentannual-create\_cp](https://docs.number.tech/documentation/developer-quickstart/pages/2Pdm0t88TPo3URCjHoXS#apicardprocrest-v1.0.0-consentannual-create_cp "mention") and [/pages/YBJbuCVqQbR5pZ3WsIkL#apicardprocrest-v1.0.0-consentrecurring-create](https://docs.number.tech/documentation/developer-quickstart/pages/YBJbuCVqQbR5pZ3WsIkL#apicardprocrest-v1.0.0-consentrecurring-create "mention").

***

## Manual card sales and consent

To make credit card sales and collect consent using Number when you want to enter the card details manually, you have the following options:

{% stepper %}
{% step %}

#### PayForm widget

You can configure and customize our PayForm widget and redirect your users to a separate page with the form or embed it as an IFrame in your existing web application.
{% endstep %}

{% step %}

#### Virtual Terminal or our desktop application

The Virtual Terminal website allows you to handle manual card sales and consent collection by default. This approach requires no coding and is perfect for a physical point-of-sale.

We also have a custom desktop application which can be convenient way to collect manual card payments and consent. It offers much of the same functionality as the Virtual Terminal.
{% endstep %}

{% step %}

#### Android or iOS SDK integration

If you have a mobile application that needs to handle payments and consent, our SDKs implement secure forms which can collect cardholder information from your users.
{% endstep %}

{% step %}

#### REST API integration

For more customization, you can call our API for sales and consent.

If you have your own PCI level one compliance program, you may write your own custom code calling our API to collect manual card payments and consent. You can read more about PCI compliance in the short [Integration Options](/documentation/getting-started/integration-options#pci-compliance) section of our integration guide.
{% endstep %}
{% endstepper %}

### PayForm widget

The PayForm is designed to be a highly flexible and secure payment form for your users. To start collecting payments and consent with the PayForm, you'll want to use our builder tool for configuration, then our REST API to generate a payment URL.&#x20;

{% hint style="info" %}
Learn more about how to configure and use the PayForm in the [PayForm](/documentation/getting-started/integration-options/payform) guide.
{% endhint %}

You can read about configuration specifics in the [PayForm](/documentation/getting-started/integration-options/payform#payform-builder) section of our full PayForm guide. For the purpose of this tutorial, you can follow the example below; we'll briefly explain each configuration step.&#x20;

#### PayForm manual card sale

In the example below, the PayForm has been setup for **an instant card payment**.&#x20;

<figure><img src="/files/l1hQPjPmKmQKS2jcrclL" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/qoj0lbPFb3JTuoYGzEyR" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/qUIfNN9WsSz8SRBDxR2L" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/7r321qijkT1S1fEbsk9G" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/iMxGiHo5OJNFEyoybqFU" alt=""><figcaption></figcaption></figure>

{% stepper %}
{% step %}

#### Visible and read-only fields

The cardholder will need to provide their first and last names, full address, email, and click a checkbox to agree to pay and give their permissions to receive an email.

Additionally, they'll see the amount field, but it'll be read-only.
{% endstep %}

{% step %}

#### Submission options

The PayForm will redirect the user to an external URL. An encrypted query string containing the POST data will also be appended to the URL&#x20;
{% endstep %}

{% step %}

#### Styling and colors

The styling and colors were left as default, only switching out the button background and border to different shades of green.
{% endstep %}

{% step %}

#### Pre-filled values

The amount will be pre-filled as $25, the redirect URL is using an example URL to your website, and the EIndex is using the sandbox value for encryption key. Endpoint value should always be left as default.
{% endstep %}
{% endstepper %}

The JSON will look like the following:

{% code title="PayForm JSON example" %}

```json
{
  "InitParams": {
    "MerchID": 1,
    "WTYPE": "PF",
    "PostURL": "",
    "RedirectURL": "https://yourwebsite.com/success",
    "REF_ID": "",
    "RPGUID": "",
    "EndPoint": "PayForm/PF.aspx",
    "EINDEX": "300",
    "Amounts": {
      "Amount": 25,
      "Surcharge": 0,
      "TotalAmt": 25
    },
    "Payer": {
      "Firstname": "",
      "Lastname": "",
      "BillingAddress": {
        "StreetAddress": "",
        "City": "",
        "State": "",
        "ZIP": "",
        "Country": ""
      },
      "Email": "",
      "Phone": ""
    },
    "WidOptions": {
      "eVisible": "6E7F",
      "eReadOnly": "0040",
      "eStyles": "0001",
      "eSubmission": "0201",
      "eColors": "#ffffff,#6cca44,#59ff00,#212121,#ffffff,#212121,#ffffff"
    }
  }
}
```

{% endcode %}

**This JSON can be used to make a REST API request to generate the actual payment form.**&#x20;

You may re-use this JSON to generate the same type of form for multiple different users. You may also want to dynamically configure values like the amounts from your code.

{% hint style="success" %}
To generate a PayForm, make a request to [PayForm Old](/api-reference/rest-api-alt/payform#payform-initialize).&#x20;
{% endhint %}

If you include a valid session key, the PayForm will be accessible under the `PaymentUrl` included in the response. You can embed it into your site or redirect the user to the page.

Once the user fills out and submits the form, we'll handle the payment.

If you want to handle the query string when redirecting back to your website to store the transaction ID in your database, read the [PayForm](/documentation/getting-started/integration-options/payform#redirect-with-query-string) section of our full PayForm guide.

#### PayForm manual consent

To use the PayForm to save a card on file, follow the steps in [#payform-manual-card-sale](#payform-manual-card-sale "mention"), change the transaction type to collecting cardholder data, and skip the amount field.

You may also collect an instant payment and consent at the same time by choosing the combo widget as your transaction type.

### Virtual Terminal or desktop application

The Virtual Terminal is a web application that allows you to manually enter credit card details and process transactions through your browser.&#x20;

{% hint style="info" %}
To learn more about using the Virtual Terminal, see the [Virtual Terminal](/documentation/getting-started/integration-options/virtual-terminal) user guide.
{% endhint %}

{% hint style="info" %}
Read more about using our custom desktop application for sales in the [Integration Options](/documentation/getting-started/integration-options) guide or [contact Number](/help/customer-support) to get access.
{% endhint %}

#### Virtual Terminal manual card sale

When you visit the Virtual Terminal, log in and expand *Credit Cards* in the navigation on the left. You'll see options for a sale, an EMV sale, authorization, forced auth, and adjustments. Follow the instructions and manually enter the cardholder details to make a sale.

<figure><img src="/files/AlcV7q2z0OnpvNwnZ43k" alt=""><figcaption></figcaption></figure>

#### Virtual Terminal manual consent

Using the Virtual Terminal, you can create annual, one-time, recurring, and subscription consents. Log in and expand *Consents* and *Recurring* tabs on the left side of the screen. Choose the type of consent you're interested in and follow the instructions to manually enter the cardholder details and store a card on file.

<figure><img src="/files/WvCBcfBjwVLAaWcaCgKw" alt=""><figcaption></figcaption></figure>

### Android / iOS SDK integration

If you are developing an Android or iOS application, you can utilize our SDKs to charge credit cards and collect consent manually by having users enter their own details.&#x20;

{% hint style="info" %}
We recommend following the [Android SDK](/documentation/getting-started/integration-options/android-sdk) and [iOS SDK](/documentation/getting-started/integration-options/ios-sdk) guides to learn how to integrate Number with your mobile applications.
{% endhint %}

#### Mobile manual card sale

The relevant methods are described in [/pages/iE4JAbx6RM93pLM1UEuz#id-1.-charge-credit-card](https://docs.number.tech/documentation/developer-quickstart/pages/iE4JAbx6RM93pLM1UEuz#id-1.-charge-credit-card "mention") section of the [Android SDK](/documentation/getting-started/integration-options/android-sdk) guide and [/pages/UDfr2U9uWMEiomNiA642#id-1.-charge-credit-card](https://docs.number.tech/documentation/developer-quickstart/pages/UDfr2U9uWMEiomNiA642#id-1.-charge-credit-card "mention") section of the [iOS SDK](/documentation/getting-started/integration-options/ios-sdk) guide.&#x20;

#### Mobile manual consent annual

The relevant methods are described in [/pages/iE4JAbx6RM93pLM1UEuz#id-3.-create-annual-consent](https://docs.number.tech/documentation/developer-quickstart/pages/iE4JAbx6RM93pLM1UEuz#id-3.-create-annual-consent "mention") section of the [Android SDK](/documentation/getting-started/integration-options/android-sdk) guide and [/pages/UDfr2U9uWMEiomNiA642#id-3.-create-annual-consent](https://docs.number.tech/documentation/developer-quickstart/pages/UDfr2U9uWMEiomNiA642#id-3.-create-annual-consent "mention") section of the [iOS SDK](/documentation/getting-started/integration-options/ios-sdk) guide.&#x20;

### REST API integration

If you wish to have more control over the integration and you are PCI Level 1 compliant, you can try using our APIs. They provide methods for all payment types available using our other services, including manual card sales and collecting different types of consent.

{% hint style="info" %}
To learn more about our APIs, see the [REST API](/documentation/getting-started/integration-options/rest-api) integration guide.
{% endhint %}

After authenticating, when you collect cardholder data alongside the other payment details, if using the REST API, prepare the HMAC secured header like shown in [Authentication](/documentation/developer-quickstart/authentication) quickstart guide, and encrypt the card number using our RSA certificate. Follow the instructions in the API reference to prepare and handle the request.

#### Manual card sale

You can use the following API operations:

* For the REST API, use [/pages/w4UMtcF7UfD7pNPTiZF7#apicardprocrest-v1.0.0-cardsale-manual](https://docs.number.tech/documentation/developer-quickstart/pages/w4UMtcF7UfD7pNPTiZF7#apicardprocrest-v1.0.0-cardsale-manual "mention").

#### Manual consent

You can use the following API operations:

* For the REST API, use [/pages/2Pdm0t88TPo3URCjHoXS#apicardprocrest-v1.0.0-consentannual-create\_man](https://docs.number.tech/documentation/developer-quickstart/pages/2Pdm0t88TPo3URCjHoXS#apicardprocrest-v1.0.0-consentannual-create_man "mention") for annual consent and [/pages/YBJbuCVqQbR5pZ3WsIkL#apicardprocrest-v1.0.0-consentrecurring-create](https://docs.number.tech/documentation/developer-quickstart/pages/YBJbuCVqQbR5pZ3WsIkL#apicardprocrest-v1.0.0-consentrecurring-create "mention") for recurring consent.


# Querying and Filtering

Find the information you need through the API or Virtual Terminal

<figure><img src="/files/ylbFUd0J1ze73jpTSSPf" alt=""><figcaption></figcaption></figure>

If you need to find a specific record in our database (such as a transaction or saved consent) or you need to find all records matching your criteria, you can either **query our APIs** programatically or **use the Virtual Terminal** to view and filter the records from its user interface.

## REST API

To query records, you'll need to find a relevant method in the [REST API](/api-reference/rest-api) reference.

When querying, you'll need to prepare the `Query` string. It should consist of variables that correspond to fields on the records and logical terms built using those variables.&#x20;

**All `Query` string variable options are fully described in the API reference under specific API methods and in the** [Querying](/documentation/resources/querying) **reference.** You can use the variables to build logical terms, and you can build and join logical terms using "&&" for a logical AND or "||" for a logical OR.

Read about Number's query language in our [Querying](/documentation/resources/querying) reference.

{% hint style="info" %}
Depending on the type of record you're querying (transaction, consent, ...), the variables you can use inside of a `Query` string will differ. The formatting rules do not change.
{% endhint %}

### Example

As an example, if want to find settled ACH transactions made in January 2025 made using Verifone card readers, you can call [/pages/aCvYq9EuHlyzNGomxgcw#apicardprocrest-v1.0.0-query-achtransaction](https://docs.number.tech/documentation/developer-quickstart/pages/aCvYq9EuHlyzNGomxgcw#apicardprocrest-v1.0.0-query-achtransaction "mention") or [ACH](/api-reference/soap-api/ach#ach-transaction-query) depending on which API you are using.

You can check the description of the `Query` string parameter or check the [Querying](/documentation/resources/querying) reference for [Querying](/documentation/resources/querying#transaction-query) section to find out that **variable 'B' corresponds to transaction status, variable 'C' corresponds to date created, and 'U' corresponds to the transaction origin**.

Each variable which requires an enum includes a description of valid values. **Settled transactions have a transaction status of '2', and Verifone transactions have an origin of 'SDK'.** To format the date correctly, follow the examples given for the variable.

You can combine the filters to build your `Query` string like so:

```sql
(B=2)&&(C>='1/1/2025')&&(C<='1/31/2025')&&(U='SDK')
```

***

## Virtual Terminal

You can filter consents, transactions, and other records through the Virtual Terminal user interface.&#x20;

To log into the Virtual Terminal, you need to have a user account created through the Client Admin Portal as described in the [Authentication](/documentation/developer-quickstart/authentication) quickstart guide.

Once you're logged in, see the navigation on the left and click on *Scheduled* to view scheduled payments, click on *Settlement* to view settlements, or expand *Reports* to find other reports. There, you'll be able to search and filter records using the user interface.

You can read more about using the Virtual Terminal in the [Virtual Terminal](/documentation/getting-started/integration-options/virtual-terminal) guide.

<figure><img src="/files/dEaDg5CRd35jLzSebnHP" alt=""><figcaption><p>Virtual Terminal navigation</p></figcaption></figure>

<figure><img src="/files/GGFAnp0WMeBRGL8L3IjT" alt=""><figcaption><p>Consent list and filters</p></figcaption></figure>

<figure><img src="/files/PfOvNPCyvMNTjFWhXgw0" alt=""><figcaption><p>Transaction list and filters</p></figcaption></figure>


# Payment Reminders

Send payment reminders to clients through text or e-mail

As an integrator, you may wish to send a payment reminder to a client through a text or e-mail which will allow them to pay the amount due. Here's an example reminder:

<figure><img src="/files/MOHW76Mj5BzUQHYxOHBX" alt=""><figcaption></figcaption></figure>

> You have a payment due to Merchant XYZ of $125.00 due on 10/4/2016. Please follow the link below to make the payment. <https://easypay5.com/sw/?SP=E8E5EC> &#x20;

Once they receive the reminder, they can click the link that is sent along with the message to open a payment page. This will allow them to enter their card details and make a payment.

After the payment is submitted, a transaction receipt would be sent to the e-mail address on file.

<figure><img src="/files/pTSXI7NBvKuP5WPTHMFc" alt=""><figcaption></figcaption></figure>

## Implementation

To send a payment reminder using the REST API, use the [/pages/w2fKiNwJnMYeVfLvlA4i#apicardprocrest-v1.0.0-other-smspay](https://docs.number.tech/documentation/developer-quickstart/pages/w2fKiNwJnMYeVfLvlA4i#apicardprocrest-v1.0.0-other-smspay "mention")endpoint.

### Request

Both implementations use a similar body structure, and the fields are described below.

<table><thead><tr><th width="195">Field name</th><th>Description</th></tr></thead><tbody><tr><td>Person</td><td>The name, address, email, and phone number for the payee.</td></tr><tr><td>MessageType</td><td><p>The type of message for the payee.</p><ul><li>EMAIL: Send an email with a link to the payment form</li><li>URLONLY: Only return a URL to the payment form in the response</li><li>TEXT: Send a text message with a link to the payment form</li></ul></td></tr><tr><td>RefID</td><td>A custom user-defined field to save with the transaction.</td></tr><tr><td>RPGUID</td><td>Another custom user-defined field to save with the transaction.</td></tr><tr><td>MessageBody</td><td><p>The message to send. <strong>Use **Merch1** to insert merchant's name into your message template.</strong><br><br>If the body is left empty, a default generic message will be used:<br></p><p><em>You have a Payment Due to [Merchant Name] of [Amount] due on [DueOn]. Please follow the link below to make the Payment. [Link Here]</em></p></td></tr><tr><td>AcctHolderID</td><td>Not used, please fill with 0.</td></tr><tr><td>Amount</td><td>The $ amount to collect.</td></tr><tr><td>ConsentID</td><td>Not used, please fill with 0.</td></tr><tr><td>DueOn</td><td>The payment due date in mm/dd/yyyy or yyyy/mm/dd format to display to the customer.</td></tr><tr><td>EINDEX</td><td>This is your unique Integrator Key Index for encryption. <strong>It should be provided by Number when you make an account with us</strong>, otherwise <a href="/pages/kj6DExa5bIpmWMzygpvr">contact Number customer support</a>.</td></tr><tr><td>MerchID</td><td>The unique identifier for the Merchant record.</td></tr><tr><td>TXID</td><td>Not used, please fill with 0.</td></tr><tr><td>WType</td><td>This specifies which payment widget to display, including custom widgets built for your company. <a href="/pages/kj6DExa5bIpmWMzygpvr">Contact Number for more information.</a></td></tr><tr><td>RedirectURL</td><td>This specifies where to redirect the user and post the results of the transaction.</td></tr><tr><td>WidgetURL</td><td>The endpoint for the widget payment form, including custom forms. <a href="/pages/kj6DExa5bIpmWMzygpvr">Contact Number</a> and we will provide you with a value. You can start with <a href="https://easypay5.com/stdwidget/"><em>https://easypay5.com/sw</em></a></td></tr><tr><td>ExpiresOn</td><td>A date in yyyy-mm-dd format for when the payment link should no longer be available.</td></tr><tr><td>SingleUse</td><td>Indicates whether the payment link should only accept a single payment.</td></tr><tr><td>OptParams</td><td>Parameters which control the design and behavior of the payment form including the visible fields, read-only fields, color and styling, and submission options.<br><br>See the <a data-mention href="/pages/lex90vp462I6tTL2RJvc#payform-builder">/pages/lex90vp462I6tTL2RJvc#payform-builder</a> section in the <a data-mention href="/pages/lex90vp462I6tTL2RJvc">/pages/lex90vp462I6tTL2RJvc</a> guide to learn how you can generate those parameters.</td></tr></tbody></table>

### Response

If you didn't catch any exceptions and your response is not null, check the value of `FunctionOK`. If `FunctionOk` is false, it indicates an error that was handled on the Number servers. You can find more details by looking at `ErrMsg` and `ErrCode` included in the response.

**You don't have to do anything else, the reminder was sent successfully.** A friendly response message is included in `RespMsg` field, and the `PaymentURL` is also returned if you wish to store it.

&#x20;


# Getting Started

Before you get started

<figure><img src="/files/UXq4EiR6iyRAcjtyAyLF" alt=""><figcaption></figcaption></figure>

To get the most out of using Number services, you'll need to define the type of integration (or integrations) you need, and learn some basic concepts around how to integrate.&#x20;

In the next sections, you can read about all of the [Integration Options](/documentation/getting-started/integration-options) and find our [Integration Checklist](/documentation/getting-started/integration-checklist) to give you an overview of all the steps required to start using our services.

{% hint style="info" %}
For all major types of integrations, there are additional integration guides or user guides under their respective sections.
{% endhint %}

Here are the articles in this section:

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Integration Checklist ></strong></td><td><a href="/pages/8YzdX7McGPhcNg2RjBrX">/pages/8YzdX7McGPhcNg2RjBrX</a></td></tr><tr><td><strong>Integration Options ></strong></td><td><a href="/pages/0GtA9h1fCfCkWInDaiv0">/pages/0GtA9h1fCfCkWInDaiv0</a></td></tr><tr><td><strong>Basics ></strong></td><td><a href="/pages/NIu9F1YMPd2MjG19Xpdb">/pages/NIu9F1YMPd2MjG19Xpdb</a></td></tr><tr><td><strong>Client Admin Portal ></strong></td><td><a href="/pages/QCzUPwvD2JMNKC9IVezV">/pages/QCzUPwvD2JMNKC9IVezV</a></td></tr></tbody></table>


# Integration Checklist

The comprehensive checklist to integrating with Number

Integrating payment processing into your system can be a daunting task. To help you on this journey, we've prepared a checklist which describes all the steps required from creating a Number account to going live, including the design, development, and testing.

{% stepper %}
{% step %}
**Create a Number account and obtain credentials: 1-2 days**

Sign up for a Number Sandbox account to gain access to the platform and its features. Ensure you have all necessary business information ready for registration.

{% hint style="info" %}
Contact us to sign up for a Number Sandbox account: \
<partners@number.tech>  /  (866) 927-9344
{% endhint %}

After account creation, retrieve the necessary credentials from the Number Client Admin Portal. This will be essential for encryption and authentication.

{% endstep %}

{% step %}
**Choose your integration methods: 1-2 days**

Read about the [Integration Options](/documentation/getting-started/integration-options) and decide which one best suit your business needs. Options include:

* **REST API and the PayForm**: Utilize the Number API and a customizable pre-built payment form that can be integrated directly into your site.
* **Verifone**: Collect payments using Verifone card readers with our software.
* **Mobile SDK**: If you have a mobile application, use the Number SDK for in-app payments.
* **Virtual Terminal**: A web application for processing payments directly through a browser.

{% hint style="info" %}
You can find guides that will help you learn how to navigate each integration method on the [Integration Options](/documentation/getting-started/integration-options) page.
{% endhint %}

For example: PCI Level 1 clients can use a purely API integration, while others would need to implement a PayForm for collecting cardholder data directly through their website.&#x20;

{% endstep %}

{% step %}
**Develop a payment workflow: 1-2 days**

Outline all interaction points in your current workflow where payments might be collected.

Define your requirements for various types of payment processes and equipment (card readers, web payments, card-present transactions, back-office processes, and reporting mechanisms).

{% endstep %}

{% step %}
**Develop the frontend components: 1-2 weeks**

{% hint style="info" %}
If you are using the mobile SDKs or the Virtual Terminal, you can skip this step as you won't need to develop any additional frontend or UI components.
{% endhint %}

Create the frontend components necessary for user interaction.

{% endstep %}

{% step %}
**Develop the EMV integration: 1 week**

{% hint style="info" %}
Unless you want to use Verifone card readers or other card readers, you can skip this step as you won't need the EMV integration.
{% endhint %}

Implement EMV functionality provided by our Windows service or SDK to support chip card transactions. Read the [Verifone](/documentation/getting-started/integration-options/verifone) guide to learn how to use these services.

{% endstep %}

{% step %}
**Develop the backend integration: 2-3 weeks**

{% hint style="info" %}
Depending on the scope of your integration, it might take less time.\
Also, you can skip this step if you only plan on only using the Virtual Terminal.&#x20;
{% endhint %}

Write the server-side logic to handle payment processing, invoking our services.\
\
Develop data management, coupling your users with the payment activities by storing consent or transaction IDs, and optionally storing transaction amounts for reconciliation.

{% endstep %}

{% step %}
**Develop the processes for logging, reporting, and reconciliation: 1 week**

Set up basic logging where applicable. Consult us to set up reporting and reconciliation processes. They will allow you to track transactions and ensure financial accuracy.

{% endstep %}

{% step %}
**Test your integration on a development environment: 1-2 weeks**

Before going live, thoroughly test your integration in a sandbox environment. Ensure that all payment flows work as expected and that you can handle various transaction scenarios. You can read more about using the sandbox in the [Testing](/documentation/testing) section.\
\
Conduct unit testing to validate the integration functionality before going live, ensuring all components work as intended.

{% endstep %}

{% step %}
N**umber inspection: 1-2 meetings**

The Number team always inspects the workflow that our clients develop prior to going live.

{% endstep %}

{% step %}
**Go live: 1 day**

Once testing is complete and you are satisfied with the implementation, switch to the production environment. Update your configuration as necessary.

{% endstep %}

{% step %}
**Monitor and maintain: continuous**

Once you go live, monitor your integration to make sure there are no problems. Work on improvements and fixes as required.
{% endstep %}
{% endstepper %}


# Integration Options

Learn about how you can integrate with Number

Before you start using our services, you'll want to decide which type of integration is most suited to your business case. We provide a plethora of ways to start using our services:

* REST API
* Mobile SDKs for Android and iOS
* PayForm and legacy widgets
* The Virtual Terminal web application
* Custom desktop applications
* Win service and DLL

**You don't have to limit yourself to one type of integration.** Many integrators use our PayForm to collect the cardholder data, and then use our API for the rest. The Virtual Terminal can also be used for various functions such as processing payments, creating card-on-file plans (consents), and generating reports. You can find more details about each integration in the next few sections.

Before you read about the specific integration options, we recommend having a look at the [#pci-compliance](#pci-compliance "mention") section below to help you clarify which options are relevant to your unique case.

***

## PCI Compliance

### What is PCI DSS?

PCI compliance refers to adherence to the Payment Card Industry Data Security Standard (PCI DSS), which is a set of security standards related to processing, storing, and transmitting credit card information. The PCI DSS was developed by the Payment Card Industry Security Standards Council (PCI SSC), which was founded by major credit card companies like Visa, MasterCard, American Express, Discover, and JCB.

{% hint style="info" %}
Key aspects of PCI compliance include:

1. **Maintaining Secure Networks and Systems**: Installing and maintaining a firewall configuration to protect cardholder data and not using vendor-supplied defaults for system passwords and other security parameters.
2. **Protecting Cardholder Data**: Companies must protect stored cardholder data and encrypt transmission of cardholder data across open, public networks.
3. **A Vulnerability Management Program**: Using and regularly updating antivirus software.
4. **Strong Access Control Measures**: Access to cardholder data should be restricted by business need-to-know, with a unique ID assigned to each person with computer access, and restricted physical access to cardholder data.
5. **Regular Monitoring and Network Tests**: Tracking and monitoring all access to network resources and cardholder data, regularly testing security systems and processes.
6. **An Information Security Policy**: Companies must maintain a policy that addresses information security for all personnel.
   {% endhint %}

PCI compliance helps protect cardholder data from theft and fraud, ensuring consumer trust and avoiding fines and penalties associated with non-compliance. Businesses of all sizes that handle credit card information are **required** to comply with PCI DSS.

### Integration choice based on compliance

**If you are not already handling cardholder data by yourself, Number can do that for you.**

Depending on whether or not you are handling the card holder data under your own documented PCI level one compliance program, you'll want to use different types of integrations.&#x20;

1. If you have your own PCI level one compliance program umbrella, you may use our APIs for all types of payment activities, including authorization of cards, issuing credits, reversal, reports, etc.
2. Otherwise, you can use our PayForm web widget and other applications served under our PCI Level One platform to collect cardholder data, and use our API for any and all other payment-related activities.

***

## REST API

The REST API will allow you to enable integration of Number payments with external applications, allowing for full automation and a high degree of customization.&#x20;

They allow a variety of functions:&#x20;

* Processing payments / voids / credits / settlements,&#x20;
* Running queries and reports,&#x20;
* Returning receipts and documents for signature,&#x20;
* Creating / modifying / processing payment plans.

It's important to note that some API functionality will require you to collect cardholder data, such as [Processing a card sale with card present](https://docs.number.tech/documentation/getting-started/pages/w4UMtcF7UfD7pNPTiZF7#apicardprocrest-v1.0.0-cardsale-cardpresent), and that requires you to be PCI Level 1 compliant. You can overcome this by using our PayForm to collect all cardholder data securely.

You can read more about implementation in the API integration guide:

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>REST API ></td><td><a href="/pages/g0s2SOjVSbGR7BXOxF78">/pages/g0s2SOjVSbGR7BXOxF78</a></td></tr></tbody></table>

***

## Mobile SDKs

The mobile SDKs will allow you to integrate Number payments services into any Android and iOS application using the prebuilt payment UI components. **Similar to PayForm, those components will allow you to collect cardholder data and process payments in a secure and PCI compliant way.**&#x20;

In addition to the native Android and iOS SDKs, we offer a React Native wrapper which can be used to build a cross-platform app.&#x20;

If you need to integrate Number payments with a mobile application, we recommend using the SDKs.

You can read more about implementation in the SDK integration guides:

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>Android SDK ></td><td><a href="/pages/iE4JAbx6RM93pLM1UEuz">/pages/iE4JAbx6RM93pLM1UEuz</a></td></tr><tr><td>iOS SDK ></td><td><a href="/pages/UDfr2U9uWMEiomNiA642">/pages/UDfr2U9uWMEiomNiA642</a></td></tr><tr><td>React Native SDK ></td><td><a href="/pages/jAgvP5o77wzQJFYgjq6C">/pages/jAgvP5o77wzQJFYgjq6C</a></td></tr></tbody></table>

***

## PayForm and legacy widgets

A PayForm is the most convenient means of collecting cardholder data. By using our builder tool or our API, you'll be able to set the design and behavioral aspects of the form and we'lll return a URL which loads it into the view. The form will then use webhooks to POST the realtime data to the site of your choice.

Once the cardholder data is collected, you can use other integrations, such as our APIs or the Virtual Terminal, to process consents, credit, void, and query transactions.

We also have a widget as a legacy option to the PayForm. With this widget, users will enter their cardholder data directly into the Number platform, and your system can be updated in realtime. **If you're just starting, we suggest using the PayForm as our modern option.**

We recommend using the PayForm to collect all cardholder data when integrating with web applications as it's secure, easy to get started, and offers a lot of customization.&#x20;

You can read more about implementation in the integration guides:

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>PayForm ></td><td><a href="/pages/lex90vp462I6tTL2RJvc">/pages/lex90vp462I6tTL2RJvc</a></td></tr><tr><td>Widgets ></td><td><a href="/pages/ALk5mwlnQmpdvUOGhbVT">/pages/ALk5mwlnQmpdvUOGhbVT</a></td></tr></tbody></table>

***

## Virtual Terminal

The Virtual Terminal (VT) is a web application which you can access through your browser. It provides all types of credit card processing functionality:

* Authorizations,
* Voids / credits / settlements,
* Reporting,
* Payment plans (recurring / subscription consent),
* Card-on-file (Annual consent).

The VT is the fastest way to start trying out our payment services. Otherwise, it's ideal for businesses processing payments over the phone or at sales points lacking a physical terminal.

You can read more about the Virtual Terminal in the user guide:

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>Virtual Terminal ></td><td><a href="/pages/UOlTsAJ4SQUaN7oY9Csw">/pages/UOlTsAJ4SQUaN7oY9Csw</a></td></tr></tbody></table>

***

## Our custom desktop application

We also have a custom desktop application which can be convenient in an office setting to collect card present payments. This application offers much of the same functionality as the Virtual Terminal. As opposed to the Virtual Terminal, the desktop app only requires you to authenticate once a day to keep your session.

The application interfaces with VeriFone card readers. These devices accept EMV chip and contactless cards in addition to the usual card swipe and manual entry.&#x20;

{% hint style="info" %}
[Contact us](/help/customer-support) to learn more about custom desktop applications.
{% endhint %}

***

## Win service and DLL

If you wish, you can take advantage of our end-to-end encryption model used with the Verifone card reader and build around it by using our Windows service or referencing our Dynamic Link Library. They channel requests through our API and responses can be consumed at the client software level. This way, you can develop your own workflow and displays.

You can read more about integrating with Verifone in the integration guide:

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>Verifone ></td><td><a href="/pages/BK3mUZUmMtSSNUopk6Wy">/pages/BK3mUZUmMtSSNUopk6Wy</a></td></tr></tbody></table>


# REST API

Getting started with the REST API for Number

Our REST API allows full integration of Number services with a high degree of customization. You can use our [REST API reference](/api-reference/rest-api) to learn about specific methods in the API.

Before you continue this section, we recommend reading sections about [authentication](/documentation/getting-started/basics/authentication), [best practices](/documentation/getting-started/basics/api-best-practices), and [input validation](/documentation/getting-started/basics/api-input-validation).

## Examples

### Authenticate

An example of using the [<mark style="color:green;">`Authenticate`</mark>](https://docs.number.tech/documentation/getting-started/integration-options/pages/fsxIL8vsPTRNOus4JvYk#apicardprocrest-v1.0.0-authenticate) method.

{% tabs %}
{% tab title="C# Synchronous" %}
{% code lineNumbers="true" %}

```csharp
private void Authenticate() {
  /// create request with account code and Token 
  string jsonContent = "{\"AcctCode\":\"EP9142446\",\"Token\":\"F31D16BA862F4EC6AE95CB90450C826A\"}";

  byte[] data = Encoding.UTF8.GetBytes(jsonContent);

  // Specify Number Endpoint 
  string MyUrl = "https://easypay5.com/APIcardProcNumber/v1.0.0/Authenticate";

  // create a webrequest 
  WebRequest request = WebRequest.Create(MyUrl);
  request.Method = "POST";
  request.ContentType = "application/json";
  request.ContentLength = data.Length;
  string responseContent = null;


  ///  Important to handle any exceptions 
  try
  {
    // execute request 
    using (Stream stream = request.GetRequestStream())
    {
      stream.Write(data, 0, data.Length);
    }
    using (WebResponse response = request.GetResponse())
    {
      using (Stream stream = response.GetResponseStream())
      {
        using (StreamReader sr = new StreamReader(stream))
        {
          responseContent = sr.ReadToEnd();
        }
      }
    }
  }
  catch (Exception ee)
  {
    ///  consume any communication exceptions and abort
    MessageBox.Show("Communication Exception : " + ee.Message);
    /// important to insert your Logging function here
    return;

  }

  /// parse Json in any number of ways  , we use Newtonsoft 
  var AuthResp = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(responseContent);

  var MyResp = AuthResp.AuthenticateResult;

  ///  here are the important values to consume
  bool FunctionOk = (bool)MyResp.FunctionOk;
  bool AuthSuccess = (bool)MyResp.AuthSuccess;
  int ErrCode = (int)MyResp.ErrCode;
  string ErrMsg = (string)MyResp.ErrMsg;
  string RespMsg = (string)MyResp.RespMsg;

  //Check for unexpected Errors on cloud servers. If errors found log Error info and abort;
  if (!FunctionOk)
  {
    MessageBox.Show("Aspen Error : " + ErrMsg + " : ErrorCode: " + ErrCode);
    /// important to insert your Logging function here
    return;
  }

  //Check for failures such as Invalid or Expired Credentials or Inactive Account.
  if (!AuthSuccess)
  {
    MessageBox.Show("Failed Authentication : " + RespMsg);
    /// important to insert your Logging function here
    return;
  }

  /// Arriving here means that the Authentication was successful. You will retrieve a SessionKey and 
  /// a list of Merchant Records associated with this account. The session key will be used for all
  /// subsequent API calls within the next 25 hours 
  string SessKey = (string)MyResp.SessKey;
  var MerchantList = MyResp.MerchantList;
}
```

{% endcode %}
{% endtab %}

{% tab title="C# Asynchronous" %}
{% code lineNumbers="true" %}

```csharp
public static async Task<string> Authenticate()
{
  string responseData = string.Empty;

  HttpClient httpClient = new HttpClient();
  /// Number Endpoint
  string apiUrl = "https://easypay5.com/APIcardProcNumber/v1.0.0/Authenticate";

  // Here is your account code and Token used to authenticate 
  string jsonContent = "{\"AcctCode\":\"EP9142446\",\"Token\":\"F31D16BA862F4EC6AE95CB90450C826A\"}";

  HttpResponseMessage response = new HttpResponseMessage();
  HttpContent content = new StringContent(jsonContent, Encoding.UTF8, "application/json");

  ///  important exception handling will provide info for communication issues  
  try
  {
    response = await httpClient.PostAsync(apiUrl, content);
  }
  catch (Exception ee) {
    return "Exception : " + ee.Message;
  }

  if (response.IsSuccessStatusCode)
  {
    // Handle successful POST response
    responseData = await response.Content.ReadAsStringAsync();
  }
  else
  {
    return "http error code " + response.StatusCode;
  }

  //  now you can parse the Json Response in a number of ways ( we will use newtonsoft )
  var AuthResp = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(responseData);
  var MyResp = AuthResp.AuthenticateResult;

  ///  here are the important values 
  bool FunctionOk = (bool)MyResp.FunctionOk;
  bool AuthSuccess = (bool)MyResp.AuthSuccess;
  int ErrCode = (int)MyResp.ErrCode;
  string ErrMsg = (string)MyResp.ErrMsg;
  string RespMsg = (string)MyResp.RespMsg;

  //Check for Aspen Errors on cloud servers. If errors found log Error info and abort;
  if (!FunctionOk)
  {
    return "Aspen Error : " + ErrMsg + " : ErrorCode:" + ErrCode;
  }

  //Check for failures such as Invalid or Expired Credentials or Inactive Account.
  if (!AuthSuccess)
  {
    return " Invalid Authentication : " + RespMsg;
  }

  /// Arriving here means that the Authentication was successful. You will retrieve a SessionKey and 
  /// a list of Merchant Records associated with this account. The session key will be used for all
  /// subsequent API calls
  string SessKey = (string)MyResp.SessKey;
  var MerchantList = MyResp.MerchantList;

  return "Success : " + SessKey;
}
```

{% endcode %}
{% endtab %}

{% tab title="JavaScript (Node.js)" %}

```javascript
'use strict';

const http = require('http');
const https = require('https');

const port = process.env.PORT || 1337;

http.createServer((req, res) => {
    let body = '';

    // AcctCode and Token supplied by Number
    const data = JSON.stringify({
        AcctCode: 'EP8449374',
        Token: '645E3CC4FD04472182C4161BA624C565'
    });

    const options = {
        host: 'easypay5.com',
        port: 443,
        path: '/APIcardProcNumber/v1.0.0/Authenticate',
        method: 'POST',
        timeout: 2000,
        headers: {
            'Content-Type': 'application/json',
            'Content-Length': Buffer.byteLength(data)
        }
    };

    const postReq = https.request(options, (postRes) => {
        postRes.setEncoding('utf8');

        postRes.on('data', (chunk) => {
            body += chunk;
        });

        postRes.on('end', () => {
            try {
                if (body === 'Bad Request') {
                    console.error('Bad request');
                    res.writeHead(400, { 'Content-Type': 'text/plain' });
                    res.end('Bad Request');
                    return;
                }

                const obj = JSON.parse(body);

                if (!obj) {
                    console.error('Communication Error: Null Object');
                    res.writeHead(500, { 'Content-Type': 'text/plain' });
                    res.end('Communication Error: Null Object');
                    return;
                }

                const { AuthenticateResult } = obj;

                if (!AuthenticateResult.FunctionOk) {
                    console.error(`${AuthenticateResult.ErrMsg} ${AuthenticateResult.ErrCode}`);
                    res.writeHead(500, { 'Content-Type': 'text/plain' });
                    res.end(`${AuthenticateResult.ErrMsg} ${AuthenticateResult.ErrCode}`);
                    return;
                }

                if (!AuthenticateResult.AuthSuccess) {
                    console.error(AuthenticateResult.RespMsg);
                    res.writeHead(401, { 'Content-Type': 'text/plain' });
                    res.end(AuthenticateResult.RespMsg);
                    return;
                }

                console.log(`SessKey: ${AuthenticateResult.SessKey}`);
                res.writeHead(200, { 'Content-Type': 'text/plain' });
                res.end(`SessKey: ${AuthenticateResult.SessKey}`);
            } catch (error) {
                console.error('Error parsing response:', error);
                res.writeHead(500, { 'Content-Type': 'text/plain' });
                res.end('Internal Server Error');
            }
        });
    });

    postReq.on('error', (error) => {
        console.error('Request error:', error);
        res.writeHead(500, { 'Content-Type': 'text/plain' });
        res.end('Request Error');
    });

    postReq.on('timeout', () => {
        console.error('Request timed out');
        res.writeHead(504, { 'Content-Type': 'text/plain' });
        res.end('Request Timeout');
    });

    postReq.write(data);
    postReq.end();
}).listen(port, () => {
    console.log(`Server listening on port ${port}`);
});
```

{% endtab %}
{% endtabs %}

### Process Annual Consent <a href="#process-annual-consent" id="process-annual-consent"></a>

An example of using [<mark style="color:green;">`ConsentAnnual_ProcPayment`</mark>](https://docs.number.tech/documentation/getting-started/integration-options/pages/pXZvz0HlPUC590yAuLhj#apicardprocrest-v1.0.0-consentannual-procpayment) method.

{% tabs %}
{% tab title="C#" %}
{% code lineNumbers="true" %}

```csharp
public static async Task<string> ProcessConsent( )
{
  string responseData = string.Empty;

  HttpClient httpClient = new HttpClient();

  /// Number Endpoint
  string apiUrl = "https://easypay5.com/APIcardProcNumber/v1.0.0/ConsentAnnual/ProcPayment";
  
  // Here is your consentID and amount of purchase
  string jsonContent = "{\"ConsentID\": 1 ,\"ProcessAmount\": 52.00 }";

  HttpContent content = new StringContent( jsonContent, System.Text.Encoding.UTF8, "application/json");
  HttpResponseMessage response = new HttpResponseMessage();

  // add your session Key to Header
  httpClient.DefaultRequestHeaders.Add("SessKey", "8D85FD7E140A4098AB303330323241303430333238");

  try
  {
    response = await httpClient.PostAsync(apiUrl, content);
  }
  catch (Exception ee)
  {
    return "Exception : " + ee.Message;
  }

  if (response.IsSuccessStatusCode)
  {
    // Handle successful POST response
    responseData = await response.Content.ReadAsStringAsync();
  }
  else
  {
    // handle http error
    return "http error code " + response.StatusCode;
  }


  var saleResponse = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(responseData);

  var procPaymentResult = saleResponse.ConsentAnnual_ProcPaymentResult;

  // Here are some of the important values 
  bool FunctionOk = (bool)procPaymentResult.FunctionOk;
  bool TxApproved = (bool)procPaymentResult.TxApproved;
  int ErrCode = (int)procPaymentResult.ErrCode;
  string ErrMsg = (string)procPaymentResult.ErrMsg;
  string RespMsg = (string)procPaymentResult.RespMsg;

  int TxID = (int)procPaymentResult.TxID;
  string TxnCode = (string)procPaymentResult.TxnCode;



  //Check for Aspen Errors on cloud servers. If errors found log Error info and abort;
  if (!FunctionOk)
  {
    return "Aspen Error : " + ErrMsg + " : ErrorCode:" + ErrCode;
  }

  //check for card issuer decline 
  if (!TxApproved)
  {
    return "Declined Transaction : " + RespMsg + " : " + TxnCode;
  }


  return "Approved Transaction " + TxID.ToString() + " : Approval Code " + TxnCode;

}
```

{% endcode %}
{% endtab %}

{% tab title="JavaScript (Node.js)" %}
{% code overflow="wrap" lineNumbers="true" %}

```javascript
'use strict';

const http = require('http');
const https = require('https');

const port = process.env.PORT || 1337;

http.createServer((req, res) => {
    let body = '';

	const sessKey = '89C8356BB8A84FE9B5303231333441303331343335'
    const data = JSON.stringify({
        ConsentID: 1,
        ProcessAmount: 5.00
    });

    const options = {
        host: 'easypay5.com',
        port: 443,
        path: '/APIcardProcNumber/v1.0.0/ConsentAnnual/ProcPayment',
        method: 'POST',
        timeout: 2000,
        headers: {
            'Content-Type': 'application/json',
            'Content-Length': Buffer.byteLength(data),
            'Accept': 'application/json',
            'SessKey': sessKey
        }
    };

    const postReq = https.request(options, (postRes) => {
        postRes.setEncoding('utf8');

        postRes.on('data', (chunk) => {
            body += chunk;
        });

        postRes.on('end', () => {
            try {
                if (body === 'Bad Request') {
                    console.error('Bad request');
                    res.writeHead(400, { 'Content-Type': 'text/plain' });
                    res.end('Bad Request');
                    return;
                }

                const obj = JSON.parse(body);

                if (!obj) {
                    console.error('Communication Error: Null Object');
                    res.writeHead(500, { 'Content-Type': 'text/plain' });
                    res.end('Communication Error: Null Object');
                    return;
                }

                const { ConsentAnnual_ProcPaymentResult } = obj;

                if (!ConsentAnnual_ProcPaymentResult.FunctionOk) {
                    console.error(`${ConsentAnnual_ProcPaymentResult.ErrMsg} : ${ConsentAnnual_ProcPaymentResult.ErrCode}`);
                    res.writeHead(500, { 'Content-Type': 'text/plain' });
                    res.end(`${ConsentAnnual_ProcPaymentResult.ErrMsg} : ${ConsentAnnual_ProcPaymentResult.ErrCode}`);
                    return;
                }

                if (!ConsentAnnual_ProcPaymentResult.TxApproved) {
                    console.error(ConsentAnnual_ProcPaymentResult.RespMsg);
                    console.error(`Decline code: ${ConsentAnnual_ProcPaymentResult.TxnCode}`);
                    res.writeHead(402, { 'Content-Type': 'text/plain' });
                    res.end(`Declined: ${ConsentAnnual_ProcPaymentResult.RespMsg}`);
                    return;
                }

                console.log(`Successful Transaction: ${ConsentAnnual_ProcPaymentResult.RespMsg}`);
                console.log(`Approval code: ${ConsentAnnual_ProcPaymentResult.TxnCode}`);
                res.writeHead(200, { 'Content-Type': 'text/plain' });
                res.end(`Success: ${ConsentAnnual_ProcPaymentResult.RespMsg}`);
            } catch (error) {
                console.error('Error parsing response:', error);
                res.writeHead(500, { 'Content-Type': 'text/plain' });
                res.end('Internal Server Error');
            }
        });
    });

    postReq.on('error', (error) => {
        console.error('Request error:', error);
        res.writeHead(500, { 'Content-Type': 'text/plain' });
        res.end('Request Error');
    });

    postReq.on('timeout', () => {
        console.error('Request timed out');
        res.writeHead(504, { 'Content-Type': 'text/plain' });
        res.end('Request Timeout');
    });

    postReq.write(data);
    postReq.end();
}).listen(port, () => {
    console.log(`Server listening on port ${port}`);
});
```

{% endcode %}

{% endtab %}
{% endtabs %}

### Void Transaction <a href="#void-transaction" id="void-transaction"></a>

An example of using [<mark style="color:green;">`CardSale_Void`</mark>](https://docs.number.tech/documentation/getting-started/integration-options/pages/2mBrGKqVF5oXgX8GlZnZ#apicardprocrest-v1.0.0-cardsale-void) method.

{% tabs %}
{% tab title="C#" %}
{% code overflow="wrap" lineNumbers="true" %}

```csharp
public static async Task TransactionVoid(string sessKey, int txID)
{
  using HttpClient httpClient = new HttpClient();
  string apiUrl = "https://easypay5.com/APIcardProcNumber/v1.0.0/CardSale/Void";

  string jsonContent = $$"""
    {"TxID":{{txID}}}
  """;

  HttpContent content = new StringContent(
    jsonContent, System.Text.Encoding.UTF8, "application/json");
  httpClient.DefaultRequestHeaders.Add("SessKey", sessKey);
  HttpResponseMessage response = await httpClient
    .PostAsync(apiUrl, content);

  if (!response.IsSuccessStatusCode)
  {
    MessageBox.Show("Error code: " + response.StatusCode);
    // <Insert your Logging function here>
    return;
  }

  var voidResponse = Newtonsoft.Json.JsonConvert
    .DeserializeObject<dynamic>(
      await response.Content.ReadAsStringAsync());
  var voidResult = voidResponse.Transaction_VoidResult;

  // Here are some of the important values 
  bool functionOk = (bool)voidResult.FunctionOk;
  int errCode = (int)voidResult.ErrCode;
  string errMsg = (string)voidResult.ErrMsg;
  string respMsg = (string)voidResult.RespMsg;

  bool txApproved = (bool)voidResult.TxApproved;
  int resultTxId = (int)voidResult.TxID;

  // Check for unexpected error on server
  if (!functionOk)
  {
    MessageBox.Show(errMsg + " ErrorCode: " + errCode);
    // <Insert your Logging function here>
    return;
  }

  // Check for declined transaction
  if (!txApproved)
  {
    MessageBox.Show(respMsg + " Decline Code: " + txnCode);
    // <Insert your Logging function here>
    return;
  }
  else
  {
    MessageBox.Show(respMsg + " Approval Code: " + txnCode);
    // <Insert your Logging function here>
    // <Do something with the response if needed>
    return;
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Credit Transaction <a href="#credit-transaction" id="credit-transaction"></a>

An example of using [<mark style="color:green;">`CardSale_ApplyCredit`</mark>](https://docs.number.tech/documentation/getting-started/integration-options/pages/2mBrGKqVF5oXgX8GlZnZ#apicardprocrest-v1.0.0-cardsale-applycredit) method.

{% tabs %}
{% tab title="C#" %}
{% code overflow="wrap" lineNumbers="true" %}

```csharp
public static async Task TransactionCredit(
  string sessKey, int txID, decimal creditAmount)
{
  using HttpClient httpClient = new HttpClient();
  string apiUrl = "https://easypay5.com/APIcardProcNumber/v1.0.0/CardSale/ApplyCredit";

  string jsonContent = $$"""
    {"TxID":{{txID}},"CreditAmount":{{creditAmount}}}
  """;

  HttpContent content = new StringContent(
    jsonContent, System.Text.Encoding.UTF8, "application/json");
  httpClient.DefaultRequestHeaders.Add("SessKey", sessKey);
  HttpResponseMessage response = await httpClient
    .PostAsync(apiUrl, content);

  if (!response.IsSuccessStatusCode)
  {
    MessageBox.Show("Error code: " + response.StatusCode);
    // <Insert your Logging function here>
    return;
  }

  var creditResponse = Newtonsoft.Json.JsonConvert
    .DeserializeObject<dynamic>(
      await response.Content.ReadAsStringAsync());
  var creditResult = creditResponse.Transaction_ApplyCreditResult;

  // Here are some of the important values 
  bool functionOk = (bool)creditResult.FunctionOk;
  int errCode = (int)creditResult.ErrCode;
  string errMsg = (string)creditResult.ErrMsg;
  string respMsg = (string)creditResult.RespMsg;

  bool txApproved = (bool)creditResult.TxApproved;
  int resultTxId = (int)creditResult.TxID;

  // Check for unexpected error on server
  if (!functionOk)
  {
    MessageBox.Show(errMsg + " ErrorCode: " + errCode);
    // <Insert your Logging function here>
    return;
  }

  // Check for declined transaction
  if (!txApproved)
  {
    MessageBox.Show(respMsg + " Decline Code: " + txnCode);
    // <Insert your Logging function here>
    return;
  }
  else
  {
    MessageBox.Show(respMsg + " Approval Code: " + txnCode);
    // <Insert your Logging function here>
    // <Do something with the response if needed>
    return;
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Query Transaction <a href="#query-transaction" id="query-transaction"></a>

An example of using [<mark style="color:green;">`Query_Transaction`</mark>](https://docs.number.tech/documentation/getting-started/integration-options/pages/dBtuA7Sh0aVhjDX09Hut#apicardprocrest-v1.0.0-query-transaction) method.

{% tabs %}
{% tab title="C#" %}
{% code overflow="wrap" lineNumbers="true" %}

```csharp
public static async Task TransactionQuery(string sessKey, string query)
{
  using HttpClient httpClient = new HttpClient();
  string apiUrl = "https://easypay5.com/APIcardProcNumber/v1.0.0/Query/Transaction";

  string jsonContent = $$"""
    {"Query":"{{query}}"}
  """;

  HttpContent content = new StringContent(
    jsonContent, System.Text.Encoding.UTF8, "application/json");
  httpClient.DefaultRequestHeaders.Add("SessKey", sessKey);
  HttpResponseMessage response = await httpClient
    .PostAsync(apiUrl, content);

  if (!response.IsSuccessStatusCode)
  {
    MessageBox.Show("Error code: " + response.StatusCode);
    // <Insert your Logging function here>
    return;
  }

  var queryResponse = Newtonsoft.Json.JsonConvert
    .DeserializeObject<dynamic>(
      await response.Content.ReadAsStringAsync());
  var queryResult = queryResponse.Transaction_QueryResult;

  // Here are some of the important values 
  bool functionOk = (bool)queryResult.FunctionOk;
  int errCode = (int)queryResult.ErrCode;
  string errMsg = (string)queryResult.ErrMsg;
  string respMsg = (string)queryResult.RespMsg;

  // Check for unexpected error on server
  if (!functionOk)
  {
    MessageBox.Show(errMsg + " ErrorCode: " + errCode);
    // <Insert your Logging function here>
    return;
  }

  var transactions = queryResult.Transactions;
  
  // <Display your transactions here>
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Consent General Query <a href="#consent-general-query" id="consent-general-query"></a>

An example of using [<mark style="color:green;">`Query_ConsentGeneral`</mark>](https://docs.number.tech/documentation/getting-started/integration-options/pages/dBtuA7Sh0aVhjDX09Hut#apicardprocrest-v1.0.0-query-consentgeneral) method.

{% tabs %}
{% tab title="C#" %}
{% code overflow="wrap" lineNumbers="true" %}

```csharp
public static async Task ConsentGeneralQuery(string sessKey, string query)
{
  using HttpClient httpClient = new HttpClient();
  string apiUrl = "https://easypay5.com/APIcardProcNumber/v1.0.0/Query/ConsentGeneral";

  string jsonContent = $$"""
    {"Query":"{{query}}"}
  """;

  HttpContent content = new StringContent(
    jsonContent, System.Text.Encoding.UTF8, "application/json");
  httpClient.DefaultRequestHeaders.Add("SessKey", sessKey);
  HttpResponseMessage response = await httpClient
    .PostAsync(apiUrl, content);

  if (!response.IsSuccessStatusCode)
  {
    MessageBox.Show("Error code: " + response.StatusCode);
    // <Insert your Logging function here>
    return;
  }

  var queryResponse = Newtonsoft.Json.JsonConvert
    .DeserializeObject<dynamic>(
      await response.Content.ReadAsStringAsync());
  var queryResult = queryResponse.ConsentGeneral_QueryResult;

  // Here are some of the important values 
  bool functionOk = (bool)queryResult.FunctionOk;
  int errCode = (int)queryResult.ErrCode;
  string errMsg = (string)queryResult.ErrMsg;
  string respMsg = (string)queryResult.RespMsg;

  // Check for unexpected error on server
  if (!functionOk)
  {
    MessageBox.Show(errMsg + " ErrorCode: " + errCode);
    // <Insert your Logging function here>
    return;
  }

  var consents = queryResult.Consents;

  // <Display your consents here>
}

```

{% endcode %}
{% endtab %}
{% endtabs %}

### Generate Receipt <a href="#generate-receipt" id="generate-receipt"></a>

An example of using [<mark style="color:green;">`ReceiptGenerate`</mark>](https://docs.number.tech/documentation/getting-started/integration-options/pages/YaMXGoIYHPbKE8K6LEPP#apicardprocrest-v1.0.0-receipt-receiptgenerate) method.

{% tabs %}
{% tab title="C#" %}
{% code overflow="wrap" lineNumbers="true" %}

```csharp
public static async Task ShowReceipt(
  string sessKey, int refID, int receiptType, int recipient)
{
  /* ReceiptType 1 TRANSACTION RECEIPT
   * ReceiptType 2 VOID RECEIPT
   * ReceiptType 3 REFUND RECEIPT
   * ReceiptType 4 ANNUAL RECEIPT
   * ReceiptType 5 RECURRING RECEIPT
   * ReceiptType 6 SUBSCRIPTION RECEIPT
   
   * Recipient 1 MERCHANT COPY
   * Recipient 2 CUSTOMER COPY
   * Recipient 3 DUAL COPY */


  using HttpClient httpClient = new HttpClient();
  string apiUrl = "https://easypay5.com/APIcardProcNumber/v1.0.0/Receipt/ReceiptGenerate";

  string jsonContent = $$"""
    {"REFID":{{refID}}, "ReceiptType":{{receiptType}}, "Recipient":{{recipient}}}
  """;

  HttpContent content = new StringContent(
    jsonContent, System.Text.Encoding.UTF8, "application/json");
  httpClient.DefaultRequestHeaders.Add("SessKey", sessKey);
  HttpResponseMessage response = await httpClient
    .PostAsync(apiUrl, content);

  if (!response.IsSuccessStatusCode)
  {
    MessageBox.Show("Error code: " + response.StatusCode);
    // <Insert your Logging function here>
    return;
  }

  var receiptResponse = Newtonsoft.Json.JsonConvert
    .DeserializeObject<dynamic>(
      await response.Content.ReadAsStringAsync());
  var receiptResult = receiptResponse.ReceiptGenerateResult;

  // Here are some of the important values 
  bool functionOk = (bool)receiptResult.FunctionOk;
  int errCode = (int)receiptResult.ErrCode;
  string errMsg = (string)receiptResult.ErrMsg;
  string respMsg = (string)receiptResult.RespMsg;

  // Check for unexpected error on server
  if (!functionOk)
  {
    MessageBox.Show(errMsg + " ErrorCode: " + errCode);
    // <Insert your Logging function here>
    return;
  }

  /* Receipt generation successful. 
   * You may now add the HTML to your page.
   * <Logic to display HTML, e.g. 
   *  webBrowser1.DocumentText = response.ReceiptHtml;> */
}

```

{% endcode %}
{% endtab %}

{% tab title="JavaScript (Node.js)" %}
{% code overflow="wrap" lineNumbers="true" %}

```javascript
'use strict';

const http = require('http');
const https = require('https');

const port = process.env.PORT || 1337;

http.createServer((req, res) => {
    let body = '';

    // ReceiptType 1 TRANSACTION RECEIPT
    // ReceiptType 2 VOID RECEIPT
    // ReceiptType 3 REFUND RECEIPT
    // ReceiptType 4 ANNUAL CONSENT AGREEMENT
    // ReceiptType 5 RECURRING CONSENT AGREEMENT
    // ReceiptType 6 SUBSCRIPTION CONSENT AGREEMENT
    // Recipient 1 MERCHANT COPY
    // Recipient 2 CUSTOMER COPY
    // Recipient 3 DUAL COPY

    const data = JSON.stringify({
        REFID: 1,
        ReceiptType: 1,
        Recipient: 1
    });

    const options = {
        host: 'easypay5.com',
        port: 443,
        path: '/APIcardProcNumber/v1.0.0/Receipt/ReceiptGenerate',
        timeout: 2000,
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Content-Length': Buffer.byteLength(data),
            'Accept': 'application/json',
            'SessKey': '89C8356BB8A84FE9B5303231333441303331343335'
        }
    };

    const postReq = https.request(options, (postRes) => {
        let responseBody = '';

        postRes.on('data', (chunk) => {
            responseBody += chunk;
        });

        postRes.on('end', () => {
            try {
                if (responseBody === 'Bad Request') {
                    console.error('Bad request');
                    res.writeHead(400, { 'Content-Type': 'text/plain' });
                    res.end('Bad Request');
                    return;
                }

                const obj = JSON.parse(responseBody);

                if (!obj) {
                    console.error('Communication Error: Null Object');
                    res.writeHead(500, { 'Content-Type': 'text/plain' });
                    res.end('Communication Error: Null Object');
                    return;
                }

                const { ReceiptGenerateResult } = obj;

                if (!ReceiptGenerateResult.FunctionOk) {
                    console.error(`${ReceiptGenerateResult.ErrMsg} : ${ReceiptGenerateResult.ErrCode}`);
                    res.writeHead(500, { 'Content-Type': 'text/plain' });
                    res.end(`${ReceiptGenerateResult.ErrMsg} : ${ReceiptGenerateResult.ErrCode}`);
                    return;
                }

                console.log(ReceiptGenerateResult.RespMsg);
                const receiptHtml = ReceiptGenerateResult.ReceiptHtml;
                res.writeHead(200, { 'Content-Type': 'text/html' });
                res.end(receiptHtml);
            } catch (error) {
                console.error('Error parsing response:', error);
                res.writeHead(500, { 'Content-Type': 'text/plain' });
                res.end('Internal Server Error');
            }
        });
    });

    postReq.on('error', (error) => {
        console.error('Request error:', error);
        res.writeHead(500, { 'Content-Type': 'text/plain' });
        res.end('Request Error');
    });

    postReq.on('timeout', () => {
        console.error('Request timed out');
        res.writeHead(504, { 'Content-Type': 'text/plain' });
        res.end('Request Timeout');
    });

    postReq.write(data);
    postReq.end();
}).listen(port, () => {
    console.log(`Server listening on port ${port}`);
});
```

{% endcode %}

{% endtab %}
{% endtabs %}

### Download our Postman Collections

**The Complete Postman Collection**

The complete postman collection includes sample requests for all of the API calls listed on this site.

&#x20;*Download the Complete Postman Collection:*

{% file src="/files/epfvFZFp3IGEXoTfBHTx" %}

**The Essentials Postman Collection**

The essentials postman collection includes sample requests to get you started with the essential API calls. The essentials collection includes:

* Authentication
* Voiding an open sale transaction
* Crediting a previously settled sale transaction
* Process an annual consent payment
* Annual consent query
* Transaction query
* Generate a receipt

&#x20;*Download the Essentials Postman Collection:*

{% file src="/files/pnqN9aL02RjUAbOrOrY8" %}


# Android SDK

Getting started with Android SDK for Number

The EasyPay Android SDK offers access to the Number API for seamless integration with any and all Android applications. For iOS integration, refer to the [iOS SDK integration guide](/documentation/getting-started/integration-options/ios-sdk).

***

## Installation

### Requirements

* Android 6.0 (API level 23) and above
* Gradle 8.2 and above
* Android Gradle Plugin 8.2.1
* Kotlin 1.9.22 and above

### Configuration

Add `easypay` to your dependencies in the `build.gradle` file.

```gradle
dependencies {
    implementation 'com.easypaysolutions:easypay:1.1.5'
    
    // If you want to use widgets, add the following line
    implementation 'com.easypaysolutions:easypay-widgets:1.1.5'
}
```

***

## Get started

### Integration

{% stepper %}
{% step %}
Prerequisites - get API key, HMAC secret and optional Sentry DSN from Number.
{% endstep %}

{% step %}

{% endstep %}

{% step %}
During initialization, the RSA certificate download begins. Proceeding with any call before downloading has finished will result with an exception `RSA_CERTIFICATE_NOT_FETCHED`.&#x20;

You can check the download status by accessing the following enum:

```kotlin
EasyPayConfiguration.getInstance().getRsaCertificateFetchingStatus()
```

{% endstep %}
{% endstepper %}

### Using widgets

#### **PaymentSheet**

Number's prebuilt payment UI component that allows you to collect credit card information in a secure way and process payments.

{% stepper %}
{% step %}
Initialize a `PaymentSheet` inside `onCreate` of your checkout `Fragment` or `Activity`, passing a method to handle the payment result.

<pre class="language-kotlin"><code class="lang-kotlin"><strong>import com.easypaysolutions.payment_sheet.PaymentSheet
</strong>import com.easypaysolutions.payment_sheet.utils.PaymentSheetResult

class PaymentSheetFragment : Fragment() {
    private lateinit var paymentSheet: PaymentSheet

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        paymentSheet = PaymentSheet(this, ::onPaymentSheetResult)
    }
    
    private fun onPaymentSheetResult(paymentSheetResult: PaymentSheetResult) {
        // implemented in the next steps
    }
}
</code></pre>

{% endstep %}

{% step %}
When the customer taps the payment button, call `present` method on the `PaymentSheet` instance with your configuration. `PaymentSheet.Configuration` requires the following parameters:

* `AmountsParam` - total $ amount of the payment;
* `ConsentCreatorParam` - annual consent details, that contains the following:
  * `limitLifeTime` - the maximum $ amount that can be charged in total,
  * `limitPerCharge` - the maximum $ amount that can be charged per transaction,
  * `merchantId` - the ID of the merchant that the consent is created for,
  * `startDate` - the date when the consent is created,
  * `customerReferenceId` or `consentId` to identify the customer.&#x20;

**Other parameters are optional.**

```kotlin
// ...
import com.easypaysolutions.repositories.annual_consent.create.ConsentCreatorParam
import com.easypaysolutions.repositories.charge_cc.AmountsParam

class PaymentSheetFragment : Fragment() {
    // ...
    
    private fun presentPaymentSheet() {
        val totalAmount: Double = 1000.0
        val consentCreator = ConsentCreatorParam(
            limitLifeTime = 100000.0,
            limitPerCharge = 1000.0,
            merchantId = 1,
            startDate = Date(),
            customerReferenceId = "CUSTOMER_REFERENCE_ID"
        )
    
        val config = PaymentSheet.Configuration
            .Builder()
            .setAmounts(AmountsParam(totalAmount))
            .setConsentCreator(consentCreator)
            .build()
            
        paymentSheet.present(config)
    }
}
```

{% endstep %}

{% step %}
Handle the payment result in the `onPaymentSheetResult` method.

```kotlin
// ...
class PaymentSheetFragment : Fragment() {
    // ...
    
    private fun onPaymentSheetResult(paymentSheetResult: PaymentSheetResult) {
        when (paymentSheetResult) {
            is PaymentSheetResult.Failed -> {
                // Handle failure
            }
    
            is PaymentSheetResult.Completed -> {
                // Handle successful payment
            }
    
            is PaymentSheetResult.Canceled -> {
                // Handle cancellation
            }
        }
    }
}
```

{% endstep %}
{% endstepper %}

#### **CustomerSheet**

Number's prebuilt UI component that lets your customers manage their saved credit cards.

{% stepper %}
{% step %}
Initialize a `CustomerSheet` inside `onCreate` of your checkout `Fragment` or `Activity`, passing a method to handle the customer sheet result.

```kotlin
import com.easypaysolutions.customer_sheet.CustomerSheet
import com.easypaysolutions.customer_sheet.utils.CustomerSheetResult

class CustomerSheetFragment : Fragment() {
    private lateinit var customerSheet: CustomerSheet

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        customerSheet = CustomerSheet(this, ::onCustomerSheetResult)
    }
    
    private fun onCustomerSheetResult(customerSheetResult: CustomerSheetResult) {
        // implemented in the next steps
    }
}
```

{% endstep %}

{% step %}
To present the customer sheet, call the `present` method on the `CustomerSheet` instance, passing your configuration. `CustomerSheet.Configuration` requires the following parameters:

* `ConsentCreatorParam` - annual consent details, that contains the following:
  * `limitLifeTime` - the maximum $ amount that can be charged in total,
  * `limitPerCharge` - the maximum $ amount that can be charged per transaction,
  * `merchantId` - the ID of the merchant that the consent is created for,
  * `startDate` - the date when the consent is created,
  * `customerReferenceId` or `consentId` to identify the customer.&#x20;

**Other parameters are optional.**

```kotlin
// ...
import com.easypaysolutions.repositories.annual_consent.create.ConsentCreatorParam

class CustomerSheetFragment : Fragment() {
    // ...
    
    private fun presentCustomerSheet() {
        val consentCreator = ConsentCreatorParam(
            limitLifeTime = 100000.0,
            limitPerCharge = 1000.0,
            merchantId = 1,
            startDate = Date(),
            customerReferenceId = "CUSTOMER_REFERENCE_ID"
        )
    
        val config = CustomerSheet.Configuration
            .Builder()
             .setConsentCreator(consentCreator)
            .build()
            
        customerSheet.present(config)
    }
}
```

{% endstep %}

{% step %}
Handle the customer sheet result in the `onCustomerSheetResult` method.

```kotlin
// ...
class CustomerSheetFragment : Fragment() {
    // ...
    
    private fun onCustomerSheetResult(customerSheetResult: CustomerSheetResult) {
        when (customerSheetResult) {
            is CustomerSheetResult.Failed -> {
                // Handle failure
            }

            is CustomerSheetResult.Selected -> {
                // Handle selected card - customerSheetResult.annualConsentId
            }
        }
    }
}
```

{% endstep %}
{% endstepper %}

### Screenshots

#### **Save Card**

<figure><img src="/files/4pQxTZaSKv5j6waKohD3" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/hAg4qGls6QQZg6SMVxrp" alt=""><figcaption></figcaption></figure>

#### **Manage Cards**

<figure><img src="/files/Tfcnfy4YB7cRB2WKc133" alt=""><figcaption></figcaption></figure>

#### **Store and Pay**

<figure><img src="/files/iSeWils4MZ3OwQ3noTAr" alt=""><figcaption></figcaption></figure>

***

## Common components

### SecureTextField component

The SDK's widgets use a component called `SecureTextField` which ensures a safe input of credit card number. It is a subclass of `TextInputEditText` which enables freedom of styling as needed.

`SecureTextField` supports only XML layout configuration:

```xml
<com.easypaysolutions.utils.secured.SecureTextField
    ... />
```

To get the `SecureData` from the `SecureTextField`, use the following property:

```kotlin
val secureData = secureTextField.secureData
```

{% hint style="info" %}
Data in the SecureTextField component is already encrypted and can be used in the API calls without any additional encryption.
{% endhint %}

***

## Common objects

Below you'll find code describing some of the objects that are commonly used in requests or responses. You can use it as a reference. The code includes parameter names, types, and some validation rules.

### `SecureData`

Most commonly used as `SecureData<String>` coming from the [#securetextfield-component](#securetextfield-component "mention").

```kotlin
data class SecureData<T> internal constructor(
    val data: T,
)
```

### `CreditCardInfoParam`

```kotlin
data class CreditCardInfoParam(
    @ValidateNumberGreaterThanZero
    @ValidateLength(maxLength = 2)
    val expMonth: Int,

    @ValidateNumberGreaterThanZero
    @ValidateLength(maxLength = 4)
    val expYear: Int,

    @ValidateLength(maxLength = 4)
    @ValidateNotBlank
    val csv: String,
)
```

### `AccountHolderDataParam`

```kotlin
data class AccountHolderDataParam(
    @ValidateLength(maxLength = 75)
    @ValidateRegex(regex = FIRST_OR_LAST_NAME)
    val firstName: String? = null,

    @ValidateLength(maxLength = 75)
    @ValidateRegex(regex = FIRST_OR_LAST_NAME)
    val lastName: String? = null,

    @ValidateLength(maxLength = 100)
    @ValidateRegex(regex = COMPANY)
    val company: String? = null,

    val billingAddress: AccountHolderBillingAddressParam,

    @ValidateLength(maxLength = 150)
    @ValidateRegex(regex = EMAIL)
    val email: String? = null,

    @ValidateLength(maxLength = 16)
    @ValidateRegex(regex = ONLY_NUMBERS)
    val phone: String? = null,
)
```

### `AccountHolderBillingAddressParam`

```kotlin
data class AccountHolderBillingAddressParam(
    @ValidateLength(maxLength = 100)
    @ValidateRegex(regex = ADDRESS1)
    @ValidateNotBlank
    val address1: String,

    @ValidateLength(maxLength = 100)
    @ValidateRegex(regex = ADDRESS2)
    val address2: String? = null,

    @ValidateLength(maxLength = 75)
    @ValidateRegex(regex = CITY)
    val city: String? = null,

    @ValidateLength(maxLength = 75)
    @ValidateRegex(regex = COUNTRY_OR_STATE)
    val state: String? = null,

    @ValidateLength(maxLength = 20)
    @ValidateRegex(regex = ZIP_CODE)
    @ValidateNotBlank
    val zip: String,

    @ValidateLength(maxLength = 75)
    @ValidateRegex(regex = COUNTRY_OR_STATE)
    val country: String? = null,
)
```

### `EndCustomerDataParam`

```kotlin
data class EndCustomerDataParam(
    @ValidateLength(maxLength = 75)
    @ValidateRegex(regex = FIRST_OR_LAST_NAME)
    val firstName: String? = null,

    @ValidateLength(maxLength = 75)
    @ValidateRegex(regex = FIRST_OR_LAST_NAME)
    val lastName: String? = null,

    @ValidateLength(maxLength = 100)
    @ValidateRegex(regex = COMPANY)
    val company: String? = null,

    val billingAddress: EndCustomerBillingAddressParam,

    @ValidateLength(maxLength = 150)
    @ValidateRegex(regex = EMAIL)
    val email: String? = null,

    @ValidateLength(maxLength = 16)
    @ValidateRegex(regex = ONLY_NUMBERS)
    val phone: String? = null,
)
```

### EndCustomerBillingAddressParam

```kotlin
data class EndCustomerBillingAddressParam(
    @ValidateLength(maxLength = 100)
    @ValidateRegex(regex = ADDRESS1)
    val address1: String,

    @ValidateLength(maxLength = 100)
    @ValidateRegex(regex = ADDRESS2)
    val address2: String? = null,

    @ValidateLength(maxLength = 75)
    @ValidateRegex(regex = CITY)
    val city: String? = null,

    @ValidateLength(maxLength = 75)
    @ValidateRegex(regex = COUNTRY_OR_STATE)
    val state: String? = null,

    @ValidateLength(maxLength = 20)
    @ValidateRegex(regex = ZIP_CODE)
    val zip: String,

    @ValidateLength(maxLength = 75)
    @ValidateRegex(regex = COUNTRY_OR_STATE)
    val country: String? = null,
)
```

### `AmountsParam`

```kotlin
data class AmountsParam(
    @ValidateNumberGreaterThanZero
    val totalAmount: Double,
    val salesTax: Double? = null,
    val surcharge: Double? = null,
)
```

### PurchaseItemsParam

```kotlin
data class PurchaseItemsParam(
    @ValidateLength(maxLength = 200)
    @ValidateRegex(regex = SERVICE_DESCRIPTION)
    val serviceDescription: String? = null,

    @ValidateLength(maxLength = 75)
    @ValidateRegex(regex = CLIENT_REF_ID_OR_RPGUID)
    val clientRefId: String? = null,

    @ValidateLength(maxLength = 75)
    @ValidateRegex(regex = CLIENT_REF_ID_OR_RPGUID)
    val rpguid: String? = null,
)
```

### `ConsentCreatorParam`

```kotlin
data class ConsentCreatorParam(
    val merchantId: Int,

    @ValidateLength(maxLength = 200)
    @ValidateRegex(regex = RegexPattern.SERVICE_DESCRIPTION)
    val serviceDescription: String? = null,

    @ValidateLength(maxLength = 75)
    @ValidateRegex(regex = RegexPattern.CLIENT_REF_ID_OR_RPGUID)
    val customerReferenceId: String? = null,

    @ValidateLength(maxLength = 75)
    @ValidateRegex(regex = RegexPattern.CLIENT_REF_ID_OR_RPGUID)
    val rpguid: String? = null,
    val startDate: Date,

    @ValidateNumberGreaterThanZero
    val limitPerCharge: Double,

    @ValidateNumberGreaterThanZero
    val limitLifeTime: Double,
)
```

***

## Public methods in the Android SDK

### 1. Charge credit card

This method processes a credit card when the credit card details are entered manually. Details include the card number, expiration date, CVV, card holder name and address.

```kotlin
ChargeCreditCard().chargeCreditCard(params: ChargeCreditCardBodyParams): NetworkResource<ChargeCreditCardResult>
```

REST API equivalent: [/pages/w4UMtcF7UfD7pNPTiZF7#apicardprocrest-v1.0.0-cardsale-manual](https://docs.number.tech/documentation/getting-started/integration-options/pages/w4UMtcF7UfD7pNPTiZF7#apicardprocrest-v1.0.0-cardsale-manual "mention")

#### **Request parameters**

* `ChargeCreditCardBodyParams`
  * `encryptedCardNumber`: [SecureData](#securedata)\<String>
  * `creditCardInfo`: [CreditCardInfoParam](#creditcardinfoparam)
  * `accountHolder`: [AccountHolderDataParam](#accountholderdataparam)
  * `endCustomer`: [EndCustomerDataParam](#endcustomerdataparam)?
  * `amounts`: [AmountsParam](#amountsparam)
  * `purchaseItems`: [PurchaseItemsParam](#purchaseitemsparam)
  * `merchantId`: Int

#### **Response body**

The response body will be serialized to `ChargeCreditCardResult`.

```kotlin
data class ChargeCreditCardResult internal constructor(
    @SerializedName("FunctionOk")
    override val functionOk: Boolean,

    @SerializedName("ErrCode")
    override val errorCode: Int,

    @SerializedName("ErrMsg")
    override val errorMessage: String,

    @SerializedName("RespMsg")
    override val responseMessage: String,

    @SerializedName("TxApproved")
    override val txApproved: Boolean,

    @SerializedName("TxID")
    override val txId: Int,

    @SerializedName("TxnCode")
    override val txCode: String,

    @SerializedName("AVSresult")
    val avsResult: String,

    @SerializedName("AcquirerResponseEMV")
    val acquirerResponseEmv: String?,

    @SerializedName("CVVresult")
    val cvvResult: String,

    @SerializedName("IsPartialApproval")
    val isPartialApproval: Boolean,

    @SerializedName("RequiresVoiceAuth")
    val requiresVoiceAuth: Boolean,

    @SerializedName("ResponseApprovedAmount")
    val responseApprovedAmount: Double,

    @SerializedName("ResponseAuthorizedAmount")
    val responseAuthorizedAmount: Double,

    @SerializedName("ResponseBalanceAmount")
    val responseBalanceAmount: Double,
)
```

### 2. List annual consents

A query that returns annual consent details. Depending on the query sent, a single consent or multiple consents may be returned.

```kotlin
ListAnnualConsents().listAnnualConsents(params: ListAnnualConsentsBodyParams): NetworkResource<ListAnnualConsentsResult>
```

REST API equivalent: [/pages/dBtuA7Sh0aVhjDX09Hut#apicardprocrest-v1.0.0-query-consentannual](https://docs.number.tech/documentation/getting-started/integration-options/pages/dBtuA7Sh0aVhjDX09Hut#apicardprocrest-v1.0.0-query-consentannual "mention")

#### **Request parameters**

* `ListAnnualConsentsBodyParams`

  * `merchantId`: Int?
  * `customerReferenceId`: String?
  * `rpguid`: String?&#x20;

  Either `customerReferenceId` or `rpguid` must be provided to get the list of consents of a specific customer.

#### **Response body**

The response body will be serialized to `ListAnnualConsentsResult`.

```kotlin
data class ListAnnualConsentsResult internal constructor(
    @SerializedName("FunctionOk")
    override val functionOk: Boolean,

    @SerializedName("ErrCode")
    override val errorCode: Int,

    @SerializedName("ErrMsg")
    override val errorMessage: String,

    @SerializedName("RespMsg")
    override val responseMessage: String,

    @SerializedName("NumRecords")
    val numRecords: Int,

    @SerializedName("Consents")
    val consents: List<AnnualConsent>,
)
```

And the `AnnualConsent` looks like the following:

```kotlin
data class AnnualConsent internal constructor(
    @SerializedName("AcctHolderFirstName")
    val accountHolderFirstName: String,

    @SerializedName("AcctHolderID")
    val accountHolderId: Int,

    @SerializedName("AcctHolderLastName")
    val accountHolderLastName: String,

    @SerializedName("AcctNo")
    val accountNumber: String,

    @SerializedName("AuthTxID")
    val authTxId: Int,

    @SerializedName("CreatedBy")
    val createdBy: String,

    @SerializedName("CreatedOn")
    var createdOn: String,

    @SerializedName("CustID")
    val customerId: Int,

    @SerializedName("CustomerRefID")
    val customerReferenceId: String,

    @SerializedName("EndDate")
    var endDate: String,

    @SerializedName("ID")
    val id: Int,

    @SerializedName("IsEnabled")
    val isEnabled: Boolean,

    @SerializedName("LimitLifeTime")
    val limitLifeTime: Double,

    @SerializedName("LimitPerCharge")
    val limitPerCharge: Double,

    @SerializedName("MerchID")
    val merchId: Int,

    @SerializedName("NumDays")
    val numDays: Int,

    @SerializedName("RPGUID")
    val rpguid: String,

    @SerializedName("ServiceDescrip")
    val serviceDescription: String,

    @SerializedName("StartDate")
    var startDate: String,
)
```

### 3. Create annual consent

This method creates an annual consent by sending the credit card details, which include: card number, expiration date, CVV, and card holder contact data. It is **not** created by swiping the card through a reader device.

```kotlin
CreateAnnualConsent().createAnnualConsent(params: CreateAnnualConsentBodyParams): NetworkResource<CreateAnnualConsentResult>
```

REST API equivalent: [/pages/2Pdm0t88TPo3URCjHoXS#apicardprocrest-v1.0.0-consentannual-create\_man](https://docs.number.tech/documentation/getting-started/integration-options/pages/2Pdm0t88TPo3URCjHoXS#apicardprocrest-v1.0.0-consentannual-create_man "mention")

#### **Request parameters**

* `CreateAnnualConsentBodyParams`
  * `encryptedCardNumber`: [SecureData](#securedata)\<String>
  * `creditCardInfo`: [CreditCardInfoParam](#creditcardinfoparam)
  * `accountHolder`: [AccountHolderDataParam](#accountholderdataparam)
  * `endCustomer`: [EndCustomerDataParam](#endcustomerdataparam)?
  * `consentCreator`: [ConsentCreatorParam](#consentcreatorparam)

#### **Response body**

The response body will be serialized to `CreateAnnualConsentResult`.

```kotlin
data class CreateAnnualConsentResult internal constructor(
    @SerializedName("FunctionOk")
    override val functionOk: Boolean,

    @SerializedName("ErrCode")
    override val errorCode: Int,

    @SerializedName("ErrMsg")
    override val errorMessage: String,

    @SerializedName("RespMsg")
    override val responseMessage: String,

    @SerializedName("ConsentID")
    val consentId: Int,

    @SerializedName("CreationSuccess")
    val creationSuccess: Boolean,

    @SerializedName("PreConsentAuthMessage")
    val preConsentAuthMessage: String,

    @SerializedName("PreConsentAuthSuccess")
    val preConsentAuthSuccess: Boolean,

    @SerializedName("PreConsentAuthTxID")
    val preConsentAuthTxId: Int,
)
```

### 4. Cancel annual consent

Cancels an annual consent. Credit card data is removed from the system after the cancellation is complete.

```kotlin
CancelAnnualConsent().cancelAnnualConsent(params: CancelAnnualConsentBodyParams): NetworkResource<CancelAnnualConsentResult>
```

REST API equivalent: [/pages/pXZvz0HlPUC590yAuLhj#apicardprocrest-v1.0.0-consentannual-cancel](https://docs.number.tech/documentation/getting-started/integration-options/pages/pXZvz0HlPUC590yAuLhj#apicardprocrest-v1.0.0-consentannual-cancel "mention")

#### **Request parameters**

* `CancelAnnualConsentBodyParams`
  * `consentId`: Int

#### **Response body**

The response body will be serialized to `CancelAnnualConsentResult`.

```kotlin
data class CancelAnnualConsentResult internal constructor(
    @SerializedName("FunctionOk")
    override val functionOk: Boolean,

    @SerializedName("ErrCode")
    override val errorCode: Int,

    @SerializedName("ErrMsg")
    override val errorMessage: String,

    @SerializedName("RespMsg")
    override val responseMessage: String,

    @SerializedName("CancelSuccess")
    val cancelSuccess: Boolean,

    @SerializedName("CancelledConsentID")
    val cancelledConsentId: Int,
)
```

### 5. Process payment for an annual consent

This method uses the credit card stored on file to process a payment for an existing consent.

```kotlin
ProcessPaymentAnnual().processPaymentAnnual(params: ProcessPaymentAnnualBodyParams): NetworkResource<ProcessPaymentAnnualResult>
```

REST API equivalent: [/pages/pXZvz0HlPUC590yAuLhj#apicardprocrest-v1.0.0-consentannual-procpayment](https://docs.number.tech/documentation/getting-started/integration-options/pages/pXZvz0HlPUC590yAuLhj#apicardprocrest-v1.0.0-consentannual-procpayment "mention")

#### **Request parameters**

* `ProcessPaymentAnnualBodyParams`
  * `consentId`: Int

#### **Response body**

The response body will be serialized to `ProcessPaymentAnnualResult`.

```kotlin
data class ProcessPaymentAnnualResult internal constructor(
    @SerializedName("FunctionOk")
    override val functionOk: Boolean,

    @SerializedName("ErrCode")
    override val errorCode: Int,

    @SerializedName("ErrMsg")
    override val errorMessage: String,

    @SerializedName("RespMsg")
    override val responseMessage: String,

    @SerializedName("TxApproved")
    override val txApproved: Boolean,

    @SerializedName("TxID")
    override val txId: Int,

    @SerializedName("TxnCode")
    override val txCode: String,

    @SerializedName("AVSresult")
    val avsResult: String,

    @SerializedName("AcquirerResponseEMV")
    val acquirerResponseEmv: String?,

    @SerializedName("CVVresult")
    val cvvResult: String,

    @SerializedName("IsPartialApproval")
    val isPartialApproval: Boolean,

    @SerializedName("RequiresVoiceAuth")
    val requiresVoiceAuth: Boolean,

    @SerializedName("ResponseApprovedAmount")
    val responseApprovedAmount: Double,

    @SerializedName("ResponseAuthorizedAmount")
    val responseAuthorizedAmount: Double,

    @SerializedName("ResponseBalanceAmount")
    val responseBalanceAmount: Double,
)
```

***

## How to properly consume the API response

All requests are suspended functions, so they should be called from coroutine scope. The result of the request is wrapped in a `NetworkResource` object, which can be handled in the following way:

```kotlin
viewModelScope.launch {
    // Example of suspended function call
    val result = ChargeCreditCard().chargeCreditCard(params)
    when (result) {
        is NetworkResource.Status.SUCCESS -> {
            // Handle success
        }
        is NetworkResource.Status.ERROR -> {
            // Handle error
        }
        is NetworkResource.Status.DECLINED -> {
            // Handle declined
        }
    }
}
```

***

## Possible exceptions

### EasyPaySdkException

Exceptions that are thrown by the SDK.

<table><thead><tr><th width="342">Exception name</th><th>Suggested solution</th></tr></thead><tbody><tr><td><code>EASY_PAY_CONFIGURATION_NOT_INITIALIZED</code></td><td>Check if <code>EasyPay.init(...)</code> method has been called.</td></tr><tr><td><code>MISSED_SESSION_KEY</code></td><td>Check if correct <code>SESSION_KEY</code> has been provided in the <code>EasyPay.init(...)</code> method.</td></tr><tr><td><code>MISSED_HMAC_SECRET</code></td><td>Check if correct <code>HMAC_SECRET</code> has been provided in the <code>EasyPay.init(...)</code> method.</td></tr><tr><td><code>RSA_CERTIFICATE_NOT_FETCHED</code></td><td>RSA certificate might not be fetched yet. Check the status by calling the <code>EasyPayConfiguration.getInstance().getRsaCertificateFetchingStatus()</code> method.</td></tr><tr><td><code>RSA_CERTIFICATE_FETCH_FAILED</code></td><td>Contact Number.</td></tr><tr><td><code>RSA_CERTIFICATE_PARSING_ERROR</code></td><td>Contact Number.</td></tr></tbody></table>

### EasyPayApiException

Exceptions that are thrown by the Number API.

***

## Semantic versioning

The SDK follows semantic versioning with a three-part version number: `MAJOR`.`MINOR`.`PATCH`.

* `MAJOR` version is incremented when there are incompatible API changes,
* `MINOR` version is incremented when functionality is added in a backwards-compatible manner,
* `PATCH` version is incremented when there are backwards-compatible bug fixes.

***

## Feature flags

### Rooted device detection

To enable rooted device detection, call the following method before calling `EasyPay.init(...)`:

```kotlin
EasyPayFeatureFlagManager.setRootedDeviceDetectionEnabled(true)
```


# Ingenico

#### Getting Started

This guide will help you quickly get started with your Ingenico card reader using our API. You'll learn how to connect and configure your device, establish secure communication, and begin processing transactions. If you prefer not to build an API integration, you can use our Virtual Terminal to process EMV transactions with your Ingenico card reader.

#### **Install the Certificate**

Once the device is powered on and connected to the network, its certificate needs to be loaded into the browser. Complete instructions are available at [Download and Install](/documentation/getting-started/integration-options/ingenico/certificate-installation) certificates.

#### **Authenticate and retrieve a session key**

After you authenticate with your AccountCode and Token, the backend returns a SessKey. This key is required to prove identity on subsequent REST API methods (passed as a SessKey header). For more information, view the [authentication](https://docs.number.tech/documentation/getting-started/basics/authentication) section of the site.

#### **View the demo site and code samples**

Code examples and endpoint references are provided to help you implement authorization, card payments, saved cards, device configuration and error handling.

The sample site is located at <https://easypay1.com/ingenicodemo>. The site can also be downloaded at [ingenicodemo.zip](https://easypay1.com/ingenicodemo/ingenicodemo.zip)

#### Virtual Terminal

You can use our Virtual Terminal with your Ingenico device, which includes built-in support for EMV transaction processing. This eliminates the need to build your own user interface or write any code. After connecting the device to your network and installing the required certificate, contact Number to have this feature activated.

You can read more about using the Virtual Terminal in the [Virtual Terminal](https://docs.number.tech/documentation/getting-started/integration-options/virtual-terminal) guide.


# Certificate Installation

How to Download and Install by Operating System

#### **Download the Certificate**

To install the SSL certificate for your browsers, start by downloading the installer package at <https://easypay1.com/ingenicodemo/certificate/IngenicoCerts.zip>. After the package is unzipped, run the installer that corresponds with your system.

#### **Method by Operating System**

**Windows (Chrome/Edge)**

Right click on `Install-EasyPayRoot.cmd` and run as Administrator. This file will install the EasyPayRoot.crt certificate and install the bonjour service if necessary.

***

**macOS (Safari/Chrome)**

Run the install-easy-pay-root shell script from the terminal:

```
bash install-easypay-root.sh
```

***

**Linux**

Run the install-easy-pay-root shell script from the terminal:

```
bash install-easypay-root.sh
```


# Process a Card Sale

The transact API call processes a payment and optionally stores the card for future use.

**This sample shows charging a payment without saving the card.**

<mark style="color:orange;">POST</mark> https\://`[your-terminal-ip]`:8090/transact\
SessKey: `[your-session-key]`\
Content-Type: application/json

#### Response Status Codes

* 200 OK - Transaction submitted successfully. This does not mean the transaction was approved and processed; see the error handling section for more information.
* 401 Unauthorized - Missing or invalid SessKey
* 400 Bad Request - Invalid request format
* 500 Internal Server Error - Processing error

#### Error Handling

Please view our [API Best Practices](https://docs.number.tech/documentation/getting-started/basics/api-best-practices) guide for information on handling errors, logging responses, and checking for declines.

{% tabs %}
{% tab title="Sample Request" %}

```
{
  "MerchID": 1,
  "SaveCard": 0,
  "AcctHolder": {
    "Firstname": "Fred",
    "Lastname": "Smith",
    "Company": "",
    "Title": "",
    "Url": "",
    "BillingAddress": {
      "Address1": "1307 Broad Hollow Road",
      "Address2": "",
      "City": "",
      "State": "",
      "ZIP": "11747",
      "Country": "USA"
    },
    "Email": "tester@easypaysolutions.com",
    "Phone": "8777248472"
  },
  "Amounts": {
    "BaseAmt": 20.00,
    "Surcharge": 0,
    "TotalAmt": 20.00,
    "ConfirmTotalAmt": true
  },
  "Refdata": {
    "ServiceDesc": "Throat Culture",
    "ClientRefID": "1876345",
    "RPGuid": "dcaa9ac0-71a8-4dd4-ad2f-fbe107d1e789",
    "POSUser": "Sally Smith"
  }
}
```

{% endtab %}

{% tab title="Sample Response" %}

```

{
  "CreditCardSaleCompositeResult": {
    "AVSresult": "U",
    "AcquirerResponseEMV": "8A023030910A2C2DD8CE50C3BBFD3030",
    "CVVresult": "",
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "IsPartialApproval": false,
    "RequiresVoiceAuth": false,
    "RespMsg": "APPROVED 534551",
    "ResponseApprovedAmount": 0,
    "ResponseAuthorizedAmount": 20,
    "ResponseBalanceAmount": 0,
    "TxApproved": true,
    "TxID": 21964,
    "TxnCode": "534551",
    "ConsentResult": {
      "CardLast4": "",
      "ConsentCreated": false, 
      "ConsentID": 0,
      "ConsentRequested": false,
      "ErrCode": 0,
      "ErrMsg": "",
      "ExpDate": ""
    }
  }
 }
```

{% endtab %}

{% tab title="Header Parameters" %}
A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}

* **MerchID** (integer, required) - Merchant identification number&#x20;
* **SaveCard** (integer, required) - Card storage flag (0 or 1). Use 1 to store the card for future card not present transactions.
* **AcctHolder** (object, required) - Cardholder and billing information - **Amounts** (object, required) - Transaction amount details:
* **BaseAmt** (number, required) - Base transaction amount - **Surcharge** (number, required) - Surcharge/fee amount. You may supply a fee but only if these have been properly configured for each merchant record.
* **TotalAmt** (number, required) - Total amount (BaseAmt + Surcharge)
* **ConfirmTotalAmt** (boolean, optional, default: false) - If true, the customer will be shown an approve amount button on the Ingenico device.
* **Refdata** (object, required) - Reference data for transaction tracking:
* **ServiceDesc** (string) - Description of service/product
* **ClientRefID** (string) - Client reference identifier
* **RPGuid** (string) - Unique transaction GUID
* **POSUser** (string) - POS user/operator name
  {% endtab %}
  {% endtabs %}

{% hint style="info" %}
IMPORTANT : Always check your response to determine the fees and final amoount which are approved as this may differ from what was requested. The ResponseAuthorizedAmount element shows the amount that was charged.
{% endhint %}


# Process a Combination Payment

The transact API call processes a payment and optionally stores the card for future use.

**This sample shows processing a payment and saving the card**. Look at the sample response tab to view the ConsentResult element.

<mark style="color:orange;">POST</mark> https\://`[your-terminal-ip]`:8090/transact\
SessKey: `[your-session-key]`\
Content-Type: application/json

#### Response Status Codes

* 200 OK - Transaction submitted successfully. This does not mean the transaction was approved and processed; see the error handling section for more information.
* 401 Unauthorized - Missing or invalid SessKey
* 400 Bad Request - Invalid request format
* 500 Internal Server Error - Processing error

#### Error Handling

Please view our [API Best Practices](https://docs.number.tech/documentation/getting-started/basics/api-best-practices) guide for information on handling errors, logging responses, and checking for declines.

* Sample Request
* Sample Response
* Header Parameters
* Body

{% tabs %}
{% tab title="Sample Request" %}

```
{
  "MerchID": 1,
  "SaveCard": 1,
  "AcctHolder": {
    "Firstname": "Fred",
    "Lastname": "Smith",
    "Company": "",
    "Title": "",
    "Url": "",
    "BillingAddress": {
      "Address1": "1307 Broad Hollow Road",
      "Address2": "",
      "City": "",
      "State": "",
      "ZIP": "11747",
      "Country": "USA"
    },
    "Email": "tester@easypaysolutions.com",
    "Phone": "8777248472"
  },
  "Amounts": {
    "BaseAmt": 20.00,
    "Surcharge": 0,
    "TotalAmt": 20.00,
    "ConfirmTotalAmt": true
  },
  "Refdata": {
    "ServiceDesc": "Throat Culture",
    "ClientRefID": "1876345",
    "RPGuid": "dcaa9ac0-71a8-4dd4-ad2f-fbe107d1e789",
    "POSUser": "Sally Smith"
  }
}
```

{% endtab %}

{% tab title="Sample Response" %}

```
{
  "CreditCardSaleCompositeResult": {
    "AVSresult": "U",
    "AcquirerResponseEMV": "8A0230309F36020001",
    "CVVresult": "",
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "IsPartialApproval": false,
    "RequiresVoiceAuth": false,
    "RespMsg": "APPROVED 784823",
    "ResponseApprovedAmount": 0,
    "ResponseAuthorizedAmount": 20,
    "ResponseBalanceAmount": 0,
    "TxApproved": true,
    "TxID": 22469,
    "TxnCode": "784823",
    "ConsentResult": {
      "CardLast4": "0027",
      "ConsentCreated": true,
      "ConsentID": 7889,
      "ConsentRequested": true,
      "ErrCode": 0,
      "ErrMsg": "",
      "ExpDate": "1231"
    }
  }
 }
```

{% code overflow="wrap" %}

```
IMPORTANT: Always check your response to determine the fees which are approved as this may differ from what was requested. The ResponseAuthorizedAmount element shows the amount that was charged.
```

{% endcode %}
{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}

* **MerchID** (integer, required) - Merchant identification number&#x20;
* **SaveCard** (integer, required) - Card storage flag (0 or 1). Use 1 to store the card for future card not present transactions.
* **AcctHolder** (object, required) - Cardholder and billing information - **Amounts** (object, required) - Transaction amount details:
* **BaseAmt** (number, required) - Base transaction amount - **Surcharge** (number, required) - Surcharge/fee amount. You may supply a fee but only if these have been properly configured for each merchant record.
* **TotalAmt** (number, required) - Total amount (BaseAmt + Surcharge)
* **ConfirmTotalAmt** (boolean, optional, default: false) - If true, the customer will be shown an approve amount button on the Ingenico device.
* **Refdata** (object, required) - Reference data for transaction tracking:
* **ServiceDesc** (string) - Description of service/product
* **ClientRefID** (string) - Client reference identifier
* **RPGuid** (string) - Unique transaction GUID
* **POSUser** (string) - POS user/operator name
  {% endtab %}
  {% endtabs %}


# Stored Card Only

The transact API call processes a payment and optionally stores the card for future use.

**This sample shows saving the card without processing a payment***.*&#x20;

{% hint style="info" %}
To save the card without processing a payment, set all of the request amount fields to zero and turn on the SaveCard flag. View the Sample Request tab for a complete example.
{% endhint %}

<mark style="color:orange;">POST</mark> https\://`[your-terminal-ip]`:8090/transact\
SessKey: `[your-session-key]`\
Content-Type: application/json

#### Response Status Codes

* 200 OK - Transaction submitted successfully. This does not mean the transaction was approved and processed; see the error handling section for more information.
* 401 Unauthorized - Missing or invalid SessKey
* 400 Bad Request - Invalid request format
* 500 Internal Server Error - Processing error

#### Error Handling

Please view our [API Best Practices](https://docs.number.tech/documentation/getting-started/basics/api-best-practices) guide for information on handling errors, logging responses, and checking for declines.

{% tabs %}
{% tab title="Sample Request" %}
{% code overflow="wrap" %}

```
{
  "MerchID": 2,
  "SaveCard": 1,
  "AcctHolder": {
    "Firstname": "Fred",
    "Lastname": "Smith",
    "Company": "",
    "Title": "",
    "Url": "",
    "BillingAddress": {
      "Address1": "1307 Broad Hollow Road",
      "Address2": "",
      "City": "",
      "State": "",
      "ZIP": "11747",
      "Country": "USA"
    },
    "Email": "tester@easypaysolutions.com",
    "Phone": "8777248472"
  },
  "Amounts": {
    "BaseAmt": 0,
    "Surcharge": 0,
    "TotalAmt": 0,
    "ConfirmTotalAmt": false
  },
  "Refdata": {
    "ServiceDesc": "Throat Culture",
    "ClientRefID": "1876345",
    "RPGuid": "dcaa9ac0-71a8-4dd4-ad2f-fbe107d1e789",
    "POSUser": "Sally Smith"
  }
}
```

{% endcode %}
{% endtab %}

{% tab title="Sample Response" %}

```
{
  "CreditCardSaleCompositeResult": {
    "AVSresult": null,
    "AcquirerResponseEMV": null,
    "CVVresult": null,
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "IsPartialApproval": false,
    "RequiresVoiceAuth": false,
    "RespMsg": "APPROVED 593742|CVV||AVS|",
    "ResponseApprovedAmount": 0,
    "ResponseAuthorizedAmount": 0,
    "ResponseBalanceAmount": 0,
    "TxApproved": true,
    "TxID": 22475, "TxnCode": null,
    "ConsentResult": {
      "CardLast4": "0885",
      "ConsentCreated": true,
      "ConsentID": 7891,
      "ConsentRequested": true,
      "ErrCode": 0,
      "ErrMsg": "",
      "ExpDate": "1249"
    }
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}

* **MerchID** (integer, required) - Merchant identification number
* **SaveCard** (integer, required) - Card storage flag (0 or 1). *Use 1 to store the card for future card not present transactions.*
* **AcctHolder** (object, required) - Cardholder and billing information
* **Amounts** (object, required) - Transaction amount details:
* **BaseAmt** (number, required) - Base transaction amount
* **Surcharge** (number, required) - Surcharge/fee amount. You may supply a fee but only if these have been properly configured for each merchant record.
* **TotalAmt** (number, required) - Total amount (BaseAmt + Surcharge)
* **ConfirmTotalAmt** (boolean, optional, default: false) - If true, the customer will be shown an approve amount button on the Ingenico device.
* **Refdata** (object, required) - Reference data for transaction tracking: - **ServiceDesc** (string) - Description of service/product
* **ClientRefID** (string) - Client reference identifier
* **RPGuid** (string) - Unique transaction GUID
* **POSUser** (string) - POS user/operator name
  {% endtab %}
  {% endtabs %}


# Get Device Configuration

Retrieves the current configuration settings.

<mark style="color:orange;">GET</mark> https\://`[your-terminal-ip]`:8090/config\
Content-Type: application/json

#### Response Status Codes

* 200 OK - Configuration retrieved successfully.

{% tabs %}
{% tab title="Sample Request" %}
None needed. There is no body for this request.
{% endtab %}

{% tab title="Sample Response" %}

```
 {
    "basePath": "https://easypay5.com/APIcardProcNumber/v1.0.0",
    "saleFromDevicePath": "/CardSale/FDevice",
    "voidPath": "/CardSale/Void",
    "enableEmvDebug": false,
    "transactionTimeout": 60,
    "errorDisplayDuration": 5,
    "approvalDisplayDuration": 4
  }
```

{% endtab %}

{% tab title="Header Parameters" %}
None needed.
{% endtab %}

{% tab title="Body" %}

<table><thead><tr><th width="186.79998779296875">Field</th><th width="109.199951171875">Type</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td>basePath</td><td>string</td><td>Base URL for payment gateway API</td><td>https://easypay5.com/APIcardProcNumber/v1.0.0</td></tr><tr><td>saleFromDevicePath</td><td>string</td><td>Path appended to basePath for sale transactions</td><td>/CardSale/FDevice</td></tr><tr><td>voidPath</td><td>string</td><td>Path appended to basePath for void/reversal transactions</td><td>/CardSale/Void</td></tr><tr><td>enableEmvDebug</td><td>boolean</td><td>Include EMV tags in transaction responses for debugging</td><td>false</td></tr><tr><td>transactionTimeout</td><td>integer</td><td>Card presentation timeout in seconds</td><td>60</td></tr><tr><td>errorDisplayDuration</td><td>integer</td><td>Duration to display error messages on terminal (seconds)</td><td>5</td></tr><tr><td>approvalDisplayDuration</td><td>integer</td><td>Duration to display approval message on terminal (seconds)</td><td>4</td></tr></tbody></table>
{% endtab %}
{% endtabs %}


# Set Device Configuration

Updates the middleware runtime configuration settings.  Changes take effect immediately for subsequent transactions.

{% hint style="info" %}
All fields are optional; send only the fields you want to update.
{% endhint %}

<mark style="color:orange;">POST</mark> https\://`[your-terminal-ip]`:8090/config\
Content-Type: application/json

#### Response Status Codes

* 200 OK - Configuration updated successfully.
* 400 Bad Request - Invalid JSON or field values

{% tabs %}
{% tab title="Sample Request" %}

```
{
    "basePath": "https://easypay5.com/APIcardProcNumber/v1.0.0",
    "saleFromDevicePath": "/CardSale/FDevice",
    "voidPath": "/CardSale/Void",
    "enableEmvDebug": false,
    "transactionTimeout": 60,
    "errorDisplayDuration": 5,
    "approvalDisplayDuration": 4
  }
```

**Partial update example**

Enable debug mode and increase timeout:

```

      {
        "enableEmvDebug": true,
        "transactionTimeout": 120
      }
```

{% endtab %}

{% tab title="Sample Response" %}
Returns the complete current configuration after update:

```

  {
    "basePath": "https://easypay5.com/APIcardProcNumber/v1.0.0",
    "saleFromDevicePath": "/CardSale/FDevice",
    "voidPath": "/CardSale/Void",
    "enableEmvDebug": false,
    "transactionTimeout": 60,
    "errorDisplayDuration": 5,
    "approvalDisplayDuration": 4
  }
```

{% endtab %}

{% tab title="Header Parameters" %}
None needed.
{% endtab %}

{% tab title="Body" %}

<table><thead><tr><th width="194">Field</th><th width="87.20001220703125">Type</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td>basePath</td><td>string</td><td>Base URL for payment gateway API</td><td>https://easypay5.com/APIcardProcNumber/v1.0.0</td></tr><tr><td>saleFromDevicePath</td><td>string</td><td>Path appended to basePath for sale transactions</td><td>/CardSale/FDevice</td></tr><tr><td>voidPath</td><td>string</td><td>Path appended to basePath for void/reversal transactions</td><td>/CardSale/Void</td></tr><tr><td>enableEmvDebug</td><td>boolean</td><td>Include EMV tags in transaction responses for debugging</td><td>false</td></tr><tr><td>transactionTimeout</td><td>integer</td><td>Card presentation timeout in seconds</td><td>60</td></tr><tr><td>errorDisplayDuration</td><td>integer</td><td>Duration to display error messages on terminal (seconds)</td><td>5</td></tr><tr><td>approvalDisplayDuration</td><td>integer</td><td>Duration to display approval message on terminal (seconds)</td><td>4</td></tr></tbody></table>
{% endtab %}
{% endtabs %}


# Reset the Device

Sends a reset command to the terminal device, cancelling any active transaction and returning the device to idle state.

<mark style="color:orange;">POST</mark> https\://`[your-terminal-ip]`:8090/reset\
Content-Type: application/json

#### Response Status Codes

* 200 OK - Reset command sent successfully.

{% tabs %}
{% tab title="Sample Request" %}
None needed. There is no body for this request.
{% endtab %}

{% tab title="Sample Response" %}
{% code overflow="wrap" %}

```
{
    "status": "OK",
    "message": "Device reset command sent"
}
```

{% endcode %}
{% endtab %}

{% tab title="Header Parameters" %}
None needed.
{% endtab %}
{% endtabs %}


# Check Device Status

This health check endpoint returns the status of the device.

<mark style="color:orange;">GET</mark> https\://`[your-terminal-ip]`:8090/status\
Content-Type: application/json

#### Response Status Codes

* 200 OK - System is operational.

{% tabs %}
{% tab title="Sample Request" %}
None needed. There is no body for this request.
{% endtab %}

{% tab title="Sample Response" %}

<pre><code>{
  "status": "OK",
  "message": "EasyPay Middleware is running",
  "buildNumber": "1.0",
  "terminal": {
    "model": "DX4000",
    "serialNumber": "242HMD438023",
    "manufacturer": "ingenico",
    "sdkVersion": "USDK V13.15.0-20241204"
  },
  "firmware": {
<strong>    "version": "AND-Q4-ALPHA 1.18.0",
</strong>    "androidOS": "10",
    "securityFirmware": "N11.11.11.00018"
  },
  "arc": {
    "appName": "AXIUM Retail Core",
    "appVersion": "24.05.01-0002-axium-iws",
    "arclibVersion": "24.05.01-0002-axium"
  },
  "hardware": {
    "contactlessReader": true,
    "smartCardReader": true,
    "msrReader": true
  },
  "memory": {
    "totalRamMB": 1867,
    "availableRamMB": 1003,
    "totalFlashMB": 14910,
    "availableFlashMB": 10095
  },
  "health": {
    "batteryLevel": "99",
    "chargingState": "Full",
    "reboots": "147",
    "cardSwipes": "71",
    "chipInsertions": "385"
  }
}
</code></pre>

{% endtab %}

{% tab title="Header Parameters" %}
None needed.
{% endtab %}

{% tab title="Body" %}

<table><thead><tr><th width="281.00006103515625">Field</th><th>Description</th></tr></thead><tbody><tr><td>status</td><td>System status ("OK" when operational)</td></tr><tr><td>message</td><td>Human-readable status message</td></tr><tr><td>buildNumber</td><td>Middleware build version</td></tr><tr><td>terminal.model</td><td>Terminal hardware model</td></tr><tr><td>terminal.serialNumber</td><td>Device serial number</td></tr><tr><td>terminal.manufacturer</td><td>Terminal manufacturer</td></tr><tr><td>terminal.sdkVersion</td><td>Ingenico USDK version</td></tr><tr><td>firmware.version</td><td>Terminal firmware version</td></tr><tr><td>firmware.androidOS</td><td>Android OS version</td></tr><tr><td>firmware.securityFirmware</td><td>Security firmware version</td></tr><tr><td>arc.appName</td><td>ARC application name</td></tr><tr><td>arc.appVersion</td><td>ARC application version</td></tr><tr><td>arc.arclibVersion</td><td>ARC library version</td></tr><tr><td>hardware.contactlessReader</td><td>NFC/contactless reader available</td></tr><tr><td>hardware.smartCardReader</td><td>EMV chip reader available</td></tr><tr><td>hardware.msrReader</td><td>Magnetic stripe reader available</td></tr><tr><td>memory.totalRamMB</td><td>Total RAM in megabytes</td></tr><tr><td>memory.availableRamMB</td><td>Available RAM in megabytes</td></tr><tr><td>memory.totalFlashMB</td><td>Total flash storage in megabytes</td></tr><tr><td>memory.availableFlashMB</td><td>Available flash storage in megabytes</td></tr><tr><td>health.batteryLevel</td><td>Battery percentage (0-100)</td></tr><tr><td>health.chargingState</td><td>Charging status (Full, Charging, Discharging)</td></tr><tr><td>health.reboots</td><td>Total device reboot count</td></tr><tr><td>health.cardSwipes</td><td>Total MSR swipe count</td></tr><tr><td>health.chipInsertions</td><td>Total chip insertion count</td></tr></tbody></table>
{% endtab %}
{% endtabs %}


# iOS SDK

Getting started with iOS SDK for Number

The EasyPay iOS SDK offers access to the Number API for effortless integration with any iOS application. For Android integration, refer to the [Android SDK integration guide](/documentation/getting-started/integration-options/android-sdk).

***

## Installation

### Requirements

* Xcode 15 or above
* Compatible with iOS 13.0 or above

### Configuration

{% stepper %}
{% step %}
Setup with Swift Package Manager

```swift
.package(url: "https://github.com/Easy-Pay-Solutions/Mobile-SDK-IOS.git", from: "1.0.6")
```

{% endstep %}

{% step %}
Setup with Cocoapods

```ruby
pod 'EasyPay'
```

{% endstep %}
{% endstepper %}

***

## Get started

### Integration

{% stepper %}
{% step %}
Prerequisites - get HMAC secret, API key and optional Sentry DSN from Number.
{% endstep %}

{% step %}

{% endstep %}

{% step %}
During the initialization, the process of downloading the certificate is starting. Proceeding with any call before downloading has finished will result in an error `RsaCertificateError.failedToLoadCertificateData`.&#x20;

You can check the status of downloading by accessing the following enum:

```swift
EasyPay.shared.certificateStatus
```

{% endstep %}

{% step %}
To enable jailbreak detection, please set `isProduction = true` when initializing the library and add the following URL schemes to main `Info.plist`.

```xml
<key>LSApplicationQueriesSchemes</key>
<array>
    <string>undecimus</string>
    <string>sileo</string>
    <string>zbra</string>
    <string>filza</string>
    <string>activator</string>
</array>
```

{% endstep %}
{% endstepper %}

### Using widgets

Number's prebuilt payment UI components allow you to collect and process credit card information and payments in a secure way.

#### Managing cards

For managing saved cards without paying, the following initializer should be used:

```swift
 CardSelectionViewController(selectionDelegate: AnyObject, preselectedCardId: Int?, paymentDetails: AddAnnualConsentWidgetModel) throws
```

`preselectedCardId` is an optional parameter that allows to mark a card as selected by passing the `ConsentId` of this card. If nil or incorrect, the selection will be ignored.

`paymentDetails` parameter is used for passing additional payment details not visible for the end user. Either `customerReferenceId` or `rpguid` must be provided to get the list of consents of a specific customer. In case of of incorrect initialization data, `CardSelectionViewControllerInitError` will be thrown.

If you would like to receive callbacks, conform to `CardSelectionDelegate` with following methods:

```swift
func didSelectCard(consentId: String) {}
```

```swift
func didDeleteCard(consentId: Int, success: Bool) {}
```

```swift
func didSaveCard(consentId: Int?, 
                 expMonth: Int?,
                 expYear: Int?,
                 last4digits: String?,
                 success: Bool)  {}
```

#### Managing cards and payment

For managing saved cards and paying, following initializer should be used:

```swift
CardSelectionViewController(amount: String, paymentDelegate: AnyObject, preselectedCardId: Int?, paymentDetails: AddAnnualConsentWidgetModel) throws
```

`amount` should be higher than 0 and it is required parameter.

`preselectedCardId` is an optional parameter that allows to mark a card as selected by passing the `ConsentId` of this card. If nil or incorrect, the selection will be ignored.

`paymentDetails` parameter is used for passing additional payment details not visible for the end user. Either `customerReferenceId` or `rpguid` must be provided to get the list of consents of a specific customer. In case of of incorrect initialization data, `CardSelectionViewControllerInitError` will be thrown.

If you would like to receive callbacks, conform to `CardPaymentDelegate` with following methods:

```swift
func didPayWithCard(consentId: Int?, paymentData: PaymentData?, success: Bool) {}
```

```swift
func didDeleteCard(consentId: Int, success: Bool) {}
```

### Screenshots

#### **Save Card**

<figure><img src="/files/axt8P3stn8aLAb00yd9a" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/23WtkCsNn8pkhM7YCf9E" alt=""><figcaption></figcaption></figure>

#### **Manage Cards**

<figure><img src="/files/0WlWgubPEfjaX00AkbY4" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/tVOs8TUXRj2YFJmoTXqX" alt=""><figcaption></figcaption></figure>

#### **Store and Pay**

<figure><img src="/files/M5YmOsUr87w8XH11Qu9e" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/gZ6dTQVBXDgeVKUZjSJ0" alt=""><figcaption></figcaption></figure>

***

## Common components

### SecureTextField component

The SDK's widgets use a component called `SecureTextField` which ensures a safe input of credit card numbers. It is a subclass of `UITextField` which enables freedom of styling as needed.

Setting up requires configuring the certificate once it was downloaded to encrypt credit card data.

```swift
nameOfYourTextField.setupConfig(EasyPay.shared.config)
```

To receive the encrypted card string required to send to the API, you can use the following method:

```swift
nameOfYourTextField.encryptCardData()
```

{% hint style="info" %}
Data in the SecureTextField component is already encrypted and can be used in the API calls without any additional encryption.
{% endhint %}

***

## Common objects

Below you'll find code describing some of the objects that are commonly used in requests or responses. You can use it as a reference. The code includes parameter names and types.

### `CreditCardInfo`

The object consists of the following fields:

```swift
let accountNumber: String //credit card number encoded in base 64
let expirationMonth: Int?
let expirationYear: Int?
let cvv: String
```

### `AccountHolder`

The object consists of the following fields:

```swift
let firstName: String
let lastName: String
let company: String?
let billingAddress: BillingAddress
let email: String?
let phone: String?
```

### `BillingAddress`

The object consists of the following fields:

```swift
let address1: String
let address2: String?
let city: String?
let state: String?
let zip: String
let country: String?
```

### `EndCustomer`

The object consists of the following fields:

```swift
let firstName: String?
let lastName: String?
let company: String?
let billingAddress: EndCustomerBillingAddress?
let email: String?
let phone: String?
```

### `EndCustomerBillingAddress`

The object consists of the following fields:

```swift
let address1: String?
let address2: String?
let city: String?
let state: String?
let zip: String?
let country: String?
```

### `Amounts`

The object consists of the following fields:

```swift
let totalAmount: String
let salesAmount: String?
let surcharge: String?
```

### `PurchItems`

The object consists of the following fields:

```swift
let serviceDescription: String?
let clientRefId: String?
let rpguid: String?
```

### `CreateConsentAnnual`

The object consists of the following fields:

```swift
let merchID: Int?
let customerRefID: String?
let serviceDescrip: String?
let rpguid: String?
let startDate: String //Timestamp in milliseconds in format \/Date(1710936735853)\/
let limitPerCharge: String
let limitLifeTime: String
```

### `AnnualEndCustomer`

The object consists of the following fields:

```swift
let firstName: String?
let lastName: String?
let company: String?
let billingAddress: AnnualEndCustomerBillingAddress?
let email: String?
let phone: String?
```

### `AnnualEndCustomerBillingAddress`

The object consists of the following fields:

```swift
let address1: String?
let address2: String?
let city: String?
let state: String?
let zip: String?
let country: String?
```

***

## Publics methods in the SDK

### Configuration

These methods allow you to configure the SDK secrets and load the certificate.

```swift
EasyPay.shared.configureSecrets(apiKey: String, hmacSecret: String)
```

```swift
EasyPay.shared.loadCertificate(_ completion: @escaping (Result<Data, Error>) -> Void)
```

### 1. Charge credit card

This method processes a credit card card sale when the credit card details are entered manually. Details include the card number, expiration date, CVV, card holder name and address.

```swift
EasyPay.apiClient.chargeCreditCard(request: CardSaleManualRequest,
                                   completion: @escaping (Result<CreditCardSaleResponse, Error>) -> Void)
```

REST API equivalent: [/pages/w4UMtcF7UfD7pNPTiZF7#apicardprocrest-v1.0.0-cardsale-manual](https://docs.number.tech/documentation/getting-started/integration-options/pages/w4UMtcF7UfD7pNPTiZF7#apicardprocrest-v1.0.0-cardsale-manual "mention")

#### **Request parameters**

* `TransactionRequest`
  * `creditCardInfo`: [CreditCardInfo](#creditcardinfo)
  * `accountHolder`: [AccountHolder](#accountholder)
  * `endCustomer`: [EndCustomer](#endcustomer)?
  * `amounts`: [Amounts](#amounts)
  * `purchItems`: [PurchItems](#purchitems)
  * `merchantId`: Int

#### **Response body**

The response will be serialized to `CardSaleManualResponseModel` and include:

```swift
public let avsResult: String
public let acquirerResponseEMV: String?
public let cvvResult: String
public let errorCode: Int
public let errorMessage: String
public let functionOk: Bool
public let isPartialApproval: Bool
public let requiresVoiceAuth: Bool
public let responseMessage: String
public let responseApprovedAmount: Double
public let responseAuthorizedAmount: Double
public let responseBalanceAmount: Double
public let txApproved: Bool
public let txId: Int
public let txnCode: String
```

### 2. List annual consents

A query that returns annual consent details. Depending on the query sent, a single consent or multiple consents may be returned.

```swift
EasyPay.apiClient.listAnnualConsents(request: ConsentAnnualListingRequest,
                                     completion: @escaping (Result<ListingConsentAnnualResponse, Error>) -> Void)
```

REST API equivalent: [/pages/dBtuA7Sh0aVhjDX09Hut#apicardprocrest-v1.0.0-query-consentannual](https://docs.number.tech/documentation/getting-started/integration-options/pages/dBtuA7Sh0aVhjDX09Hut#apicardprocrest-v1.0.0-query-consentannual "mention")

#### **Request body**

* `AnnualQueryHelper`

  * `merchantId`: String
  * `customerReferenceId`: String?
  * `rpguid`: String?
  * `endDate`: Date?&#x20;

  Either `customerReferenceId` or `rpguid` must be provided to get the list of consents of a specific customer.

#### **Response body**

The response will be serialized to `ConsentAnnualListingResponseModel` and include:

```swift
public let functionOk: Bool?
public var responseMessage: String?
public let errorMessage: String?
public let errorCode: Int?
public let numberOfRecords: Int?
public let consents: [ConsentAnnual]?
```

And the `ConsentAnnual` consists of the following fields:

```swift
public let id: Int?
public let accountHolderId: Int?
public let customerId: Int?
public let merchantId: Int?
public let customerRefId: String?
public let rpguid: String?
public let serviceDescription: String?
public let accountHolderLastName: String?
public let accountHolderFirstName: String?
public let isEnabled: Bool?
public let startDate: String?
public let endDate: String?
public let numberOfDays: Int?
public let limitPerCharge: Double?
public let limitLifeTime: Double?
public let authTxID: Int?
public let createdOn: String?
public let createdBy: String?
public let accountNumber: String?
```

### 3. Create annual consent

This method creates an annual consent by sending the credit card details, which include: card number, expiration date, CVV, and card holder contact data. It is not created by swiping the card through a reader device.

```swift
EasyPay.apiClient.createAnnualConsent(request: CreateConsentAnnualRequest,
                                      completion: @escaping (Result<CreateConsentAnnualResponse, Error>) -> Void)
```

REST API equivalent: [/pages/2Pdm0t88TPo3URCjHoXS#apicardprocrest-v1.0.0-consentannual-create\_man](https://docs.number.tech/documentation/getting-started/integration-options/pages/2Pdm0t88TPo3URCjHoXS#apicardprocrest-v1.0.0-consentannual-create_man "mention")

#### **Request body**

* `CreateConsentAnnualManualRequestModel`
  * `creditCardInfo`: [CreditCardInfo](#creditcardinfo)
  * `consentAnnualCreate`: [CreateConsentAnnual](#createconsentannual)
  * `accountHolder`: [AccountHolder](#accountholder)
  * `endCustomer`: [AnnualEndCustomer](#annualendcustomer)?

#### **Response body**

The response will be serialized to `CreateConsentAnnualResponseModel` and include:

```swift
public let functionOk: Bool
public let responseMessage: String
public let errorMessage: String
public let errorCode: Int
public let creationSuccess: Bool
public let preConsentAuthSuccess: Bool
public let preConsentAuthMessage: String
public let preConsentAuthTxId: Int
public let consentId: Int
```

### 4. Cancel annual consent

Cancels an annual consent. Credit card data is removed from the system after the cancellation is complete.

```swift
EasyPay.apiClient.cancelAnnualConsent(request: CancelConsentAnnualRequest,
                                      completion: @escaping (Result<CancelConsentAnnualResponse, Error>) -> Void)
```

REST API equivalent: [/pages/pXZvz0HlPUC590yAuLhj#apicardprocrest-v1.0.0-consentannual-cancel](https://docs.number.tech/documentation/getting-started/integration-options/pages/pXZvz0HlPUC590yAuLhj#apicardprocrest-v1.0.0-consentannual-cancel "mention")

#### Request parameters

* `CancelConsentAnnualManualRequestModel`
  * `consentId`: Int

#### **Response body**

The response will be serialized to `CancelConsentAnnualResponseModel` and include:

```swift
public let functionOk: Bool?
public let responseMessage: String?
public let errorMessage: String?
public let errorCode: Int?
public let cancelledConsentId: Int?
public let cancelSuccess: Bool?
```

### 5. Process payment for an annual consent

This method uses the credit card stored on file to process a payment for an existing consent.

```swift
EasyPay.apiClient.processPaymentAnnualConsent(request: ProcessPaymentAnnualRequest,
                                              completion: @escaping (Result<ProcessPaymentAnnualResponse, Error>) -> Void)
```

REST API equivalent: [/pages/pXZvz0HlPUC590yAuLhj#apicardprocrest-v1.0.0-consentannual-procpayment](https://docs.number.tech/documentation/getting-started/integration-options/pages/pXZvz0HlPUC590yAuLhj#apicardprocrest-v1.0.0-consentannual-procpayment "mention")

#### **Request body**

* `ProcessPaymentAnnualRequestModel`
  * `consentId`: Int
  * `processAmount`: String

#### Response body

The response will be serialized to `ProcessPaymentAnnualResponseModel` and include:

```swift
public let functionOk: Bool?
public let txApproved: Bool?
public let responseMessage: String?
public let errorMessage: String?
public let errorCode: Int?
public let txnCode: String?
public let avsResult: String?
public let cvvResult: String?
public let acquirerResponseEMV: String?
public let txId: Int?
public let requiresVoiceAuth: Bool?
public let isPartialApproval: Bool?
public let responseAuthorizedAmount: Double?
public let responseBalanceAmount: Double?
public let responseApprovedAmount: Double?
```

***

## How to properly consume the API response

The response must be consumed in the intended order and format. Clients who deviate from this can experience unwanted behavior.

```swift
if response.data.errorMessage != "" && response.data.errorCode != 0 {
    //This indicates an error which was handled on the Number servers, consume the ErrCode and the ErrMsg 
    return
} else if response.data.functionOk == true && response.data.txApproved == false {
    //This indicates a declined authorization, display the TXID, RspMsg (friendly decline message), also the decline Code (TxnCode)
} else {
   //Transaction has been approved, display the TXID,  and approval code (also in TXNCODE)  
}
```

If there is no `TxApproved` flag, then you can omit the last evaluation. More information about consuming the API response can be found in [Consuming the API response](/documentation/getting-started/basics/api-best-practices#consuming-the-api-response) section.

***

## Possible errors

### RsaCertificateError

<table><thead><tr><th width="317">Error name</th><th>Suggested solution</th></tr></thead><tbody><tr><td><code>failedToLoadCertificateData</code></td><td>Check certificate status, wait until the full download before proceeding with calls, try to download it again manually.</td></tr><tr><td><code>failedToCreateCertificate</code></td><td>Contact Number.</td></tr><tr><td><code>failedToExtractPublicKey</code></td><td>Contact Number.</td></tr></tbody></table>

### AuthenticationError

<table><thead><tr><th width="312">Error name</th><th>Suggested solution</th></tr></thead><tbody><tr><td><code>missingSessionKeyOrExpired</code></td><td>Check if you have provided the correct <code>apiKey</code> and <code>hmacSecret</code>, contact Number to receive updated secrets.</td></tr></tbody></table>

### NetworkingError

<table><thead><tr><th width="309">Error name</th><th>Suggested solution</th></tr></thead><tbody><tr><td><code>unsuccesfulRequest</code></td><td>Check HTTP status code.</td></tr><tr><td><code>noDataReceived</code></td><td>Data from backend was empty, contact Number.</td></tr><tr><td><code>dataDecodingFailure</code></td><td>Data from backend was not decoded properly, contact Number.</td></tr><tr><td><code>invalidCertificatePathURL</code></td><td>Contact Number.</td></tr></tbody></table>

***

## Semantic versioning

The SDK follows semantic versioning with a three-part version number: `MAJOR`.`MINOR`.`PATCH`.

* `MAJOR` version is incremented when there are incompatible API changes,
* `MINOR` version is incremented when functionality is added in a backwards-compatible manner,
* `PATCH` version is incremented when there are backwards-compatible bug fixes.


# React Native Wrapper

The React Native Mobile SDK wrapper provides a bridge between a React Native based application and the native Number mobile SDK libraries.&#x20;

{% hint style="warning" %}
Number's [Android](/documentation/getting-started/integration-options/android-sdk) and [iOS](/documentation/getting-started/integration-options/ios-sdk) SDK libraries are required for use of the wrapper. **It is highly recommended that you review the core SDK products before proceeding.**
{% endhint %}

***

## Installation

### Requirements

1. Mac OS based workstation v15 or newer
2. Xcode v16.2 or newer
3. Android Studio Ladybug Feature Drop | 2024.2.2 or newer
4. React Native CLI
5. React Native v0.77 without new architecture enabled
6. Node v18.19.0 or newer
7. npm v10.8.2 or newer

### Prerequisites

Before beginning your implementation you will need a Number account. It should include the following:

1. **Session Key**: this authenticates you to a particular account.
2. **HMAC secret**: used to create a hash which proves your request is authentic.
3. **RSA Certificate**: to encrypt the credit card number prior to transmission.
4. **A sentry.io key**: used for logging events and errors.
5. **Merchant record or merchant ID**: Each Number account can support multiple merchant records.&#x20;

{% hint style="info" %}
Each merchant record can be a separate location center which generates a separate daily settlement report. Many of our API calls require that you specify which merchant ID to use.
{% endhint %}

### Installation instructions

{% stepper %}
{% step %}
**Setup your environment**

Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions until the "Creating a new application" step before proceeding.
{% endstep %}

{% step %}
**Install components**

**For iOS**

From the project's **root folder**, run *npm install*. This will load the `node_modules` packages that are listed in the `package.json` file. Change directories to the iOS folder and run *pod install*.

```ruby
# in a terminal window
  npm install

  cd ios
  pod install
```

{% endstep %}

{% step %}
**Configure keys**

In the `app.tsx` file, pass your configuration to`EasyPayModule.configureSecrets`:

```swift
EasyPayModule.configureSecrets("YOUR_API_KEY", "YOUR_HMAC_SECRET", "SENTRY_DSN", true)
```

{% endstep %}
{% endstepper %}

***

## Getting started

### Start your application

First, you will need to start the **Metro Server**, the JavaScript bundler that ships with React Native. To start Metro, **run the following command from the root of your React Native project**:

```ruby
# using npm
  npm start

# OR using Yarn
  yarn start
```

Let the Metro Bundler run in its own terminal. To run the app, **open a new terminal from the root of your React Native project** and run one of the following commands:

```ruby
# using npm
  npm run android

# OR using Yarn
  yarn android
```

```ruby
# using npm
  npm run ios

# OR using Yarn
  yarn ios
```

If everything is set up correctly, you should see your new app running in your Android Emulator or iOS Simulator.&#x20;

This is one way to run your app — you can also run it directly from within Android Studio and Xcode respectively. To launch the wrapper in XCode, click on the `EasyPayRN.xcworkspace` file.

### Certificates

When API traffic originates from unknown networks or mobile devices, we mandate that any credit card numbers be encrypted prior to transmission to Number. We will provide an RSA 2048 certificate which is used by Number's Android and iOS SDKs to automatically encrypt the card data.

During the initialization, the process of downloading the certificate is starting. Proceeding with any call before downloading has finished will result in an error  `RsaCertificateError.failedToLoadCertificateData`.

To test the certificate download, call:&#x20;

```swift
EasyPayModule.loadCertificate()
```

### Using the widgets

Number's prebuilt payment UI components allow you to collect and process credit card information in a secure way.

#### **Managing cards**

For managing saved cards without making a payment, the following initializer should be used:

```swift
await EasyPayModule.manageAndSelect(config, user, payment, address)
```

```javascript
 # testing from App.tsx
  const testManageAndSelect = async () => {
    try {
      const config = {
        rpguid: "3d3424a6-c5f3-4c28",
        customerReferenceId: "12456",
        merchantId: "1"
      };
      const user = {
        endCustomerFirstName: "Simple",
        endCustomerLastName: "Simon",
      }
      const payment = {
        limitPerCharge: "1000.0",
        limitLifetime: "10000.0",
        // cardId: 123 // optional
      }
      const address = {
        endCustomerAddress1: "A1",
        endCustomerAddress2: "",
        endCustomerCity: "Newark",
        endCustomerState: "AZ",
        endCustomerZip: "90210",
      }
      await EasyPayModule.manageAndSelect(config, user, payment, address)
    } 
   catch (error) {
     console.log(error)
   }
  }
```

The config and payment objects are used for passing additional payment details not visible for the end user. Either `customerReferenceId` or `rpguid` must be provided to get the list of consents of a specific customer.&#x20;

In case of of incorrect data, `CardSelectionViewControllerInitError` will be thrown.

#### **Collecting payments**

For managing saved cards and collecting a payment, following initializer should be used:

```swift
await EasyPayModule.pay (config, user, payment, address)
```

```javascript
# testing from App.tsx
  const testManageAndPay = async () => {
    try {
      const config = {
        rpguid: "3d3424a6-c5f3-4c28",
        customerReferenceId: "12456",
        merchantId: "1"
      };
      const user = {
        endCustomerFirstName: "Simple",
        endCustomerLastName: "Simon",
      }
      const payment = {
        amount: "25.99",
        limitPerCharge: "1000.0",
        limitLifetime: "10000.0",
        // cardId: 123 // optional
      }
      const address = {
        endCustomerAddress1: "A1",
        endCustomerAddress2: "",
        endCustomerCity: "Newark",
        endCustomerState: "AZ",
        endCustomerZip: "90210",
      }
      await EasyPayModule.pay (config, user, payment, address)
    } 
    catch (error) {
      console.log(error)
    }
  }
```

### Event emitters

Communication between the Number SDK widgets and the React Native wrapper is handled via event emitters. These event emitters allow you to respond to user events such as a payment being processed.&#x20;

The `EasyPayModule.swift` file contains functions that map to the iOS SDK's `CardPaymentDelegate` and `CardSelectionDelegate` protocols. These functions send events that are received in the wrapper's JavaScript code.

```swift
//MARK: - CardSelectionDelegate

func didSelectCard(consentId: String) {
  RNEventEmitter.emitter.sendEvent(
    withName: "onCardSelected",
    body: ["consentId": consentId])

}

func didDeleteCard(consentId: Int, success: Bool) {
  if success {
    RNEventEmitter.emitter.sendEvent(
      withName: "onCardDeleted",
      body: ["consentId": consentId])
  }
}

func didSaveCard(
  consentId: Int?,
  expMonth: Int?,
  expYear: Int?,
  last4digits: String?,
  success: Bool
) {
  if !success {
    return
  }
  guard let cid = consentId else { return }
  var body: [String: Any] = ["consentId": cid]

  if let month = expMonth {
    body["expMonth"] = month
  }
  if let year = expYear {
    body["expYear"] = year
  }
  if let digits = last4digits {
    body["last4digits"] = digits
  }

  RNEventEmitter.emitter.sendEvent(
    withName: "onCardSaved",
    body: body)
}

//MARK: - CardPaymentDelegate

func didPayWithCard(
  consentId: Int?,
  paymentData: PaymentData?,
  success: Bool
) {
  if !success {
    return
  }

  //guard let cid = consentId else { return }
  var cid = 0
  if consentId != nil {
    cid = consentId ?? 0
  }

  let body: [String: Any?] = [
    "consentId": cid,
    "functionOk": paymentData?.functionOk == true,
    "txApproved": paymentData?.txApproved == true,
    "responseMessage": paymentData?.responseMessage,
    "errorMessage": paymentData?.errorMessage,
    "errorCode": paymentData?.errorCode,
    "txnCode": paymentData?.txnCode,
    "avsResult": paymentData?.avsResult,
    "cvvResult": paymentData?.cvvResult,
    "acquirerResponseEMV": paymentData?.acquirerResponseEMV,
    "txId": paymentData?.txId,
    "requiresVoiceAuth": paymentData?.requiresVoiceAuth == true,
    "isPartialApproval": paymentData?.isPartialApproval == true,
    "responseAuthorizedAmount": paymentData?.responseAuthorizedAmount,
    "responseApprovedAmount": paymentData?.responseApprovedAmount,
  ]

  RNEventEmitter.emitter.sendEvent(
    withName: "onCardPaid",
    body: body.compactMapValues({ $0 }))

}

```

On the React Native side, **configure event listeners to respond to the raised events**:

```javascript
# testing from App.tsx

    // iOS Events
    const selectionListener = nativeEventEmitter.addListener('onCardSelected', (data: {
        consentId: String;
    }) => {
        console.log('Card Selected', data.consentId);
    });
    const deleteListener = nativeEventEmitter.addListener('onCardDeleted', (data: {
        consentId: String;
    }) => {
        console.log('Card Deleted', data.consentId);
    });
    const saveListener = nativeEventEmitter.addListener('onCardSaved', (data: {
        consentId: String;
    }) => {
        console.log('Card Saved', data.consentId);
        /* See also:
          consentId
          expMonth
          expYear
          last4Digits
        */
    });
    const paidListener = nativeEventEmitter.addListener('onCardPaid', (data: {
        consentId: string;
        functionOk: boolean;
        txApproved: boolean;
        responseMessage: string;
        errorMessage: string;
        errorCode: int;
        txnCode: string;
        avsResult: string;
        cvvResult: string;
        acquirerResponseEMV: string;
        txId: int;
        requiresVoiceAuth: boolean;
        isPartialApproval: boolean;
        responseAuthorizedAmount: number;
        responseApprovedAmount: number;

    }) => {

        console.log('functionOK', data.functionOk);
        console.log('Consent ID', data.consentId);
        console.log('Transaction ID', data.txId);
    });

    // Android Events
    const manageErrorListener = nativeEventEmitter.addListener('onManageError', (data: {
        error: String;
    }) => {
        console.log('Manage error', data.error);
    });

    const manageResultListener = nativeEventEmitter.addListener('onManageResult', (data: {
        selectedConsentId ? : number;
    }) => {
        console.log('Selected Consent Id', data.selectedConsentId);      
    });

    const paymentErrorListener = nativeEventEmitter.addListener('onPaymentError', (data: {
        error: String;
    }) => {
        console.log('Payment error', data.error);
    });
    const paymentCancelListener = nativeEventEmitter.addListener('onPaymentCancelled', () => {
        console.log('Payment cancelled');
    });
    const paymentResultListener = nativeEventEmitter.addListener('onPaymentResult', (result: {
        data: {
            errorMessage: string;
            responseMessage: string;
            txApproved: boolean;
            txId: number;
            txCode: string;
            avsResult: string;
            acquirerResponseEmv: string;
            cvvResult: string;
            isPartialApproval: boolean;
            requiresVoiceAuth: boolean;
            responseApprovedAmount: number;
            responseAuthorizedAmount: number;
            responseBalanceAmount: number;
        };
    }) => {        
        console.log('Payment result', result.data);
    });
```


# PayForm

Getting started with PayForm for Number

The PayForm is designed to be a highly flexible and secure payment form for your users. It is built to be rendered in the browser and integrated with your existing web content.

Collecting a payment or saving a card on file is a two-step process:

1. A call is made to our REST API to initialize the payment parameters
2. A payment link is generated.

You control all of the operational and design parameters of the PayForm:

1. Form styling
2. Field visibility and read-only parameters
3. Initial data (cardholder names, $ amounts, etc.)
4. User-defined data (ReferenceID, etc.)
5. Defined methods for receiving a real-time update after transactions are authorized

**You can then present the PayForm in one of two ways:**&#x20;

<table data-header-hidden><thead><tr><th width="114"></th><th></th></tr></thead><tbody><tr><td><img src="/files/jsgJjH5z3PGSxTF8fJEk" alt="" data-size="original"></td><td>As an iFrame on your website</td></tr><tr><td><img src="/files/P5VmFb7Carf7kBpF5tIV" alt="" data-size="original"></td><td>As a direct link to the PayForm</td></tr></tbody></table>

{% hint style="info" %}
**To generate a PayForm**, you can make a call to our REST API using a request body generated on the PayForm builder website.
{% endhint %}

{% content-ref url="/pages/2fgqMqF7WUzxnJEDjiTf" %}
[PayForm](/api-reference/rest-api/payform)
{% endcontent-ref %}

***

## PayForm builder

<figure><img src="/files/UOZYMWKWJ4bXCGsRjB6B" alt=""><figcaption></figcaption></figure>

It might be difficult to prepare a PayForm request by yourself at first. **To make it easy and to get started, we've prepared a tool which can generate your form for you**.&#x20;

This is the PayForm wizard tool:

{% embed url="<https://easypay8.com/payformwizard/>" %}
PayForm Builder
{% endembed %}

This is a second option for creating PayForm configuration:

{% embed url="<https://easypay8.com/byopayform/>" %}
Legacy Builder
{% endembed %}

### Transaction types

There are three operation types you can choose from:

1. Collect an instant payment using credit cards, ACH, Apple Pay or Google Pay
2. Save accountholder data to be charged later (card-on-file, account on file)
3. Both saving the accountholder data *and* collecting instant payment

This choice will also pre-determine some of the required fields and submission options for you.

### Visible and read-only fields

There is a number of fields you can have added to your form. For some of the fields, you can choose to provide a default value, and to mark them as read-only.

<table><thead><tr><th width="166">Field name</th><th width="403">Description</th><th>Read-only option</th></tr></thead><tbody><tr><td>First Name</td><td>Cardholder first name. If only <code>First Name</code> is visible, field will be changed to <code>Full Name</code><strong>.</strong></td><td>yes</td></tr><tr><td>Last Name</td><td>Cardholder last name. If only <code>Last Name</code> is visible, field will be changed to <code>Full Name</code><strong>.</strong></td><td>yes</td></tr><tr><td>Address</td><td>Cardholder street address.</td><td>yes</td></tr><tr><td>City</td><td>Cardholder city.</td><td>yes</td></tr><tr><td>State</td><td>Cardholder state.</td><td>yes</td></tr><tr><td>Zip Code</td><td>Cardholder zip code.</td><td>yes</td></tr><tr><td>Amount</td><td>A total $ amount to charge, when applicable to the chosen transaction type.</td><td>yes</td></tr><tr><td>REFID</td><td>A user-defined custom field</td><td>yes</td></tr><tr><td>RPGUID</td><td>A hidden user-defined custom field</td><td>yes</td></tr><tr><td>Expiration</td><td>Expiration date on the card, <strong>required</strong>.</td><td>-</td></tr><tr><td>CVV</td><td>Security code on the back of the card, <strong>required</strong>.</td><td>-</td></tr><tr><td>Agree to Pay confirmation</td><td>Adds a checkbox that will be required to submit and complete the instant card payment.</td><td>-</td></tr><tr><td>Agree to Save Card on File confirmation</td><td>Adds a checkbox that will be required to successfully save the card on file.</td><td>-</td></tr><tr><td>Email</td><td>Cardholder email address.</td><td>yes</td></tr><tr><td>Auth to Email</td><td>Permission to send an email.</td><td>-</td></tr><tr><td>Logos</td><td>Adds EasyPay Solutions, PCI Certified, and Digicert Secured logos to the form.</td><td>-</td></tr></tbody></table>

### Submission options

Based on your requirements, you can choose from many submission options explained below.

<table><thead><tr><th width="166">Submission option</th><th>Description</th></tr></thead><tbody><tr><td>Redirect external</td><td>After submitting, the user will be redirected to a provided external URL. <br><br>An encrypted string containing the POST data is appended to the URL to be consumed by the merchant.</td></tr><tr><td>Redirect internal - receipt combo</td><td><p>After submitting, the user will be redirected to an internal page displaying a combination receipt for merchant and customer. <br><br>An encrypted string containing the POST data is appended to the URL to be consumed by the merchant. </p><p></p><p>This can also be used in conjunction with <code>Silent Post</code> for the purpose of transmitting data.</p></td></tr><tr><td>Redirect internal - receipt customer</td><td>After submitting, the user will be redirected to an internal page displaying a receipt for the customer. <br><br>An encrypted string containing the POST data is appended to the URL to be consumed by the merchant.<br><br>This can also be used in conjunction with <code>Silent Post</code> for the purpose of transmitting data.</td></tr><tr><td>Redirect internal - success message</td><td>After submitting, the user will be redirected to an internal page displaying a success message and a check mark image. <br><br>An encrypted string containing the POST data is appended to the URL to be consumed by the merchant.<br><br>Sometimes used with desktop apps which use embedded browsers.</td></tr><tr><td>Silent post</td><td><p>After submitting, an encrypted string containing the POST data is sent to the provided URL to be consumed by the merchant. </p><p></p><p>The data is transmitted in the background. <strong>The user is not redirected.</strong></p></td></tr><tr><td>Post message</td><td>When the PayForm is inside of an iFrame, after submitting, an encrypted string containing the POST data is sent to the parent page to be consumed by the merchant. <strong>The user is not redirected.</strong></td></tr><tr><td>Require AVS full match</td><td>To submit the PayForm, a full AVS match must be submitted. <strong>This requires the <code>Address</code> and <code>Zip Code</code> to match exactly what is on record with the issuer for the card.</strong></td></tr><tr><td>Require AVS partial match</td><td>To submit the PayForm, a partial AVS match must be submitted. <strong>This requires that, at a minimum, there is a <code>Zip Code</code> match achieved.</strong></td></tr><tr><td>Require CVV match</td><td>To submit the PayForm, a full CVV match must be achieved. <strong>The transaction will be voided if the <code>CVV</code> does not fully match what is on file with the card issuer.</strong></td></tr><tr><td>Payment widget</td><td>This PayForm will collect a one-time payment. <strong>Automatically set when choosing the transaction type.</strong></td></tr><tr><td>Save Card on File widget</td><td>This PayForm will save the card on file for future use. <strong>Automatically set when choosing the transaction type.</strong></td></tr><tr><td>JSON post</td><td>Replace the encrypted POST data with a JSON object to be consumed.</td></tr><tr><td>Send only Transaction ID /  Consent ID</td><td>Only include the <code>TxID</code> and <code>ConsentID</code> in the data to be consumed.</td></tr></tbody></table>

### Style and colors

We care about making sure that the PayForm can match the style of your branding. You'll notice that some options are mutually exclusive.&#x20;

Here is a list of all non-default customization options that can affect the look of the PayForm:

<table><thead><tr><th width="293">Customization element</th><th>Options</th></tr></thead><tbody><tr><td>Label position</td><td>Left of the text box, above the text box, within the text box.</td></tr><tr><td>Text box corners</td><td>Semiround, round, semiround subtle.</td></tr><tr><td>Font family</td><td>Serif Font, Roboto font.</td></tr><tr><td>Required field indicators</td><td>Show.</td></tr><tr><td>Hide buttons</td><td>Hide both buttons, hide cancel button.</td></tr><tr><td>Text box size</td><td>Tall text boxes, short text boxes.</td></tr><tr><td>Background color<br>Button background color<br>Button border color<br>Button text color<br>Label text color<br>Text box text color<br>Text box background color</td><td>Any RGB value (can be selected using the color picker).</td></tr></tbody></table>

### Pre-filled values

Depending on your needs, you might want to have some of the values pre-filled with defaults. This will allow you to provide a default for the `First Name`, `Last Name`, `Address`, `City`, `State`, `Zip`, `Amount`, `REFID`, `RPGUID`, and `Email`.

Additionally, in this part of the builder, you can set values for the hidden config fields used by the form: `Endpoint`, `Redirect URL`, `Post URL`, and `EIndex`.

<table><thead><tr><th width="298">Hidden config field</th><th>Description</th></tr></thead><tbody><tr><td>Endpoint</td><td>Points to specific web application on our server. Number will provide guidance.</td></tr><tr><td>Redirect URL</td><td>A URL to redirect the user after the payment is processed, if applicable.</td></tr><tr><td>Post URL</td><td>A URL to POST the real-time values after the payment is completed, if applicable.</td></tr><tr><td>EIndex</td><td>Integrator key index for encryption assigned when integrator account is first created, received with the initial login credentials</td></tr></tbody></table>

***

## PayForm API request

Once you have the request ready, you can call our REST API to generate the PayForm and the `PaymentURL` that you can use to access it. See the reference to [PayForm Old](/api-reference/rest-api-alt/payform#payform-initialize) endpoint.

Here's an example PayForm generated using the endpoint:

<figure><img src="/files/BgUfk86UdPvPgSg8TrHu" alt=""><figcaption></figcaption></figure>

### Consuming data from the PayForm

After the payment form has been submitted and credit card authorization is completed, **you can opt to gather real-time information using JSON post, redirect with query string, or a post message to your parent page.**

When configuring the form, you may provide one or both of the following URLs:

* `POST URL` where we will POST values as either JSON stream or by appending a query string,
* `Redirect URL` to redirect to the page of your choice after transaction is completed, with or without a query string appended.

#### JSON POST

Using `JSON POST`, you'll be able to provide a `POST URL` for our servers to stream the data to. Then, you can tap into the request input stream to receive your JSON string.

Here's an example of the result and how to tap into the input stream:

{% tabs %}
{% tab title="JSON" %}

```jsonc
{
  "ConsentID": 33,
  "TransactionID": 21008,
  "CardNumber": "4511",
  "CardType": "Visa",
  "ExpireDate": "12/28",
  "Amount": 56.20,
  "Surcharge": 0.0,
  "CardholderFirstName": "Nancy",
  "CardholderLastName": "Draper",
  "CustomerFirstName": "",
  "CustomerLastName": "",
  "Email": "ndraper@easypaysolutions.com",
  "REFID": "764532#1",
  "RPGUID": "38976345",
  "ApprovalCode": "OK5013"
}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="C#" %}

```csharp
public void ProcessPayFormInput(object sender, EventArgs e)
{
  string json;
  using (var reader = new StreamReader(Request.InputStream))
  {
    json = reader.ReadToEnd();
  }
  // Process the input
}
```

{% endtab %}
{% endtabs %}

#### Redirect with query string

If you don't choose to use `JSON POST`, we will submit an HTTP GET request to your page with query parameters appended to the URL. In order for you to validate the information, when configuring the form you can choose from the following encryption options for those query parameters:

* EIndex: If you supply `EIndex`, a value which defines your unique AES 256 encryption key as described above, you can read query string values as encrypted parameters (the encrypted message `m`, and the initialization vector `i`);
* None: Otherwise, we will supply the query parameters with **no encryption** and you will be able to query our API to ensure that **1. those values exist** and **2. they were created in the last few moments**.

{% hint style="danger" %}
**When you are receiving transaction data that is not encrypted, you should validate it before storing any details to avoid malicious actors creating unqualified data.**
{% endhint %}

In the case that you're not using encryption, we recommend **validating the information**.&#x20;

{% stepper %}
{% step %}

#### Retrieve and validate the transaction details

Using the `TransactionID` returned by the PayForm, you can call our REST API to [retrieve full transaction details](https://docs.number.tech/documentation/getting-started/integration-options/pages/dBtuA7Sh0aVhjDX09Hut#apicardprocrest-v1.0.0-query-transaction_fulldetail) to get all of the information regarding the transaction.

Then, you can confirm if a transaction with the selected ID exists, and if the `CreatedOn` date roughly matches the current time or the time the PayForm was submitted.
{% endstep %}

{% step %}

#### Retrieve and validate the consent details (if the card was saved)

If `ConsentID` was returned alongside the `TransactionID`, you can use the REST API to [get full detail of annual consent](https://docs.number.tech/documentation/getting-started/integration-options/pages/dBtuA7Sh0aVhjDX09Hut#apicardprocrest-v1.0.0-query-consentannual_fulldetail) to get all of the information regarding the consent.

Then, you can confirm if a consent with the selected ID exists, and if the `CreatedOn` date roughly matches the current time or the time the PayForm was submitted.
{% endstep %}
{% endstepper %}

With this, **you can avoid malicious actors filling your database with unqualified transaction data**.

#### HTTP POST message

In this method, the PayForm you have rendered in your iFrame will message your parent page directly.

Here are example scripts for your parent page to listen for the message provided by the PayForm:

{% tabs %}
{% tab title="JavaScript (example 1)" %}

```javascript
// Listen for post messages from an iFrame
window.addEventListener('message', (event) => {
  const resultsMessage = document.getElementById('results');

  // Ensure the message is from a trusted origin
  const trustedOrigin = 'https://easypay5.com'; // use PayForm origin
  if (event.origin !== trustedOrigin) {
    console.warn('Received message from untrusted origin:', event.origin);
    return;
  }

  // Update the innerHTML with the message data
  resultsMessage.innerHTML = event.data;

  // Optionally, handle the message data further
  // alert(event.data);
});
```

{% endtab %}

{% tab title="JavaScript (example 2)" %}

```javascript
// addEventListener support for IE8
function bindEvent(element, eventName, eventHandler) {
  if (element.addEventListener) {
    element.addEventListener(eventName, eventHandler, false);
  }
  else if (element.attachEvent) {
    element.attachEvent('on' + eventName, eventHandler);
  }
}

// Listen to message from child window
bindEvent(window, 'message', function(e) {
  var resultsMessage = document.getElementById('results');
  resultsMessage.innerHTML = e.data;
  // Optionally, handle the message data further
  // alert(e.data);
});

```

{% endtab %}
{% endtabs %}

If your implementation is using encryption, after decrypting, you'll get a string which looks similar to this:

```
TXID|174|CONSENTID|213|CARDNO|5339|CARDTYPE|Amex|FIRSTNAME|Bob|LASTNAME|smith|REFID|7899
```

If you are not using encryption, it will contain 2 URL parameters instead, and looks similar to this:

```
?txid=123&cid=321
```

#### Requesting additional transaction and consent details

Having the `TransactionID` (`TxID`) and `ConsentID`, you can use our REST API to:

* Gather additional informating concerning the sale;
  * For the REST API, you can use [full transaction details](https://docs.number.tech/documentation/getting-started/integration-options/pages/dBtuA7Sh0aVhjDX09Hut#apicardprocrest-v1.0.0-query-transaction_fulldetail), and [full consent details](https://docs.number.tech/documentation/getting-started/integration-options/pages/dBtuA7Sh0aVhjDX09Hut#apicardprocrest-v1.0.0-query-consentannual_fulldetail) methods;
* Provide a receipt;
  * For the REST API, you can use [generate a transaction receipt](https://docs.number.tech/documentation/getting-started/integration-options/pages/YaMXGoIYHPbKE8K6LEPP#apicardprocrest-v1.0.0-receipt-receiptgenerate) method;


# Apple Pay / Google Pay

Configuring your PayForm for integrated payments via the Apple and Google digital wallets

In order to add Apple Pay / Google Pay functionality to your PayForm, you'll need to modify your [request](/api-reference/rest-api/payform) as follows:

**InitParams.EndPoint remains the same:**

{% code overflow="wrap" %}

```jsonc
"EndPoint": "PayForm/PF.aspx"
```

{% endcode %}

**WidOptions.eFeatures should be updated to the code "0004":**

{% code overflow="wrap" lineNumbers="true" %}

```json
"WidOptions": {
      "eVisible": "2EFF",
      "eReadOnly": "0000",
      "eStyles": "0001",
      "eSubmission": "0210",
      "eFeatures": "0004", /* this code must be present */
      "eColors": "#ffffff,#428bca,#007bff,#212121,#ffffff,#212121,#ffffff"
}
```

{% endcode %}

#### Considerations&#x20;

1. **Notify us prior to submitting test transactions:** Notify the Number team when you are ready to test. We will configure your account to prepare it for your test submissions.
2. **PayForm appearance/size:** If our PayForm determines that Apple Pay or Google Pay can be used during the cardholder's browser session, you will notice one or both additional buttons displayed (see below). The PayForm will grow vertically as appropriate to accomodate the additional pay buttons.

<figure><img src="/files/xZZNo2eGKo5ZvsCrS1PW" alt=""><figcaption></figcaption></figure>

3. **Domain:** If you plan to display our widget within an iframe, we will need to get your domain approved (Apple Pay only).  Contact the Number tech team to accomplish this. We will have you publish a small text file on your web server which Apple will discover.
4. **SandBox:** In order to get approvals in the sandbox (Apple Pay only) you will need:\
   \- A Sandbox Apple ID (different from your real Apple ID)\
   \- An iPhone or iPad that supports Apple Pay.\
   \- The device must be signed into iCloud with the sandbox account, not your normal Apple ID.

#### Step-by-step: How to get test cards into your Apple Pay Wallet

1. **Create a Sandbox Apple ID** \
   Go to Apple’s developer site → *Account* → *Users and Access* → *Sandbox Testers*. Create a new tester account (email must be unique and not tied to an existing Apple ID).
2. **Sign out of your real Apple ID on your device**\
   Settings → Your Name → *Sign Out*.
3. **Sign in with the Sandbox Apple ID**\
   Settings → Sign in → use the sandbox credentials.
4. **Open the Wallet app**\
   Once the device is in sandbox mode, you can begin to add Sandbox test cards to your **Apple Pay Wallet (**&#x74;ap **Add Card)**.&#x20;
5. **This link has valid test cards you can put in your wallet:**\
   [Sandbox Testing - Apple Pay - Apple Developer](https://developer.apple.com/apple-pay/sandbox-testing/)
6. **Use the cards only in sandbox-supported apps/sites**\
   They will not work in production environments. Real cards are required for production testing.

## Google Pay Considerations&#x20;

To test Google Pay in our PayForm you need to do the following:

1. Notify us that you are ready to test (we will modify your test account)
2. Make sure you are logged in to your google account
3. Open your Number PayForm using your test account. The Google Sandbox Wallet should become available automatically.

The sandbox test cards provided by Google often do not pass CVV match requirements. You may want to leave that option out of the submission options while you test.&#x20;

Once you are ready to Pay you will see a message which indicates that no actual funds will be charged in the TEST ENVIRONMENT.&#x20;

<figure><img src="/files/P8SKvsCZROM9cslKxGpz" alt=""><figcaption></figcaption></figure>

&#x20;


# Incremental Authorizations

You may wish to configure your PayForm to collect an Initial *Authorization Only*.

This Authorization can be Reversed or Incrementally increased during your workflow and eventually finalized and sent for settlement.  In order to Specify *Authorization Only* adjust your [request](/api-reference/rest-api/payform) as follows

{% code overflow="wrap" %}

```jsonc
"eFeatures": "0008",
```

{% endcode %}

This tells the PayForm that any dollar amount authorized will stay in a PENDING state awaiting any changes or Incremental increases you specify using our API.

{% hint style="warning" %}
Be VERY CAREFUL when setting this feature value; transactions collected here will rely on you to FINALIZE them using the API. If you do an Authorization Only for a dollar value, the merchant WILL NOT collect the funds until you FINALIZE the transaction.
{% endhint %}

Use this REST API call to execute incremental authorizations or finalize the transaction:

{% content-ref url="/pages/mIUOkLIdbQGmBaUi7xmi" %}
[Incremental Auth](/api-reference/rest-api/card-operations/authentication)
{% endcontent-ref %}


# Subscription

The PayForm can be configured to collect subscription type payments.

In order to do this, you can adjust your [request](/api-reference/rest-api/payform) as follows:

> "eFeatures": "0001",

This will provide for your final redirect address as well as a webhook URL

Here are other changes you will need to consider:&#x20;

> "eSubmission": "0221",\
> "eFeatures": "0001",\
> "WTYPE": "PF",\
> "EndPoint": "Payform/PF.aspx",\
> "PostURL": "<https://easypay1.com/postingapp/submit.aspx>", <mark style="color:$danger;">// your webhook location</mark>\
> "RedirectURL": "<https://easypay8.com/CYWidget/>", <mark style="color:$danger;">// your redirect URL</mark>

You can add the following section to your initialization request to describe your desired subscription:

> "Subscription": {\
> "Amount": 20.0,\
> "Period": "WEEKLY",\
> "FirstPayDate": "2026-02-11"\
> },

Note:  *You must use a date which is today or future, or an error will occur.*

**Valid subscription periods:**

* WEEKLY
* BI\_WEEKLY
* TWICE\_MONTHLY
* MONTHLY
* BI\_MONTHLY
* QUARTERLY
* SEMI\_ANNUALLY
* ANNUALLY

### Operation

The Subscription PayForm is designed to do the following:

1. Collect an independent Fee ( optional )
2. Create a Subscription consent ( stored card )
3. Do the initial charge ( depending on "FirstPayDate":)

&#x20;**Fig 1  (when a fee is also required):**&#x20;

{% columns %}
{% column %}

```
"eVisible": "0665",
"eFeatures": "0001",
"eReadOnly": "0040",
"eStyles": "0001",
"eSubmission": "0221",

"Amounts": {
 "Amount": 20,
 "Surcharge": 0,
 "TotalAmt": 20
 },
```

{% endcolumn %}

{% column %}

<figure><img src="/files/TWItZFZ2mpvVXlQF9Was" alt=""><figcaption></figcaption></figure>
{% endcolumn %}
{% endcolumns %}

&#x20;**Fig 2 (when NO fee is required initially):**

{% columns %}
{% column %}

```
"eVisible": "0625",
"eFeatures": "0001",
"eReadOnly": "0040",
"eStyles": "0001",
"eSubmission": "0221",

"Amounts": {
 "Amount": 0,
 "Surcharge": 0,
 "TotalAmt": 0
 },
```

{% endcolumn %}

{% column %}

<figure><img src="/files/AUz8OEElQBBx8xQHM3hS" alt=""><figcaption></figcaption></figure>
{% endcolumn %}
{% endcolumns %}

**Here is a full request (for Fig 2):**

```
{
  "InitParams": {
    "MerchID": 1,
    "WTYPE": "PF",
    "PostURL": "HTTPS://easypay1.com/postingapp/submit.aspx",
    "RedirectURL": "https://easypay8.com/CYWidget/",
    "REF_ID": "A97689#",
    "RPGUID": "92e1e15c-f64a-466b-8733-9b518b9f374c",
    "EndPoint": "PayForm/PF.aspx",
    "EINDEX": "300",
    "Amounts": {
      "Amount": 0, (only if you want to collect a separate fee) 
      "Surcharge": 0,
      "TotalAmt": 0
    },
    "Payer": {
      "Firstname": "John Doe",
      "Lastname": "",
      "BillingAddress": {
        "StreetAddress": "",
        "City": "",
        "State": "",
        "ZIP": "04048",
        "Country": ""
      },
      "Email": "",
      "Phone": ""
    },
    "Subscription": {
        "Amount": 120,
        "Period": "WEEKLY",
        "FirstPayDate": "2026-02-11"
     },
    "WidOptions": {
      "eVisible": "0625",
      "eFeatures": "0001",
      "eReadOnly": "0040",
      "eStyles": "0001",
      "eSubmission": "0221",
      "eColors": "#ffffff,#428bca,#007bff,#212121,#ffffff,#212121,#ffffff"
    }
  }
}

```

### Behavior

You will continue to get webhooks throughout the lifetime of your subscription

**Here are some examples:**

```
{
    "acctid":5325,
    "type":"SUBSCRIP_CREATE",
    "refid":"A97689#",
    "rpguid":"92e1e15c-f64a-466b-8733-9b518b9f374c",
    "cardholder":"John Doe",
    "email":"",
    "subscription":{
        "id":15,"amount":120000,
        "result":"SUCCESS","period":"WEEKLY",
        "startdate":"2/11/2026",
        "nextdate":"2/18/2026",
        "status":"ACTIVE",
        "errcode":0,
        "errmsg":"NA"
    }
}
```

```
{
    "acctid":5325,
    "type":"SUBSCRIP_PAYMENT",
    "refid":"A97689#",
    "rpguid":"92e1e15c-f64a-466b-8733-9b518b9f374c",
    "cardholder":"John Doe",
    "email":"",
    "subscrip_id":15,
    "transaction":{
        "id":100,
        "amount":120000,
        "result":"APPROVED",
        "txncode":"OK2194",
        "errcode":0,
        "errmsg":"NA"
    }
} 
```

### Cancelling a subscription

In order to discontinue automatic payments for a given subscription you must cancel the subscription using the API.

[Cancel a consent subscription | Docs](https://docs.number.tech/api-reference/rest-api/consent-subscription/cancel-a-consent-subscription)


# Verifone

Getting started with Verifone for Number

The Verifone card readers are small hand-held devices. They communicate with your computer on a USB port. A chip transaction is comprised of about a dozen transmissions between the host (your computer) and the device, and then finally to the Number cloud platform.

Using the Verifone card readers offers a highly secure method of collecting cardholder data.

Cardholder data is encrypted within the device itself, and remains encrypted as it travels across the Internet to our PCI Level One Compliant processing platform.&#x20;

{% hint style="info" %}
When a merchant supports a Verifone card reader, it helps eliminate chargebacks for transactions which were run through the device.
{% endhint %}

<figure><img src="/files/JAdQWeAgQ2ZUBfXZqnS3" alt=""><figcaption></figcaption></figure>

### PCI SSC SSF <a href="#pci-ssc-software-security-framework-ssf" id="pci-ssc-software-security-framework-ssf"></a>

Software Security Framework (SSF) is a re-working of the existing PCI standard PA DSS. The PA DSS has been retired since June 30, 2021. Number's "Aspen 3.1" is the first application to achieve the PCI Councils SSF certification, and it provides an end-to-end encrypted solution.

<figure><img src="/files/iRmeiJ42KQtosB2FcBVv" alt=""><figcaption></figcaption></figure>

***

## Software options <a href="#what-we-offer" id="what-we-offer"></a>

Currently, we offer three different options for collecting payments with the Verifone card readers, all of which require a Windows OS on the host computer.

{% stepper %}
{% step %}
**Standalone desktop application (upon request)**

This application has automatic updates and allows you to collect payments, create card-on-file and payment plans, process a card-on-file, void or credit, settle transactions, and do reporting with an option to export to a PDF.
{% endstep %}

{% step %}
**Browser-based interface**

We developed a Windows service which uses Cross-Origin Resource Sharing (CORS) to communicate with the browser. The Win service will return a simple XML response for each transaction directly to the HTML/PHP/ASP.NET page for consumption by the host application.

As an integrator, this allows you to write simple client-side scripts within your own web applications to initiate transactions with a local Verifone. **You can also use this service with our Virtual Terminal to avoid writing any code.**
{% endstep %}

{% step %}
**Number Verifone SDK**

This DLL provides a means of collecting payments and creating card-on-file plans. Used in conjunction with your custom windows application, you can manage all aspects of your payment requirements.
{% endstep %}
{% endstepper %}

#### **Requirements**

There are 2 categories of integrations which require two different sets of files

1. Browser-based - install our Win service which contains all your dependencies, including the drivers and console installer.
2. Desktop-based - install our SDK, then use separate installers for drivers and a custom event log.

## Desktop application <a href="#easy-pay-verifone-sdk" id="easy-pay-verifone-sdk"></a>

<figure><img src="/files/sUHVQgqANgLwhsDBEhx7" alt=""><figcaption></figcaption></figure>

If you wish to use the standalone desktop application for Verifone, [contact Number ](/help/customer-support)for installation files and instructions.

## Browser-based installation <a href="#browser-based-installation" id="browser-based-installation"></a>

For any browser-based Implementation using the Verifone, you will need to install the local win service. This includes our Virtual Terminal implementation as well as your own custom web applications.

<figure><img src="/files/L9Hxigb6nD2ru7cl0msP" alt=""><figcaption></figcaption></figure>

To Begin: Download the compressed archive:

#### [Verifone Middleware Installer](https://easypay1.com/deploy/MiddleWare/EPVerifoneSetup_E2E_1042.zip)<br>

**To install the Win service:**

{% stepper %}
{% step %}
Connect your device to a free USB port.
{% endstep %}

{% step %}
Allow the device to initialize.
{% endstep %}

{% step %}
Extract the above archive to a location of your choice.
{% endstep %}

{% step %}
Locate the EXE file and right click on it to choose *Run as administrator*.
{% endstep %}

{% step %}
Wait for the application to finish, then reboot computer.
{% endstep %}
{% endstepper %}

The above installation package does the following:

1. Installs USB drivers for the Verifone.
2. Creates a custom event log with Windows named *EPmiddleware*.
3. Installs a certificate which encrypts data between the browser and the Windows service.
4. Installs the *EasyPay Verifone MiddleWare E2E 1042 Service* which listens on port 8031.

Your website can now issue commands to the Win Service as is demonstrated using the sample site:&#x20;

[Sample Verifone Website](https://easypay1.com/JqueryVerifone/)

You can download the entire site here:

[Sample Verifone Website Content](https://easypay1.com/docs/jquery_verifone.zip)

{% hint style="warning" %}
To run the Verifone demo website, you must have the Verifone Windows service installed.
{% endhint %}

### Virtual Terminal

You can use our Virtual Terminal together with the Windows service. It has built-in support for Verifone. This way, you won't have to build your own UI or write any code. After installing the service, [contact Number](/help/customer-support) to have this feature activated.

You can read more about using the Virtual Terminal in the [Virtual Terminal](/documentation/getting-started/integration-options/virtual-terminal) guide.

### Requesting a transaction from your custom web application

You will find a script file named EasyPayVerifone.js in the sample VeriFone website provides the following functionality:

1. EMV sale only
2. EMV sale and save card
3. Manual sale (keyed entry) sale only
4. Manual sale and save card
5. EMV save card only
6. Reset the Middleware and Verifone

#### You can call these functions as follows:

```clike
// EMV Sale Only
$(document).ready(function () {
	$('#EMVSaleOnly').click(function () {
		EMVSaleCombo(false);
	});
});
// EMV Sale and Save Card
$(document).ready(function () {
	$('#EMVSaleAndSave').click(function () {
		EMVSaleCombo(true);
	});
});
// Manual Sale Only
$(document).ready(function () {
	$('#ManualSaleOnly').click(function () {
		ManualSaleCombo(false);
	});
});
// Manual Sale and Save Card
$(document).ready(function () {
	$('#ManualSaleAndSave').click(function () {
		ManualSaleCombo(true);
	});
});
// EMV Save Card Only
$(document).ready(function () {
	$('#SaveCardOnly').click(function () {
		SaveCardChip();
	});
});
// Unlock Middleware and Reset Verifone
$(document).ready(function () {
	$('#UnlockButton').click(function () {
		UnlockVerifone();
	});
});
```

### Creating your first EMV transaction

In the script file named EasyPayVerifone.js you can inspect the function named EMVSaleCombo():

EMVSaleCombo(SaveCard)

It expects the following objects

1. SaveCard ( true / false)
2. SessionKey ( string )
3. AccountHolder ( Json )
4. EndCustomer ( can be the same as Accountholder )
5. PurchaseDetails (Json)
6. Amount ( can be numeric value or JSON object )

The SessionKey is obtained by using our API to Authenticate.  Your Server can pass this down to your client side script.  &#x20;

The AccountHolder object looks like this. Note the embedded address object:

{% code overflow="wrap" %}

```
{"Firstname":"Jim","Lastname":"Smith","address":{"Address1":"21 Elm St","Address2":"","City":"Farmindale","State":"CA","ZIP":"83765","Country":"USA"},"Phone":"207-453-4587"}
```

{% endcode %}

The End Customer object is identical to the Accountholder object .  You may not have two objects so you can set both to the same value.

The PurchaseDetails object provides two user defined fields and a service description for your use and this object looks like this:

{% code overflow="wrap" %}

```
{"REFID":"41-96875","RPGUID":"1265432","ServiceDesc":"SERVICE DESCRIPTION HERE"}
```

{% endcode %}

The Amount object supports both a simple number such as "103.41" or an object such as the following:

{% code overflow="wrap" %}

```
{"baseAmt":"100.43","feeAmt":"2.01","totalAmt":"102.44"}   
```

{% endcode %}

If you don’t plan to collect processing fees then you can just send a simple numeric value.&#x20;

Once you have compiled all Json Object data you make your call to the local windows service as is outlined in the EasyPayVerifone.js script file.&#x20;

Here is a sample URL GET request:

{% code overflow="wrap" %}

```
https://localhost:8031/VerifoneSVC/service/GetEmvComboJson?SessKey=&AcctHolderJson={"Firstname":"Jim","Lastname":"Smith","address":{"Address1":"21 Elm St","Address2":"","City":"Farmindale","State":"CA","ZIP":"83765","Country":"USA"},"Phone":"207-453-4587"}&EndCustJson={"Firstname":"Jim","Lastname":"Smith","address":{"Address1":"21 Elm St","Address2":"","City":"Farmindale","State":"CA","ZIP":"83765","Country":"USA"},"Phone":"207-453-4587"}&PurchDetailsJson={"REFID":"41-96875","RPGUID":"","ServiceDesc":"SERVICE DESCRIPTION HERE"}&MerchID=1&Amount={"baseAmt":"100.43","feeAmt":"2.01","totalAmt":"102.44"}&SaveCard=false
```

{% endcode %}

### Resetting The Device&#x20;

The red Button on the Verifone can be used to Cancel the current operation and also to setup for the Ready State. \
\
Your software will be notified of the Reset should this Occur.

You can also call the function named UnlockVerifone(); which will reset both the software and the hardware so that you can once again enter the ready state. &#x20;

If you ever send a command to the Verifone Middleware while it is still processing the previous one, it will respond with an error stating that is it BUSY.  In the rare situation where the Middleware remains Busy for an unreasonable amount of time you can issue the UnlockVerifone(); command in order to return the device to the ready State. You can also press the red Button on the device 2 times to \
enter the ready state.

{% hint style="warning" %}
If you continue to receive a *Busy* response from the middleware, but you don't believe that waiting will yield productive results, you may use the `unlockVerifone` function to return the device to *Ready* state.
{% endhint %}

### Middleware response types

For browser type Verifone operations, the middleware provides a response object in XML format. This object can be de-serialized or can be consumed as XML. Currently, there are two response object types:

1. `WidgetArgs` - sale response when **requesting an authorization for a non-zero dollar amount**, with the option to save the card;
2. `WidgetArgs2` - consent response when **requesting to only save the card**.

### Consuming the sale response

It is important to consume the `WidgetArgs` response in a particular order, starting with `TxEventTyp`.

{% code title="Response example" overflow="wrap" %}

```xml
<?xml version="1.0" encoding="utf-16"?>
<WidgetArgs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <TxEventTyp>TxApproved</TxEventTyp>
    <ApprovedAmt>20</ApprovedAmt>
    <IsPartialApproval>false</IsPartialApproval>
    <RespMsg>APPROVED 801193</RespMsg>
    <ErrMsg />
    <TxnCode>801193</TxnCode>
    <TxID>19969</TxID>
    <ErrCode>0</ErrCode>
    <Mask>4663xxxxxxxx2741</Mask>
    <cardType>Visa</cardType>
    <ConsentResult>
        <ConsentCreated>true</ConsentCreated>
        <ConsentRequested>true</ConsentRequested>
        <ErrMsg />
        <ErrCode>0</ErrCode>
        <ConsentID>7849</ConsentID>
        <CardLast4>2741</CardLast4>
        <ExpDate>0528</ExpDate>
    </ConsentResult>
</WidgetArgs>
```

{% endcode %}

***

`TxEventTyp` string

The type of event that occurred during the transaction, indicating success or failure.

Values: TxApproved, TxDecline, TxReversed, PreSaleDeviceCode, PostSaleDeviceCode, TimeOut, AspenError, AuthFail, FunctionFail, Exception.

***

Here are actions to take for each possible value of `TxEventTyp`:

{% stepper %}
{% step %}
**TxApproved**

The sale was approved by the issuer. You should examine and store these values:

* `TxID` - the unique ID of the transaction; needed to refund or void the transaction.
* `TxnCode` - the transaction approval code.
* `ApprovedAmt` - the $ amount charged to the card.
  {% endstep %}

{% step %}
**TxDecline**

The sale was declined by the issuer. You should examine and store these values:

* `TxID` - the unique ID of the declined transaction.
* `TxnCode` - the transaction decline code.
  {% endstep %}

{% step %}
**TxReversed**

The issuer approved the transaction, however, during the final interaction with the chip, the device required the transaction to be declined, and the transaction was voided (reversed).
{% endstep %}

{% step %}
**PreSaleDeviceCode**

An error occurred within the device prior to the transaction getting submitted to the issuer. Examine `ErrCode` and `ErrMsg` for more information.
{% endstep %}

{% step %}
**PostSaleDeviceCode**

An error occurred within the device after the transaction was submitted to the issuer. Examine `ErrCode` and `ErrMsg` for more information.
{% endstep %}

{% step %}
**Timeout**

The user waited too long to insert the card or interact with the device. Examine `ErrCode` and `ErrMsg` for more information.
{% endstep %}

{% step %}
**AspenError**

An error occurred on Number Aspen Cloud processing servers. Examine `ErrCode` and `ErrMsg` for more information.
{% endstep %}

{% step %}
**AuthFail**

When doing a save card only operation, the issuer declined to verify the card details when executing a $0 authorization. The card will not be saved. You should examine:

* `TxID` - the unique ID of the declined transaction.
* `TxnCode` - the transaction decline code.
  {% endstep %}

{% step %}
**FunctionFail**

Returned when you supply improper or out of range values in the request, or when you execute a Verifone command while the previous action has not yet completed. Examine `ErrCode` and `ErrMsg` for more information.
{% endstep %}

{% step %}
**Exception**

An error was encountered in the local Windows service. Examine `ErrCode` and `ErrMsg` for more information.
{% endstep %}
{% endstepper %}

### Consuming the consent response

It is important to consume the `WidgetArgs2` response in a particular order, starting with `ConsentEventTyp`.

{% code title="Response example" overflow="wrap" %}

```xml
<?xml version="1.0" encoding="utf-16"?>
<WidgetArgs2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <ConsEventTyp>ConsentSuccess</ConsEventTyp>
    <AuthSuccess>true</AuthSuccess>
    <AuthMsg>APPROVED 632641|CVV||AVS|0</AuthMsg>
    <AuthTxID>16809</AuthTxID>
    <RespMsg>Success : Created Consent ID : 001270</RespMsg>
    <ErrMsg />
    <ConsentID>1270</TxnCode>
    <ErrCode>0</ErrCode>
    <Mask>4663xxxxxxxx2741</Mask>
    <cardType>Visa</cardType>
</WidgetArgs>
```

{% endcode %}

***

`ConsentEventTyp` string

The type of event that occurred during the save card on file operation, indicating success or failure.

Values: ConsentSuccess, ConsentFailed, PreConDeviceCode, PostConDeviceCode, TimeOut, AspenError, AuthFail, FunctionFail, Exception.

***

Here are actions to take for each possible value of `ConsentEventTyp`:

{% stepper %}
{% step %}
**ConsentSuccess**

The consent was created and card was saved successfully. You should examine and store `ConsentID` to be able to charge the customer later.
{% endstep %}

{% step %}
**ConsentFailed**

The consent was not created. Examine `ErrCode` and `ErrMsg` for more information.
{% endstep %}

{% step %}
**PreConDeviceCode**

An error occurred within the device prior to the card being submitted. Examine `ErrCode` and `ErrMsg` for more information.
{% endstep %}

{% step %}
**PostConDeviceCode**

An error occurred within the device after the data was submitted. Examine `ErrCode` and `ErrMsg` for more information.
{% endstep %}

{% step %}
**Timeout**

The user waited too long to insert the card or interact with the device. Examine `ErrCode` and `ErrMsg` for more information.
{% endstep %}

{% step %}
**AspenError**

An error occurred on Number Aspen Cloud processing servers. Examine `ErrCode` and `ErrMsg` for more information.
{% endstep %}

{% step %}
**AuthFail**

When doing a save card only operation, the issuer declined to verify the card details when executing a $0 authorization. The card will not be saved.
{% endstep %}

{% step %}
**FunctionFail**

Returned when you supply improper or out of range values in the request, or when you execute a Verifone command while the previous action has not yet completed. Examine `ErrCode` and `ErrMsg` for more information.
{% endstep %}

{% step %}
**Exception**

An error was encountered in the local Windows service. Examine `ErrCode` and `ErrMsg` for more information.
{% endstep %}
{% endstepper %}

***

## Number Verifone SDK <a href="#easy-pay-verifone-sdk" id="easy-pay-verifone-sdk"></a>

<figure><img src="/files/5aHD5uJoTnyULgzHz31P" alt=""><figcaption></figcaption></figure>

**Important :** You can not run both the Verifone Middleware and the Verifone SDK together at the same time. Both packages will need to have control over COM 9 so only one can be active at one time.

**Installation**

For you to directly interface with the Verifone using our SDK, you will need the Verifone drivers with the custom logging package, and the SDK reference files:

[USB drivers and Logging Package](https://easypay1.com/deploy/SetupVerifoneDrivers/Setup_USB_log_win11.zip)

[SDK Interface](https://easypay1.com/deploy/VerifoneSDK/EP.Enterprise.Vx820Lib2.zip)

When installed, the first component will provide USB drivers and create a virtual COM 9 port. In addition, it will add a unique event log to the existing windows event log collection.&#x20;

To install the first component, please do the following:

{% stepper %}
{% step %}
Connect your Verifone to the USB port which you plan to utilize.
{% endstep %}

{% step %}
Wait until the device is fully initialized.
{% endstep %}

{% step %}
Download and extract the ZIP file named *Setup\_USB\_log.zip* to the location of your choice.
{% endstep %}

{% step %}
Right click the EXE named *Setup\_USB\_log.exe* and choose *Run as administrator*.
{% endstep %}

{% step %}
After installation, there should be a new windows event log named *EPmiddleWare*.
{% endstep %}

{% step %}
With the Verifone plugged in you should also see an entry in the device manager attached to COM 9
{% endstep %}
{% endstepper %}

<figure><img src="/files/EtSZB0hu0fyZYlNR91e7" alt=""><figcaption></figcaption></figure>

To use the SDK, you only need to directly interface to the file named *EP.Enterprise.Vx820.dll*. The other files are dependencies. Make sure to extract all 4 of the files to the location of your choice.

<table data-header-hidden><thead><tr><th width="117"></th><th></th></tr></thead><tbody><tr><td><img src="/files/lbENUmvjFdGi7dei7n7O" alt=""></td><td>EP.Enterprise.Vx820Lib.dll</td></tr><tr><td><img src="/files/lbENUmvjFdGi7dei7n7O" alt=""></td><td>EP.Vx820.Common.dll</td></tr><tr><td><img src="/files/JJTNSaTp41z53PPmqJo0" alt=""></td><td>EP.Enterprise.Vx820Lib.dll.config</td></tr><tr><td><img src="/files/lbENUmvjFdGi7dei7n7O" alt=""></td><td>DPayments.DPaymentsSDK.dll</td></tr></tbody></table>

Number has developed a sample executable program using the SDK which allows you to authorize cards, save cards, and create payment plans:

[Sample Program Executable](https://easypay1.com/Deploy/VerifoneSDK/WinFrm.zip)

[Sample Program Source Code](https://easypay1.com/Deploy/VerifoneSDK/SourceCode_WinFrm.zip)

***

### Sample SDK Program&#x20;

<figure><img src="/files/W2uBesCyaKJQsJlNUHJD" alt=""><figcaption></figcaption></figure>

Initially you will need the following to begin processing cards&#x20;

* Number URL Endpoint ( API URL )&#x20;
* Account Code&#x20;
* Token&#x20;

For testing you can use the default URL supplied but it is important that you consult with Number personnel to determine the best endpoint prior to going live. Your Account code and Token will be supplied to you for your sandbox account.&#x20;

&#x20;

### EMV Sale&#x20;

Once you have authenticated you can proceed to the SALE page.

Take Notice of the MERCHID field as each Number Account can have one or more merchant records associated with it.  For Live accounts you will be provided a deployment form which identifies these along with their identifier {1,2,3} etc. &#x20;

For a typical Chip transaction, you only need to specify an amount and press INITIATE CHIP.  The device should now prompt you to insert the CHIP.  If you check the SAVE CARD checkbox then Number will VAULT the card details after the successful sale and return a CONSENT ID which you can use to authorize the card directly using our API at a later time.  If you want to KEY IN the card details directly into the VeriFone, you will enter Account Holder Information then press INITIATE MANUAL TRANSACTION. &#x20;

<figure><img src="/files/mhuk7UzEHmq82fPxfuQa" alt=""><figcaption></figcaption></figure>

### Programming Considerations

To reference the SDK&#x20;

<mark style="color:blue;">using</mark> EP.Enterprise.Vx820Lib;

**Important :** manage only one single instance of the class ( this allows you to operate on the COM 9 port )&#x20;

<mark style="color:blue;">private</mark> <mark style="color:purple;">EP\_Verifone\_Mod</mark> EPVerifone;

Here are some steps required prior to doing a card authorization &#x20;

```clike
private void Form1_Load(object sender, EventArgs e)
{

	// Instantiate Class . .assumes that this form will manage one instance of the class . . Only One instance should exist  . .  
	EPVerifone = new EP_Verifone_Mod();

	// subscribe to event which provides info concerning the transaction 
	EPVerifone.OnDeviceMsg += new EP_Verifone_Mod.TxHandler(On_Device_Msg);

	// subscribe to event which tells you when the card was removed  
	EPVerifone.OnCardRemoved += new EP_Verifone_Mod.CardRemovedHandler(On_Card_Removed);

	/// attempt to initiate the com port 
	if (!EPVerifone.InitComPort())
	{
		MessageBox.Show(EPVerifone.Err.SafeMessage);
		return;
	}

	/// attempt to open the com port 
	if (!EPVerifone.OpenPort())
	{
		MessageBox.Show(EPVerifone.Err.SafeMessage);
		return;
	}

	// do basic configuration ; which EasyPay API to use 
	EPVerifone.Url = EasyPayParams.APIurl;

	/// set ASPEN credentials 
	EPVerifone.Credentials.AccountCode = EasyPayParams.AccountCode;
	EPVerifone.Credentials.Token = EasyPayParams.Token;

	/// this will Initialize the module and validate your settings 
	if (!EPVerifone.InitMod())
	{
		MessageBox.Show(EPVerifone.Err.SafeMessage);
		return;
	}

} 
```

Now you can initiate a transaction&#x20;

```clike
private void Btn_InitChipTx_Click(object sender, EventArgs e)
{
	 //ensure your amount, fee, total are correct 
	if (!figureAmounts()) {
		return;
	}
	
	/// clear previous responses
	ClearResponseTbox();

	/// IMPORTANT !!  make sure the class is not already working on a transaction 
	if (EPVerifone.DeviceIsBusy)
	{   /// not you can use the UNLOCK command if class not responding 
		MessageBox.Show("Please wait for previous Transaction to complete");
		return;
	}

	/// attempt to open the com port IF NECCESARY 
	if (!EPVerifone.OpenPort())
	{
		MessageBox.Show(EPVerifone.Err.SafeMessage);
		return;
	}

	// set up a new transaction 
	EmvParams Params = new EmvParams();

	/// decide if you also want EasyPay to Save the card for Furure Payments 
	if (Chk_SaveCard.Checked) {
		Params.QuickSaveCard = true;
	}

	string Amt1 = Txt_Amount.Text.Replace("$", "").Replace(" ", "").Replace(",", "");
	decimal Amt2 = 0;


	if (!decimal.TryParse(Amt1, out Amt2)) {
		return;
	}

	if (Amt2 < 0.01M)
	{
		// need more than zero  
		return;
	}

	Params.Amounts = new EP_Amounts1(Amt, Fee, Total);

	Params.TxAmount = Params.Amounts.TotalAmt;
	Params.MerchID = (int)NumericMerchID.Value;
	Params.AcctHolder = new EP_Person();
	Params.AcctHolder.Firstname = txtFirstName.Text.Trim();
	Params.AcctHolder.Lastname = txtLastName.Text.Trim();
	Params.AcctHolder.BillIngAdress = new EP_Address();
	Params.AcctHolder.BillIngAdress.Address1 = txtAddress.Text.Trim();
	Params.AcctHolder.BillIngAdress.City = txtCity.Text.Trim();
	Params.AcctHolder.BillIngAdress.State = txtState.Text.Trim();
	Params.AcctHolder.BillIngAdress.ZIP = txtZip.Text.Trim();
	Params.AcctHolder.Email = Txt_Email.Text.Trim();

	Params.EndCustomer = new EP_Person();

	Params.EndCustomer.Firstname = txtCustFirstName.Text.Trim();
	Params.EndCustomer.Lastname = txtCustLastName.Text.Trim();
	Params.EndCustomer.BillIngAdress = new EP_Address();
	Params.EndCustomer.BillIngAdress.Address1 = txtCustAddress.Text.Trim();
	Params.EndCustomer.BillIngAdress.City = txtCustCity.Text.Trim();
	Params.EndCustomer.BillIngAdress.State = txtCustState.Text.Trim();
	Params.EndCustomer.BillIngAdress.ZIP = txtCustZip.Text.Trim();

	Params.RefID = txtRefID.Text.Trim();
	Params.RPGUID = txtRPGUID.Text.Trim();
	Params.ServiceDesc = txtServiceDesc.Text.Trim();


	/// in case you want to log your request 
	string MyString = Serialize(Params);

	/// initiate the transaction and wait for the event to fire . .
	if (!EPVerifone.InitiateEmvPayment(Params))
	{
		MessageBox.Show(EPVerifone.Err.SafeMessage);
		return;
	}
}
```

Wait for your transaction to complete and event will fire&#x20;

```clike
 private void On_Device_Msg(object e, TxArgs MyArgs)
 {
    /// This event Fires when Device has completed processing transaction ( fires in a separate thread ) 
  
    /// update textboxes from a foriegn thread 
   if (TxtApprovedAmt.InvokeRequired)
       TxtApprovedAmt.Invoke((MethodInvoker)delegate { TxtApprovedAmt.Text = MyArgs.ApprovedAmt.ToString("c"); });
   else
       TxtApprovedAmt.Text = MyArgs.ApprovedAmt.ToString("c");

   if (TxtResponseType.InvokeRequired)
       TxtResponseType.Invoke((MethodInvoker)delegate { TxtResponseType.Text = MyArgs.TxEventType.ToString(); });
   else
       TxtResponseType.Text = MyArgs.TxEventType.ToString();

   if (TxtIsPartialApproval.InvokeRequired)
       TxtIsPartialApproval.Invoke((MethodInvoker)delegate { TxtIsPartialApproval.Text = MyArgs.IsPartialApproval.ToString(); });
   else
       TxtIsPartialApproval.Text = MyArgs.IsPartialApproval.ToString();

   if (TxtErrMsg.InvokeRequired)
       TxtErrMsg.Invoke((MethodInvoker)delegate { TxtErrMsg.Text = MyArgs.ErrMsg; });
   else
       TxtErrMsg.Text = MyArgs.ErrMsg;

   if (TxtErrorCode.InvokeRequired)
       TxtErrorCode.Invoke((MethodInvoker)delegate { TxtErrorCode.Text = MyArgs.ErrCode.ToString(); });
   else
       TxtErrorCode.Text = MyArgs.ErrCode.ToString();

   if (TxtResponseMessage.InvokeRequired)
       TxtResponseMessage.Invoke((MethodInvoker)delegate { TxtResponseMessage.Text = MyArgs.RespMsg; });
   else
       TxtResponseMessage.Text = MyArgs.RespMsg;

   if (TxtTxID.InvokeRequired)
       TxtTxID.Invoke((MethodInvoker)delegate { TxtTxID.Text = MyArgs.TxID.ToString(); });
   else
       TxtTxID.Text = MyArgs.TxID.ToString();

   if (TxtTxnCode.InvokeRequired)
       TxtTxnCode.Invoke((MethodInvoker)delegate { TxtTxnCode.Text = MyArgs.TxnCode; });
   else
       TxtTxnCode.Text = MyArgs.TxnCode;


   /// GET CARD DETAILS HERE FOR CHIP OR MANUAL 
   TxHist lastTrans = EPVerifone.LastTransaction;

   TxEntryTypes EntryType = lastTrans.TxEntryTyp;
   if (EntryType == TxEntryTypes.EMV)
   {
      ///  must wait for card removed event to fire before you close port ( if at all)  , ( always use ClosePortSoft method ) 
   }
   else {
      ///  if it is not a chip transaction you can close the port if needed ( you dont have to close the port at all , but if you do always use the ClosePortSoft method )  
   }

   
   /// if a request was made to save the card you can gather the important paramters 
   string ConsentResults = "ConsentRequested=" + MyArgs.ConsentResult.ConsentRequested.ToString() + "; ConsentCreated=" + MyArgs.ConsentResult.ConsentCreated.ToString() + "; ConsentID=" + MyArgs.ConsentResult.ConsentID.ToString() + "; CardLast4=" + MyArgs.ConsentResult.CardLast4 + "; ExpDate=" + MyArgs.ConsentResult.ExpDate + "; ErrCode=" + MyArgs.ConsentResult.ErrCode + "; ErrMsg=" + MyArgs.ConsentResult.ErrMsg;

   /// if a request was made to save the card you can gather the important paramters 
   if (MyArgs.ConsentResult.ConsentRequested)
   {
       if (TxtSavedCardResults.InvokeRequired)
           TxtSavedCardResults.Invoke((MethodInvoker)delegate { TxtSavedCardResults.Text = ConsentResults; });
       else
           TxtSavedCardResults.Text = ConsentResults;
   }

   /// here we can gather info about the card which was processed 
    if (MyArgs.TxEventType == TxEventType.TxApproved || MyArgs.TxEventType == TxEventType.TxDecline)
   {
 
      string AcctNum =  lastTrans.CardNum;
      string CardType =  lastTrans.CardType;
      string Fname =  lastTrans.FirstName;
      string LastName =  lastTrans.LastName;
   }
   else
   {
      //  no need to look at Card details since no authorization was performed
   }


}
```

For additional coding samples including creating recurring payment plans please refer to the sample SDK program &#x20;

### Managing the Workflow&#x20;

Once you initiate a transaction the  EPVerifone class will set the DeviceIsBusy flag to True.  make sure you monitor this flag before attempting another transaction. EMV transactions can take time and you will expect the On\_Device\_Msg Event to Fire to alert you of the Results.  If for some reason the DeviceIsBusy flag stays true for an unreasonable amount of time you should issue the   UnLockAndReset(ref ErrStr) command which will reset both the SDK Software and the Verifone Device in order for you to once again enter the Ready State. There is also a Red Button on the Verifone device which you can press two times to reset the process and fire the On\_Device\_Msg Event.

### Custom Windows event log

After installing all the dependencies for either the SDK or the browser-based approach,, you will notice a new Windows event log has been registered named *EPmiddleWare*.&#x20;

This event log stores information about processed transactions as well as any errors encountered, and serves as a powerful troubleshooting component.

{% hint style="info" %}
With the Verifone Windows event log installed, a merchant can export the log and send it to Number if any unexpected behavior is encountered.
{% endhint %}

<figure><img src="/files/NAnsRFKIlq0gCzSoK4Vr" alt=""><figcaption></figcaption></figure>

***

## Verifone power settings

Both the middleware service and the SDK will attempt to maintain a continuous connection to the Verifone device. If your hardware is suspended or enters sleep, this can cause issues. To avoid these, please make sure to modify your USB power settings.

#### Windows 10 and Windows 11

For Windows 10, you'll need to go to Control Panel > Power Options > Edit Plan Settings.

On Windows 11, open Control Panel > Hardware and Sound > Power Options > Edit Plan Settings.

Go to *Advanced power settings* and change the *USB settings* to disable *USB selective suspend* for your active power plan.

{% hint style="danger" %}
When using the Verifone, **make sure that your machine is running the power plan with the modified settings**. All power plans have separate power settings.
{% endhint %}

<figure><img src="/files/E4XVWj5gv2NWTF6lJX2s" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/hsWKYRPz8ds8kDGtZ4Pb" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
If you don't see the USB power settings on your machine, you might need to expose them.

1. Run the Command Prompt as an administrator.
2. Type the command below you into the elevated command prompt, and press Enter:

{% code overflow="wrap" %}

```
REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Power\PowerSettings\2a737441-1930-4402-8d77-b2bebba308a3\48e6b7a6-50f5-4782-a5d4-53bb8f07e226 /v Attributes /t REG_DWORD /d 2 /f
```

{% endcode %}

3. After running the command, reboot your computer, then reopen your advanced power settings following the steps listed above.
   {% endhint %}

### Order Test Cards

You can order EMV test cards directly from the First Data Test Pack 2 available on OmniPay’s store. This pack includes a set of preconfigured test cards designed for EMV certification and integration testing, making it easy to validate transaction flows in your environment:

[https://omnipaystore.com/product/first-data-test-pack-2/](<https://omnipaystore.com/product/first-data-test-pack-2/&#xA; >)


# Virtual Terminal

Getting started with Virtual Terminal for Number

<figure><img src="/files/IBtYSPLw6UmuNJdUXeaG" alt=""><figcaption></figcaption></figure>

The Virtual Terminal is a web application that provides all types of credit card processing functionality. The VT is the fastest way to start trying out our payment services.&#x20;

When you log in to the Virtual Terminal, you are brought to the home screen. The number of open transactions and scheduled payments due display at the top of the screen. Your default merchant and user roles are listed just below, along with the expiration date of your password.&#x20;

<figure><img src="/files/M7aisqZx6Tkq0I99jBu1" alt=""><figcaption></figcaption></figure>

***

## Payments

Instructions on how to manage various payments using the Virtual Terminal.&#x20;

Before you start, you may want to read about using your Verifone device with the Virtual Terminal in the [Verifone](/documentation/getting-started/integration-options/verifone) guide.

### Non-EMV payments

Make non-EMV manual sales using the Virtual Terminal.

Click the *Credit Cards* tab on the left side of the screen, then *Sale*. Manually enter all of the information from your keyboard, and enter the $ amount to be charged.&#x20;

A guest ID or a service description can also be added here and searched for later. The ID will also print on the **receipt**, and the service description will print on the **settlement report**.

### EMV payments

Make EMV payments using the Virtual Terminal.

Click the *Credit Cards* tab on the left side of the screen, then on *Sale-EMV*.  You will then need to click on *Insert Chip* or *Manual Card Entry*.&#x20;

Clicking on *Insert Chip* will prompt the end-user or customer to insert or tap their card for contactless payments. For *Manual Card Entry*, the end user must enter the full card number, expiration date, and CVV code by pressing the green enter button on the Verifone after each entry.&#x20;

***

## Surcharging

Surcharge and convenience fees are automatically calculated during a credit card sale, both manual entry and EMV, as well as when charging an existing card on file.&#x20;

{% hint style="info" %}
**The surcharge / convenience fee is automatically calculated based on the percentage set in the Client Admin Portal and the card type used.** The Virtual Terminal will also ensure that fee does not go over the card brand rules of 3%.
{% endhint %}

Users have the option to waive the fee on any transaction if required. The fee can be waived before processing by checking the *Waive Fee* box on the form.

<figure><img src="/files/AclbSFAfnWlYCKXGYIKv" alt=""><figcaption></figcaption></figure>

The receipt will detail the charge amounts including the base amount, fee, and total amount charged. Rules require that the fee amount is visible to the customer. In addition to the receipts, the Virtual Terminal reporting and detail views show the fee as part of the total amount.

<figure><img src="/files/Bdz9Y5tGt1eKFc0Vqs78" alt=""><figcaption><p>The base, surcharge, and total amounts on the receipt</p></figcaption></figure>

<figure><img src="/files/4SQXbo8KLFSYC3NJSQly" alt=""><figcaption><p>The base, surcharge, and total amounts in the transaction list</p></figcaption></figure>

<figure><img src="/files/uC7KOlQ2H5F21GIOY8zc" alt=""><figcaption><p>The base, surcharge, and total amounts in transaction details</p></figcaption></figure>

***

## Create consents

All consent types allow a card to be charged without the card or customer being present. Consents can be created by swiping the card or manually entering the information.

A consent receipt is always created by the system for your customer to sign. We encourage your office to get signatures for consents whenever possible.

An email address can be added to the consent so your customer will receive a receipt when the consent has been used.&#x20;

### Annual and one-time

Creating annual and one-time consents allows your office to charge a card at a later date. **This can be useful in situations where you expect a balance to be due after services have been provided.**

An annual consent can be used multiple times, and a one-time consent can only be used once.&#x20;

{% hint style="info" %}
Both annual and one-time consents are valid until the card expires or 365 days have passed.
{% endhint %}

#### Create an annual consent or a one-time consent

Click the *Consents* tab on the left side of the screen, then *Create Annual Consent*, *Create Annual: EMV*, or *Create One-Time Consent* depending on the type of consent you need and payment method.

<figure><img src="/files/gwmpXtm2jSRl7HD7R09W" alt=""><figcaption></figcaption></figure>

Annual consents require that a max charge be determined as a limit per transaction. This can be any $ amount determined by your office.&#x20;

An email address can also be added to the consent so your customer will receive a receipt when the consent has been used.&#x20;

### Fixed recurring

Creating a fixed recurring consent allows your office to set up a payment plan with your customer.  **This can be useful in situations where your customer has an outstanding balance due.**

{% hint style="info" %}
Fixed recurring consents can be setup for any length of time.
{% endhint %}

#### Create a fixed recurring consent

Click the *Recurring* tab on the left side of the screen, then *Create Recurring Consent* or *Create Recurring: EMV* based on the payment method.

<figure><img src="/files/TfzDM08DBYNwqEUdeill" alt=""><figcaption></figcaption></figure>

An email address can be added to the consent so your customer will receive a receipt

### Subscription

Creating a subscription consent allows your office to set up a re-occurring payment indefinitely. **This can be useful in situations where your customer makes a regular donation or payment to your organization.**&#x20;

{% hint style="info" %}
The subscription consent end date is always automatically set to the card expiration date.
{% endhint %}

#### Create a subscription consent

Click the *Recurring* tab on the left side of the screen, then *Create Subscription*.

<figure><img src="/files/6JNer1aTWuT6SMniL0li" alt=""><figcaption></figcaption></figure>

Subscription payments can be processed manually or automatically depending on your preference. You can change the payment amount as well as the scheduled dates for your subscription consent.&#x20;

To alter the schedule, you will modify the *Payment Adjust Date*. **The system will discard the previously scheduled payment plan and calculate a new one.** Only those scheduled payments for today and beyond will get processed, and it will not attempt to process payments for dates in the past.&#x20;

You can also place a subscription on hold. **This will pause all processing until the hold is released.** Once released, payments will resume for all present and future payments as calculated using your dates and amounts.

***

## Consent list

The consent list is where you will manage your consents after they have been created. The query filter can be used to search your consent list.

Click the *Reports* tab on the left side of the screen, then *Consents*.

<figure><img src="/files/GGFAnp0WMeBRGL8L3IjT" alt=""><figcaption></figcaption></figure>

#### Consent operations

In the *Consent Operations* box right above the table, there are several options available to help you manage your consents. **The availability of each option will vary depending on whether the selected consent is annual or recurring.**

{% stepper %}
{% step %}

#### **Edit**

The edit screen allows you to add or change the email address associated with consent, update the billing zip code and expiration date, add or change the reference ID and service description.
{% endstep %}

{% step %}

#### Full Detail

Displays all of the information associated with the consent.
{% endstep %}

{% step %}

#### Cancel Consent

This option will open a dialog box to confirm you want to cancel the consent.
{% endstep %}

{% step %}

#### List Transactions

Lists transactions that have been processed on the selected consent.
{% endstep %}

{% step %}

#### Edit Schedule

This option will open a dialog box that lists the payment schedule for a fixed recurring consent. We recommend using this to postpone a payment or two.&#x20;

{% hint style="warning" %}
If your customer wants to change the schedule completely, it is recommended that you cancel the existing consent and create a new one.
{% endhint %}
{% endstep %}

{% step %}

#### Charge

Use when you want to charge an amount to annual and one-time consents.

<figure><img src="/files/wr7uQNRiab0xdo00x3sw" alt=""><figcaption></figcaption></figure>
{% endstep %}
{% endstepper %}

#### **Receipts**

Allows you to reprint the consent agreement. You can choose between the customer, merchant, and dual receipt options.

***

## Scheduled payments

The scheduled payments view is where you will view and manage all scheduled payments.

Click the *Scheduled* option on the left side of the screen.

<figure><img src="/files/uUujAd2RDaJ1mI1PN6ns" alt=""><figcaption></figcaption></figure>

#### Schedule Operations

Run fixed recurring consents and subscriptions.&#x20;

{% hint style="success" %}
Scheduled payments can also be run automatically on the day they are due. [Contact Number](/help/customer-support) and we'll turn this feature on up for you.
{% endhint %}

Filter the consents you want to run by date range and consent type. Once you have the consents you want to charge filtered, you can click *Process All to **process all payments due***. You can also individually select consents and run them by clicking *Process Selected*.&#x20;

The option to *Reschedule* or *Cancel Payment* are also available.

#### Failed Payments

If a customer’s card is declined, you will receive a notification report.

#### Payment History

Displays a history of payments run on a particular consent through the *Scheduled Payments* option.

***

## Transaction list

The transaction list is where you will view and manage the transactions.

Click the *Reports* tab on the left side of the screen, then *Transactions*.

<figure><img src="/files/PfOvNPCyvMNTjFWhXgw0" alt=""><figcaption></figcaption></figure>

#### Transaction operations

In the *Transaction Operations* box right above the table, there are several options available to help you manage your transactions.

{% stepper %}
{% step %}

#### Void

Voids can be performed the same day as the transaction before settlement.&#x20;

{% hint style="warning" %}
Transactions under *HOST* with a surcharge can only be voided within 20 minutes of the transaction's approval.
{% endhint %}
{% endstep %}

{% step %}

#### Credit

Credits (refunds) can be processed after settlement.
{% endstep %}

{% step %}

#### **Full Detail**

Displays all the transaction details.
{% endstep %}
{% endstepper %}

#### Receipts

Reprint the receipts. You can choose between the customer, merchant, and dual receipt options.

### Transaction filter

Filter transactions based on the merchant the transaction was processed under, the date range, transaction status, and transaction type.&#x20;

#### Transaction status and type filters

For filtering by transaction status and transaction type, see the table below.

<table><thead><tr><th valign="top">TxStatus</th><th valign="top">TxType</th></tr></thead><tbody><tr><td valign="top"><em>OPEN</em> - An authorized transaction that has not been settled.</td><td valign="top"><em>CCAUTHONLY</em> - Authorization only, not a live transaction.</td></tr><tr><td valign="top"><em>SETTLED</em> - A finalized transaction sent for deposit to your account.</td><td valign="top"> <em>CCSALE</em> - An authorized transaction.</td></tr><tr><td valign="top"><em>FAILED</em> - Transaction did not receive an authorization.</td><td valign="top"><em>CCFORCE</em> - Number Support team use only.</td></tr><tr><td valign="top"><em>LOCKED</em> - Transaction has an error.</td><td valign="top"><em>CCVOICE</em> - Transaction authorized by voice authorization operator.</td></tr><tr><td valign="top"><em>VOID</em> - Transaction was voided.</td><td valign="top"><em>CCADJUST</em> - A credit issued through administrative adjustment. Number Support team use only.</td></tr><tr><td valign="top"><em>HOST</em> - Transactions with surcharge or a convenience fee.</td><td valign="top"><em>CCCREDIT</em> - A credit transaction refunded to customer card.</td></tr></tbody></table>

### Transaction search

Search your database, create reports based on results, void, credit, and reprint receipts.

<figure><img src="/files/8EXOFh4kMZp8A6kdMNt4" alt=""><figcaption></figcaption></figure>

#### Search for

Find the search value in a specific field by using the *Search for a* dropdown.

<table><thead><tr><th valign="top">Search field type</th></tr></thead><tbody><tr><td valign="top"><code>Acct LastName</code> - Last name of the cardholder.</td></tr><tr><td valign="top"><code>Acct FirstName</code> - First name of the cardholder.</td></tr><tr><td valign="top"><code>Cust LastName</code> - Last name of the customer (if different than cardholder).</td></tr><tr><td valign="top"><code>Cust FirstName</code> - First name of the customer (if different than cardholder).</td></tr><tr><td valign="top"><code>RefID</code> - The custom user-defined value entered at the time of transaction.</td></tr><tr><td valign="top"><code>Amount</code> - The $ amount of the transaction.</td></tr></tbody></table>

#### Search value

The value to search for in the specified field.

#### Search type

Choose the desired comparison type for search.

***

## Settlements

View and manage the settlements.

Click the *Settlement* option on the left side of the screen.

<figure><img src="/files/BOuLbR9CuAVib36oHJJE" alt=""><figcaption></figcaption></figure>

#### Manually settle transactions.&#x20;

Select the appropriate merchant account.&#x20;

Select individual transactions, and click *Settle Selected*. Click *Settle All* to settle all open transactions, or click *Preview Batch* to see what will be settled.

***

## Batch history

Displays a list of your settlements and allows for reprinting of batch reports.

Click on the *Reports* tab on the left side of your screen, then *Batch History*.

<figure><img src="/files/sWLfmTI8zWja23v2JoEO" alt=""><figcaption></figcaption></figure>

***

## Miscellaneous

In the upper right-hand corner of the screen, there is a menu of miscellaneous operations.

<figure><img src="/files/fbxNTt4sFO1XVDNw2zuK" alt=""><figcaption></figcaption></figure>

{% stepper %}
{% step %}

#### My Settings

Update your name, email, cellphone number, and change your password
{% endstep %}

{% step %}

#### Contact Us

Displays our support phone number and allows you to send us a secure email.
{% endstep %}

{% step %}

#### Logout

Log out and end your session with the Virtual Terminal. An open session will automatically log the user out after 15 minutes of inactivity.

{% hint style="danger" %}
**Remember to always log out or lock your computer when walking away from your workstation!**
{% endhint %}
{% endstep %}
{% endstepper %}

***

## Lockouts

In order to protect our client’s information, it is necessary for us to lockout users who cannot provide correct credentials. **A lockout will occur if incorrect credentials are entered 6 times in a row.**&#x20;

There are two types of lockouts:&#x20;

* **User lockout** occurs when a user entered their **password** incorrectly for 6 successive attempts.&#x20;
* **Endpoint lockout** causes your entire office to be locked out because the **username** entered was unknown to our system, and used for 6 successive attempts.&#x20;

{% hint style="info" %}
If you are experiencing problems authenticating, contact your administrator to reset your credentials. **We recommend to do this before the 6th attempt which could cause a lockout.**
{% endhint %}

If you do experience a **user lockout**, you will need to follow these steps to continue:

{% stepper %}
{% step %}

#### Get new credentials

Obtain new or updated credentials from your administrator
{% endstep %}

{% step %}

#### Reset the terminal

Visit the [reset page](https://easypay5.com/reset) to clear any cookies that have been set on your terminal.
{% endstep %}

{% step %}

#### Try using your new credentials

Login with the new or updated credentials.
{% endstep %}
{% endstepper %}

If you do experience an **endpoint lockout**, you will first need to need to call the [Number support team](/help/customer-support) to get the lock removed, then follow the instructions for a user lockout.&#x20;

### Expired passwords&#x20;

As an additional security precaution, passwords expire after 4 months. You can see your password expiration date every time you log into the Virtual Terminal. &#x20;

You may choose to change your password as often as you wish, however you must change your password every 4 months at a minimum. **Entering an expired password 6 times in succession will cause a user lockout as described above.**

&#x20;


# WooCommerce Plugin

Classic WooCommerce Payment Plugin for PayForm

The Number WooCommerce Gateway plugin enables merchants to securely accept credit and debit card payments using Number’s hosted [PayForm](/documentation/getting-started/integration-options/payform). No additional programming is required, as the plugin automatically generates the PayForm URL and processes transaction results.

#### Features

* Secure hosted card collection powered by PayForm
* PCI-compliant tokenized payment processing
* Native WooCommerce checkout integration
* Securely save payment methods for faster repeat purchases
* Full and partial refund capabilities
* Surcharging support
* Express checkout with Apple Pay and Google Pay
* Customizable form styling

#### Software Requirements

* Minimum WordPress Version: 7.0
* WooCommerce Version: 10.6.1
* WooCommerce checkout pages must be set to *Classic Shortcode (*[*see WooCommerce Docs*](https://woocommerce.com/document/woocommerce-store-editing/customizing-cart-and-checkout/#incompatible-extensions)*)*

#### Install the Plugin

1. Upload the plugin zip via WordPress Admin&#x20;
2. Activate the plugin
3. Navigate to WooCommerce → Settings → Payments and enable Number Gateway
4. Enable open\_ssl in the php.ini file by uncommenting `extension=openssl`.
5. Add the encryption key that corresponds to your eIndex. While you are using test credentials you will use our sandbox test key.

```
Add the environment variable Number_ENCRYPTION_KEY and set it's value.

Modify the wp-config.php file to access the key as shown below:

/* Add any custom values between this line and the "stop editing" line. */
define('Number_ENCRYPTION_KEY', getenv('Number_ENCRYPTION_KEY') ?: ($_SERVER['Number_ENCRYPTION_KEY'] ?? null));
/* That's all, stop editing! Happy publishing. */
```

{% file src="/files/kleBqMwynlVUqGmRBa8r" %}

#### Configuration and Settings

**General Settings**

<table><thead><tr><th width="186">Setting</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td>Enable/Disable</td><td>Enables or disables the Number payment gateway. When enabled, customers will be able to select this payment method during checkout.</td><td>no</td></tr><tr><td>Title</td><td>Defines the payment method title displayed to customers during checkout.</td><td>Credit Card Payment</td></tr><tr><td>Description</td><td>Controls the description shown to customers beneath the payment method title.</td><td>Pay securely using NumberPayments.</td></tr></tbody></table>

**API Settings**

<table><thead><tr><th width="189.4000244140625">Setting</th><th>Description</th><th>Default</th></tr></thead><tbody><tr><td>API Key</td><td>The API Key provided by Number.</td><td></td></tr><tr><td>Key Expires</td><td>The expiration date of the API key.</td><td></td></tr><tr><td>Merchant ID</td><td>The merchant ID from your Number account.</td><td></td></tr><tr><td>API URL</td><td>Endpoint URL used to submit payment transactions. </td><td><a href="https://easypay5.com/ApicardProcRest/v1.0.0">https://easypay5.com/ApicardProcRest/v1.0.0</a></td></tr><tr><td>eIndex</td><td>Encryption key index used by the hosted payment form.</td><td>300</td></tr></tbody></table>

**Payment Form Fields and Styling**

These settings control the appearance and behavior of the hosted payment form. There are a number of fields you can have added to your form. For some of the fields, you can choose to provide a default value, and to mark them as read-only.

{% hint style="info" %}
The PayForm Builder tool can be used to help configure these settings. It is available at <https://easypay8.com/byopayform>.
{% endhint %}

| Setting     | Description                                                                                                                                              | Default                                                 |
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
| Widget Type | Determines which transaction type the widget collects. Available options: `payment` (Standard payment form), `combination` (Combo widget configuration). | payment                                                 |
| Visible     | Controls which payment form fields are visible to the customer. Example configuration values are determined by the PayForm Builder tool.                 | 0600                                                    |
| ReadOnly    | Determines whether specific payment fields are read-only.                                                                                                | 0000                                                    |
| Styles      | Controls predefined style configuration options for the payment form.                                                                                    | 0001                                                    |
| Colors      | Defines the color palette used by the payment form.                                                                                                      | #ffffff,#428bca,#007bff,#212121,#ffffff,#212121,#ffffff |

#### PayForm Configuration and Features

Additional payment form functionality and validation settings.

| Setting           | Description                                                                                                                   | Default |
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------- |
| Enable Wallets    | Enables supported digital wallets during checkout. Supported wallets: Apple Pay and Google Pay.                               | no      |
| Apple Pay Domain  | The domain registered with Apple for Apple Pay verification.                                                                  |         |
| AVS Partial Match | Requires only the ZIP/postal code to match the card issuer records.                                                           | no      |
| CVV Match         | Requires the card security code (CVV) to match the issuer records. If the CVV does not match, the transaction will be voided. | no      |

#### FAQ

<details>

<summary><strong>Are card details stored on my website?</strong></summary>

**No**. Card details are collected securely using PayForm and tokenized by the payment provider. Sensitive card data is not stored on your WooCommerce site.

</details>

<details>

<summary><strong>Does the plugin support saved payment methods?</strong></summary>

**Yes**. Logged-in customers can securely save their payment methods for faster future purchases.

</details>

<details>

<summary><strong>Does it work with WooCommerce Blocks?</strong></summary>

**No**, not at this time. The current plugin supports WooCommerce classic checkout.

</details>


# Text2Pay

One of our most popular features enables you to generate payment links on demand through the API and deliver them directly to cardholders via SMS or email.

The API call needed to invoke this activity is shown here: [Text to Pay](https://docs.number.tech/api-reference/rest-api/text-to-pay)

With a single API call, you can configure the payment experience by controlling visible and read-only fields, customizing form behavior and styling, and including a personalized message for the recipient. The payment form can be pre-populated with customer information such as name, address, and Patient ID. You may also provide reference data or other contextual information, which will be associated with the transaction after authorization.

#### Field Descriptions&#x20;

MessageType: ( TEXT,EMAIL,URLONLY ,SMS)\
RefID: ( user defined field )&#x20;\
RPGUID: ( user defined field )

*MessageBody:* (here you can create a custom message to send via text or email)&#x20;\
*AcctHolderID:* ( NOT USED )&#x20;\
*Amount:* ( payment amount )&#x20;\
*ConsentID:* ( NOT USED )&#x20;\
*DueOn:* ( can be shown in message to indicate when payment is due  )\
*EINDEX:* ( can be used to indicate encrypted webhook )&#x20;\
*MerchID:* ( Must provide a valid Merchant record index for the Account used )&#x20;\
*TXID:* (NOT USED)&#x20;\
*WType:*  ( use SW here )&#x20;\
*RedirectURL:*  ( we can redirect to your site and pass real-time info after authorization )&#x20;\
*WidgetURL:* ( we will provide you the proper address for your payment form )\
*ExpiresOn:* ( we can display the link expiration date within your message)&#x20;\
*SingleUse:* ( enter a 1 to restrict the link to be used more than one time for payment )&#x20;\
*OptParam:* (this provides a means for us to configure and style the payment form)\
*Questions:* ( NOT USED )&#x20;

#### Defining your Form&#x20;

The OPTPARAM field defines the payment form in terms of visible fields, read-only fields, styles and behavior.  We use a specific tool to generate this value found here  <https://easypay8.com/byowidget/> .  You may select the options you desire then press GENERATE OPTPARAMS.  We are always glad to assist you with defining your form as this is a very important part of collecting payments. &#x20;

#### Sending a Simple TEXT Message ( Use Option TEXT )

here you can use the *MessageBody Field* &#x20;

When sending a TEXT/SMS, it is best to keep the message short and sweet. it is for this reason we have a DEFAULT message which you can use by simply leaving this field empty.&#x20;

We will simply pull a few details from your request such as:

MERCHANT NAME, AMOUNT, PAYMENT DUE DATE, LINK EXPIRATION

**The resulting text message will read as Follows**&#x20;

<sup>*You have a Payment Due to ( Merchant Name ) of (Amount) due on ( Due Date ) .  Follow the link below to make payment (Payment Link) This Link Expires on ( Exp Date )*</sup>&#x20;

If you decide to create your own message we will append the following to your message:

<sup>*Follow the link below to make payment (Payment Link) This Link Expires on ( Exp Date )*</sup>&#x20;

#### Sending a Custom SMS Message ( Use Option SMS )

For the This Option you must create a custom message. To help create your message we have provided some Variable fields: Please include the "||" characters.&#x20;

* ||Merch1||  when we see this in your message we will replace it with the actual Merchant name
* ||Amt||  when we see this in your message we will replace it with Amount specified
* ||PayLink||  when we see this in your message we will replace it with the payment link
* ||DueOn||  when we see this we will replace it with the Date you specify for payment due date
* ||ExpOn||  when we see this we will replace it with the Date you specify for payment link expiration Date&#x20;

The SMS option does NOT support HTML tags however you can force a Line Break with "\n"

**Adding your own HTML Links**

Here is an example of an Html Link you may wish to insert:

[https://mypatientportal.com/statement/page1.php?ID=457](<https://mypatientportal.com/statement/page1.php?ID=457  >)

In order to insert this into your custom SMS you will need to extract ALL the text and convert to a Byte Array represented as HEXADECIMAL then place between Custom Tag Z as follows \<z....\<z/>&#x20;

for the above example you will end up with the following&#x20;

\<z68747470733A2F2F6D7970617469656E74706F7274616C2E636F6D2F73746174656D656E742F70616765312E7068703F49443D343537\</z>

Here is an example Custom Message for SMS using the variables above

Dear John Doe\nThis is a friendly reminder that you have an outstanding balance of ||Amt|| for your visit on 5/5/2026 with ||Merch1|| Due On ||DueOn||. Please follow this link to make payment ||PayLink||\n and click here for Statement\n\<z68747470733A2F2F6D7970617469656E74706F7274616C2E636F6D2F73746174656D656E742F70616765312E7068703F49443D343537\</z>

**The resulting text message will read as Follows**&#x20;

<figure><img src="/files/TLO3PFVxNSVxknK2kDF5" alt=""><figcaption></figcaption></figure>

#### Sending a Custom EMAIL Message&#x20;

For the Email Option you must create a custom message. To help create your message we have provided some Variable fields: Please include the "||" characters.&#x20;

* ||Merch1||  when we see this in your message we will replace it with the actual Merchant name
* ||Amt||  when we see this in your message we will replace it with Amount specified
* ||PayLink||  when we see this in your message we will replace it with the payment link
* ||DueOn||  when we see this we will replace it with the Date you specify for payment due date
* ||ExpOn||  when we see this we will replace it with the Date you specify for payment link expiration Date&#x20;

**Adding your own Anchor tags**&#x20;

Here is an example of an Anchor tag you may wish to insert:

\<a href="[https://MypatientPortal.com/Statement/page1.php?ID=457">Click](https://MypatientPortal.com/Statement/page1.php?ID=457">Click) Here for Statement\</a>

In order to insert this into your custom Email you will need to extract ALL the text between the Anchor Tags ( IINCLUDING SPACES ) and convert to a Byte Array represented as HEXADECIMAL&#x20;

for the above example you will end up with the following&#x20;

\<a20687265663D2268747470733A2F2F4D7970617469656E74506F7274616C2E636F6D2F53746174656D656E742F70616765312E7068703F49443D343537223E436C69636B206865726520666F722053746174656D656E74\</a>

&#x20;

Here is an example Custom Message for EMAIL using the variables above

\<b>Dear John Doe,\</b>\<br />\<br />This is a friendly reminder that you have an outstanding balance of \<br /> $26.56 for your visit on 5/5/2026 with ||Merch1||. \<br />\<br />This payment is due on ||DueOn||. You can easily review your statement and submit your payment securely through our patient Portal \<br />\<br />Or you can also safely follow the link shown here.\<br />||PayLink||\<br />This Link Expires on ||ExpOn||\<br />\<br />\<a20687265663D2268747470733A2F2F4D7970617469656E74506F7274616C2E636F6D2F53746174656D656E742F70616765312E7068703F49443D343537223E436C69636B206865726520666F722053746174656D656E74\</a>\<br />\<br />\<b>Thank You\<br/>||Merch1|| Billing Dept\</b>

&#x20; Here is the resulting email message:&#x20;

<figure><img src="/files/KaJ1N113xWBIgwazQGTE" alt=""><figcaption></figcaption></figure>


# Basics

How to correctly integrate with Number and our backend

If you choose to use the REST API, we recommend you to read about [Authentication](/documentation/getting-started/basics/authentication), [API Best Practices](/documentation/getting-started/basics/api-best-practices), and [API Input Validation](/documentation/getting-started/basics/api-input-validation). You may also want to refer to the resources about [Querying](/documentation/resources/querying) and [Error Codes](/documentation/resources/error-codes) once you start working on the integration.

Here are the articles in this section:

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Authentication ></strong></td><td><a href="/pages/EaDC5Lrnndv0FVDZ16nx">/pages/EaDC5Lrnndv0FVDZ16nx</a></td></tr><tr><td><strong>API Best Practices ></strong></td><td><a href="/pages/O4skKwGvwu6Bnp83WZ8H">/pages/O4skKwGvwu6Bnp83WZ8H</a></td></tr><tr><td><strong>API Input Validation ></strong></td><td><a href="/pages/ANRlDOIxkqeWrI1GmtCl">/pages/ANRlDOIxkqeWrI1GmtCl</a></td></tr></tbody></table>


# Authentication

How to authenticate with the Number backend

<figure><img src="/files/Fj4hgVje5vNDu2WWJdiE" alt=""><figcaption></figcaption></figure>

The REST API provides their own methods for authenticating with Number. You will need to use them to receive a `SessKey`. To authenticate, you need to provide your `AccountCode` and `Token`.

***

***

***

As a result of authentication, you will obtain a session key. This key is required to prove your identity when using any of the other methods provided by our backend.

***

***

It is required that you manage a session key throughout any 24-hour period:&#x20;

You will need to reauthenticate when one of the following two errors occurs:&#x20;

{% hint style="danger" %}
**Error 5030: Expired session - session key has expired after 25 hours**
{% endhint %}

{% hint style="danger" %}
**Error 5050: Unauthorized - your IP has changed since you last authenticated**
{% endhint %}

The system will lock your IP out if you send 6 unsuccessful authentication attempts in a row. **Always abort unsuccessful authentication attempts instead of retrying and notify the user.** Only the Number support team can remove the lock from a merchant.

We recommend that either manage a session key object for 24 hours or simply use the key until you receive one of above errors at which time you will RE-Authenticate.

***

## HMAC and RSA

{% hint style="info" %}
The HMAC and RSA section only applies to using the REST API.
{% endhint %}

If you are not passing cardholder data through the REST API, you only need the session key to authenticate and connect to your account. Otherwise, you need to use a signature secured by an HMAC secret and and encrypt the cardholder data using our RSA certificate.

### HMAC header

When required to secure the request, the `SessKey` header will need to include additional data.

***

***

This altered key should be passed instead of the plain session key using a header with the same name, `SessKey`. Here are some examples of creating the header signature:

### RSA encryption

When the REST API traffic originates from unknown networks or mobile devices, we also mandate that any credit card numbers be encrypted prior to building your request. You can download our RSA 2048 certificate and use the public key to encrypt the cardholder information.&#x20;

{% hint style="info" %}
When passing cardholder data through our REST API, only the credit card number needs to be encrypted using RSA, the expiration date and CVV can be left as is.
{% endhint %}

{% hint style="warning" %}
When encrypting sensitive cardholder data, use RSA encryption padding of OaepSHA1. \
Encrypted card numbers will always have 512 bytes.
{% endhint %}

Examples of RSA encryption:

{% tabs %}
{% tab title="C#" %}

<pre class="language-csharp" data-overflow="wrap" data-line-numbers><code class="lang-csharp">using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;

// Example card number to encrypt
string myCardNumber = "4111111111111111";

X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
X509Certificate2? myCert = null;

store.Open(OpenFlags.ReadOnly);
bool certFound = false;

// Search for cert within store either by thumbprint or subject 
foreach (X509Certificate2 cert in store.Certificates)
{
  if (cert.Subject.Contains("mobile.easypay5.com"))
  {
    myCert = cert;
    certFound = true;
    break;
  }
}

if (!certFound || myCert == null)
{
  MessageBox.Show("Unable to find the certificate");
  return;
}

byte[] plainBytes = Encoding.UTF8.GetBytes(myCardNumber);
RSA? rsaPublicKey = myCert.GetRSAPublicKey();

if (rsaPublicKey == null)
{
  MessageBox.Show("Unable to get RSA public key from the certificate");
  return;
}

// Use the OaepSHA1 RSA encryption padding
<strong>byte[] encryptedBytes = rsaPublicKey.Encrypt(plainBytes,
</strong><strong>  RSAEncryptionPadding.OaepSHA1);
</strong>
// Convert to Base64 before sending to the API
string encryptedString = Convert.ToBase64String(encryptedBytes);

// Example payload for the API
string jsonPayload = $@"
{{
    ""ccCardInfo"": {{
        ""AccountNumber"": ""{encryptedString}"",
        ""ExpMonth"": 10,
        ""ExpYear"": 2028,
        ""CSV"": ""122""
    }}
}}";

</code></pre>

{% endtab %}

{% tab title="Java" %}

<pre class="language-java" data-overflow="wrap" data-line-numbers><code class="lang-java">package NumberEncrypt;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.Enumeration;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

public class EncryptCard {

  public static void main(String[] args) {

    CertificateDetails certDetails = getCertificateDetails(
      "C:\\Users\\BobSmith\\Downloads\\mobile_easypay5_com.cer", "");
    String myCardNumber = "4111111111111111";
    byte[] plainbytes = myCardNumber.getBytes(StandardCharsets.UTF_8);
    try {
      Cipher cipher = Cipher.getInstance(
        "RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
      cipher.init(Cipher.ENCRYPT_MODE,
        certDetails.getX509Certificate().getPublicKey());
      byte[] encryptedBytes = cipher.doFinal(plainbytes);
      String eBytesString = Base64.getEncoder()
        .encodeToString(encryptedBytes);
      System.out.println(eBytesString);

    }
    catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    }
    catch (NoSuchPaddingException e) {
      e.printStackTrace();
    }
    catch (InvalidKeyException e) {
      e.printStackTrace();
    }
    catch (IllegalBlockSizeException e) {
      e.printStackTrace();
    }
    catch (BadPaddingException e) {
      e.printStackTrace();
    }
  }

<strong>  public static CertificateDetails getCertificateDetails(
</strong><strong>    String jksPath, String jksPassword) {
</strong>
    CertificateDetails certDetails = null;
    try {
      // Provide location of Java Keystore and password for access
      KeyStore keyStore = KeyStore.getInstance("Windows-MY");
      keyStore.load(
        new FileInputStream(jksPath), jksPassword.toCharArray());

      // Iterate over all aliases
      Enumeration&#x3C;String> aliasEnum = keyStore.aliases();
      String alias = "";
      while (aliasEnum.hasMoreElements()) {
        alias = (String)aliasEnum.nextElement();
        if (alias.contains("mobile.easypay5.com")) {
          break;
        }
      }
      Certificate[] certChain = keyStore.getCertificateChain(alias);
      certDetails = new CertificateDetails();
      certDetails.setX509Certificate((X509Certificate)certChain[0]);
    }
    catch (KeyStoreException e) {
      e.printStackTrace();
    }
    catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    }
    catch (CertificateException e) {
      e.printStackTrace();
    }
    catch (FileNotFoundException e) {
      e.printStackTrace();
    }
    catch (IOException e) {
      e.printStackTrace();
    }

    return certDetails;
  }
}

package NumberEncrypt;

import java.security.PrivateKey;
import java.security.cert.X509Certificate;

public class CertificateDetails {

  private PrivateKey privateKey;
  private X509Certificate x509Certificate;
  public PrivateKey getPrivateKey() {
    return privateKey;
  }
  public void setPrivateKey(PrivateKey privateKey) {
    this.privateKey = privateKey;
  }
  public X509Certificate getX509Certificate() {
    return x509Certificate;
  }
  public void setX509Certificate(X509Certificate x509Certificate) {
    this.x509Certificate = x509Certificate;
  }
}
</code></pre>

{% endtab %}

{% tab title="JavaScript (Node.js)" %}
{% code overflow="wrap" lineNumbers="true" %}

```javascript
const crypto = require("crypto");
const fs = require("fs");
​
var myCardNumber = "4761530001111118";
​
try {
  const publicKey = Buffer.from(
    fs.readFileSync("mobile.easypay5.com.pem", { encoding: "utf-8" })
  );
​
  const encryptedData = crypto.publicEncrypt({
      key: publicKey,
      padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
      oaepHash: 'sha1',
    },
    Buffer.from(myCardNumber) // Convert the string to a buffer
  );
​
  const encryptedString = encryptedData.toString("base64");
}
catch (error) {
  console.error("Error encrypting card data:", error);
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

#### Encrypted test cards <a href="#test-cards" id="test-cards"></a>

Here are some test cards with encrypted card numbers for [First Data Testing](/documentation/testing/first-data-testing). Before you implement encryption, you can use them for testing in the Sandbox environment.

You can read more about testing in the [Testing](/documentation/testing) section.

{% tabs %}
{% tab title="Visa" %}
Card number: **4761 5300 0111 1118**

{% code title="Encrypted string" %}

```
K8ELXxBJGpgO02O9Rw3XYe32D4msyv2lBO/SaQyx2vkPjFdy8hBjOxKQ9Q9NMQro9HotSzdev0Legr+iwevfvMnZINZMAy7ufNA4CniT3YcNdOYbzATBD1iTTiLcf+/we9QHsuo70R7Mij9oONFdh5UX948v89ZQMc95RyXtXpU1sUXkf/GG+gm9XFG0y09pb7KCIwa8vxhbMej0I7k7xhR3t6651XWec7H4NVE6jqMOSK7S3/cuqU9eHhqOD24f3X8xnzrGQUTGEvfk63bsH4UgXq/lEo27yMSi0FpsBLyw7fE/1FsFQG58HgMoXmwdjGtHPSH4/xUXJHtihkKHi8Ge9Zch7k9v7ZiAAe48qUPmFs2bOH3XV3jtvPo3fX64vz3Ode37oehe06+MmQR7ho+cR/r/IDAA74zQWRgYfDL79UhaLEMCQ7mcoxGlRgz5gfOy1inD1mL14lPlH8FcTDcnlDBtwakzlSP8NrmtFGvz3gV9T3d9nAP2yBvP4qXF875rGhiXgQ8HQHAit0SyxMuqdNtnScUbTu4iUHqQr4xtsiOQ/MoJIFgygtPs4ndEpNAeImvr7+DgFQvhkZyDWJBQ8qqpv4vlO3pDAJ6/7UzSmSD5D9vjdFj9tAAf72cXLtu1STcB7XKzzrG696kBdYAWhoF/z72n1n4AtZGWMf0=
```

{% endcode %}
{% endtab %}

{% tab title="Mastercard" %}
Card number: **5137 2211 1111 6668**

{% code title="Encrypted string" %}

```
WkPwbAzt1xZxECR4tdWOZDi219AiFmKq8qn6/MwwMPSeqkcRInqFMp3DxmM33G7pPrsvkIZA5zwk/tPLjjKkPDE1czVdVHA8yxYra6ggiGnjlASrxKdDGz6vaujGOnnex3cjXxV4mGC2gEhERTaFyXVlJDpM2jh/fdbXpg11n0BwmFBzgReTAV5BsS87vOqLfHjg9evm4lTIlYoqKR6DcGLn27Wd2ExwQu6V8nc8rkR6hwqEXsz3BFsbDtUhLeeWZdsEtZfKbAMzVAjwhUIbtsm4NOLLyQ5aSVc3P48FuW5GU9OZJD1MeicdsD+DFYmQk77UkEWEcKm9hogzf66sgrLAhY+TXg4iO4X0BJb8AJQRV0m9Am3VaemOIX/zw851AacwWxVNgYwrxbzcik9ODZR5GR8pHwXsPfeED2XISzGyfBdpv/5gqs5wTAlpZc0yW0nDShx9j+nmUJGVrd3RMHJddOe5+8HIWHFqAh3cQ6DBPe4FgBrTTtM44FlG+PuCRcVW6eQrnUr/llnWJdrUT5wKvGodewJCZv5JAdY9JZk9uj/qyITnDXVDC7uxxdHQgdq8yqjLZ/6iUoSu/dFFIflXmc/QFF13kRX74+XzYkMdEhUWQQ73R2KUKuTtO0jPMW5f+52UVJmUjEKYcggB8PcapFXAToKY0WaQhoSwOi0=
```

{% endcode %}
{% endtab %}

{% tab title="Discover" %}
Card number: **6011 2087 0111 7775**

{% code title="Encrypted string" %}

```
FFcT8XK/lbjN6oBxp7qY4DND1QYeejnjcaYxCfVVaRQ4tqgE6SrOSGqvpfkOXWbacOHDd26SF+lNGx2Uj7UxMRglY/6AjsMfWfffG15kyfKNLJIPwiLklpNwKgOH3J9z8CHYXF1G7gQR/q4Z42z851iFB7DNGfPJ7iZk+ZPh4YEer+R+ZH2nlLx0GVcbI6YOXtCgNLC8LJd8brzrmqKyA/0ZrJJaD+PmiK6rZxcHdPqIdx1Bc+x7y54GTd6LpigGVtnS65PKPzjIjfXYpTgyBQhbqIpy6qu5r6G3CwWupYjdXV4xX3GzTsQDX3byoSssRdQEmDeUa78iIlk3QbHHJn81SdorHaUI34uU1c0D5eqWzVSh4aAhrnTjDlx0ecS1Wn0cPpMvDxVZI3pEq3TrnuUQZgvcHJDMsZ3Dn1pviQnah272d3bh8uL8u/Drb7FLREgK7o8ZlV/rcPGgf++8N7CMEyZgIfVWuXc8EVRHA2KWuSTKgFfNyWX7GAF41f1EYEYn7dMd8EZcv6atpXNuLhsIAyKUeVoYO8nhBLHmtNBvKm2Ly5CSW344MiKUjmpR8+FpuBgLyJrVHkAaZmKLKcmaKqVEcVzqq+uiN0RhXWnkiUyODKdaP+LQjsNzmdbieW0ZaXJJPOkmMrgbuOfeDv6B9MUEW3UOoUEFAY48+Kg=
```

{% endcode %}
{% endtab %}

{% tab title="AMEX" %}
Card number: **3710 3008 9111 338**

{% code title="Encrypted string" %}

```
hWp5QKogAb7jkP85oHB7q+yYLw75IXVBzhGdQ0oZUUNk+z1uVLWK3ZyFwoi1Op8f5naINaHZ9T0ke2OW7Ydh7aYo3nTmhXVkM8LdYB3OUcvscj92HB5CHiWo1jBG0Jv4+vicBfOFT404r4MLwIqpdJVrr0URS0sSbSSPo34vk31GS9mihi+8UBzRXip8WKgnS5003grbvYf7tqGGK4YwrxCIgZRGqGIIrjqhrILBwn3zUmCjFuMItiNJ+VhnrThBeIXk9Lb8+FqzzZw63sIW41m4xOuVa4ZMB/4EpuG84BsA2V1WukRWzQRCo2CFYn55T96/GRdUrz3tGWEVs3NfXs4116IcK5fwYNBt/n0gVhmji4TU4JjUl64XS9gjfnPHGm3YsuOIuHL4Kapklp6UpDh/bVt795zMisGvlYEWazjflsO6MkDE+lgwt5XNs0kGVdWql9OHYSxAcmEmgZ4/ERf4dmgp/3TN5cMh4KZWGnEeWapcUtWWRISnHCCnkOpvz3wDsjH/96zb9DsYsXJ+92u76tCo3PNOMcD/cyEwMpqpjqjg/Z0a1YcS/anEXdGGwoXy65VCEALLy8mAct7whyQeValIPXeNq7sEbU2Y+LO8pevIfepDjChC5lVm4r/vUJOWq0ZvOCfUgHpRKqLS+zq0AYC0xP1Y8Xe1L+yT1zY=
```

{% endcode %}
{% endtab %}
{% endtabs %}

***

## Lockouts

When you authenticate, you will receive `FunctionOK` and `AuthSuccess` flags in the response. You should handle the response as follows:

1. Check the FunctionOK flag.
   1. If false, read the `ErrMsg` and `ErrCode`, and abort.
   2. If true, read the `AuthSuccess` flag.
      1. If `AuthSuccess` is false, read `RspMsg` and abort.
      2. If `AuthSuccess` is true, save the `SessKey` value.

Once again, it's important to **abort unsuccessful authentication attempts** and notify the user that new credentials need to be applied to the product.&#x20;

The system will lock your IP after 6 unsuccessful attempts in a row. When a lockout occurs, our support department will need to manually audit it to determine if it's safe to remove the lock.&#x20;

***

## Token Renewal

The Client Admin Portal will allow you to create and manage all of your tokens.  There is no limit to the number of tokens you can create. We recommend creating a separate token for each individual processing location (IP address).

Each token has a lifespan of 2 years since it was generated and will need to be replaced afterwards. This can only be done by physically logging into The Client Admin Portal. To make the process faster, The Client Admin Portal provides a way to POST new tokens to your web server to help automate a part of the renewal process.

To learn how to use the Client Admin Portal to renew tokens, see the [Client Admin Portal Old](/documentation/getting-started/client-admin-portal) guide.

<figure><img src="/files/hp0Xh32MTynmnmy8vb4Q" alt=""><figcaption></figcaption></figure>


# API Best Practices

A list of best practices for working with the APIs

## Consuming the API Response

When consuming the API response for any endpoint, you can follow a similar format. It'll allow you to correctly handle all types of responses and display the correct information in the user interface.

{% stepper %}
{% step %}

#### Catch all exceptions when calling the API

These can be a result of problems communicating with our service or problems executing the client-side code.
{% endstep %}

{% step %}

#### Check for a null response

Depending on your implementation, you might receive a null response indicating an unexpected error instead of an exception.
{% endstep %}

{% step %}

#### Check the value of `FunctionOk`

This boolean flag is included in all API responses and indicates whether the operation executed without exceptions on our servers.&#x20;

If the value of `FunctionOk` is false, it indicates an error which was handled on the Number servers. In case of problems, you can display the `ErrMsg` and `ErrCode` to the user.
{% endstep %}

{% step %}

#### Check other success flags such as `AuthSuccess` or `TxApproved`

These boolean flags will be included depending on the operation, and they indicate whether the operation was approved. You should use the friendly response message provided in the `RspMsg` field to display more information to the user.

In case of transactions, `TxApproved` with the value of false indicates that the card issuer does not want to approve the transaction. You can also supplement your response with the decline code found in `TxnCode`.
{% endstep %}
{% endstepper %}

***

## Logging

It's important to correctly handle exceptions and log all the responses. **Before you interface with our APIs, we recommend creating a simple logging utility.** This way, there'll be a trail of breadcrumbs in case any issues arise in the future. Without logs, finding out what went wrong can be time consuming.

### Recommended way to log the responses

{% stepper %}
{% step %}

#### Create a utility class for logging

It should contain a method that will take the API call name as well as `FunctionOk`, `IsSuccess`, `RespMsg`, `ErrCode`, and `ErrMsg` values. This will compile all of the information necessary to track any issue.

Store the timestamp of the response and all of those values in a database record or as a row in a log file. When logging to a file, it's recommended to roll onto a new file on a monthly basis.
{% endstep %}

{% step %}

#### Use the utility class to log all API results

Log all of the responses, including successful ones, using your utility class.
{% endstep %}
{% endstepper %}

### Logging class example

See the example below to give you more insight into how you might create your logging utility.

{% tabs %}
{% tab title="C#" %}
{% code lineNumbers="true" fullWidth="true" %}

```csharp
namespace APITest
{
  public static class LoggingUtil
  {
    private const string PATH = "C:\\Logs\\Payments\\";

    private static readonly object _locker = new();

    /// <summary>
    /// Log the API response and return logging success.
    /// </summary>
    /// <returns>True if logged successfully, otherwise false.</returns>
    public static bool LogResponse(string apiCallName, bool FunctionOK,
      bool IsSuccess, string RespMsg, int ErrorCode, string ErrMsg)
    {
      try
      {
        if (string.IsNullOrEmpty(RespMsg))
          RespMsg = "N/A";

        // Ensure the directory exists
        if (!Directory.Exists(PATH))
        {
          Directory.CreateDirectory(PATH);
        }

        string myMonthlyFileName = DateTime.Now.Year.ToString("D4")
          + "_" + DateTime.Now.Month.ToString("D2") + ".log";
        string timeStamp = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.ff");
        string message = timeStamp + "," + apiCallName + "," + FunctionOK.ToString() + ","
          + IsSuccess.ToString() + "," + RespMsg + "," + ErrorCode.ToString() + "," + ErrMsg;
        bool fileExists = File.Exists(PATH + myMonthlyFileName);

        lock (_locker)
        {
          // Use StreamWriter with 'using' statement to ensure proper resource disposal
          using (StreamWriter swriter = File.AppendText(PATH + myMonthlyFileName))
          {
            // Place a header in each new monthly log file
            if (!fileExists)
              swriter.WriteLine("Timestamp,apiCallName,FunctionOK,IsSuccess,RespMsg,ErrorCode,ErrMsg");

            // Write the response as a new line
            swriter.WriteLine(message);
          }
        }
        return true;
      }
      catch (Exception ex)
      {
        // Optionally log or handle the exception here
        return false;
      }
    }
  }
}

```

{% endcode %}
{% endtab %}
{% endtabs %}

***

## Preventing duplicate charges

<figure><img src="/files/18v8SMqhDGA5f1AjnyRc" alt=""><figcaption></figcaption></figure>

Common issues we encounter include complaints about duplicate charges. This can happen when integrators process card-on-file transactions without proper safeguards that prevent submitting the same form multiple times.

If there is button on a webpage that initiates a charge, and there is no mechanism preventing it from being clicked multiple times, **the cardholder would be charged each time**. To prevent this, it's crucial to disable the button immediately after it's pressed, ensuring that double taps do not occur.&#x20;

{% hint style="warning" %}
When processing card-on-file transactions, remember to lock the submit button after form submission to prevent multiple API calls and duplicate charges from occuring.

You may also choose to include simple logic that checks `ConsentID` and `TransactionAmount` that would prevent the same combination from being processed multiple times within a short timeframe.
{% endhint %}

**Timeouts**&#x20;

The mechanics of processing a credit card transaction involves many servers operating at separate geographical locations.  Normally this is all accomplished within 2 seconds. Occasional delays will be encountered somewhere within the processing train.  We submit each transaction to the Acquirer and then the card Issuer in order to get a decision. In the case where you receive a timeout from our gateway you should assume that the transaction was still successful. The best practice would be to query our system immediately after you receive a timeout or communication error to determine if the transaction was successful.  If you are processing a stored card, then you can query by ConsentID. If you are passing cardholder data, you can Query by Reference ID or other elements.  Employing this important logic will eliminate duplicate transactions and ensure your ledger agrees with ours.&#x20;


# API Input Validation

Basic details about input validation in the APIs

The following string values are validated within the APIs and will only allow a finite set of characters. If you send characters which are not allowed, you can receive an `ErrCode` of 7123.

<table><thead><tr><th width="236">Field / fields</th><th>Allowed characters</th></tr></thead><tbody><tr><td><code>Firstname</code>, <code>Lastname</code></td><td>Alphanumeric, single quote, minus sign, period, space, ampersand, comma, question mark, forward slash.</td></tr><tr><td><code>Company</code>, <code>Title</code></td><td>Alphanumeric, minus sign, period, pound sign, underscore, comma, ampersand, forward slash.</td></tr><tr><td><code>Address</code></td><td>Alphanumeric, minus sign, period, pound sign, underscore, comma, forward slash. Single quotes are stripped out.</td></tr><tr><td><code>City</code></td><td>Alpha, space, period.</td></tr><tr><td><code>State</code>, <code>Country</code></td><td>Alpha, space.</td></tr><tr><td><code>Zip</code></td><td>Alphanumeric, space, dash.</td></tr><tr><td><code>ClientRefID</code>, <code>RPGUID</code></td><td>Alphanumeric, minus sign, period, pound sign, comma, underscore, space, equal sign, ampersand. Single quotes are stripped out.</td></tr><tr><td><code>ServiceDescrip</code></td><td>Alphanumeric, space, underscore, period, pound sign, minus sign.</td></tr></tbody></table>


# Testing Considerations

## **Responses**

When Processing using the API or the VeriFone Middleware you should be ready to consume the following types of responses:

1. Approvals
2. Declines
3. Aspen Errors (non-zero error code)
4. Exceptions within your processing layer (Timeouts or other Comm issues )

For PayForm and Virtual Terminal, all of this is handled for you, however when using the API or the VeriFone your software must properly consume and handle the above conditions.

***Lets take a look at the API first***

If you attempt an API call such as VOID a credit card transaction you should first set up to handle the exception.

```
try
{
    response = await httpClient.PostAsync(apiUrl, content);
}
catch (Exception ee)
{
    return "Exception : " + ee.Message;
}
```

You can easily test your ability to consume an Aspen Error by simply trying to Void a transaction that doesn’t exist. Try sending a large number beyond the number of transactions already committed.

```
{
    "TxID": 53000
}
```

The response will look like the following. Notice the FunctionOK flag is false which will be your QUE to look at the error code and log this condition:

```
{"Transaction_VoidResult":{
    "ErrCode":6724,
    "ErrMsg":"ERROR:6724:HIGH:Could NOT retrieve transaction details for TXID 53000",
    "FunctionOk":false,
    "RespMsg":"",
    "TxApproved":false,
    "TxID":0
    }
}
```

Even if no error is encountered you still might not have the successful VOID as the card issuer may **decline** the reversal. Always make sure you check the TxApproved Flag .

If the card issuer declines your reversal attempt you will notice that FunctionOK = True ( No Aspen Errors were encountered ) but TxApproved = False (issuer declined the reversal)

In this case you will Monitor the RespMsg for any further information regarding the decline

Here is the proper order when consuming the API response:

1. Catch any exception in communicating to EasyPay ( perhaps a Timeout )
2. Check status of FunctionOK flag ( If false then check and log error codes and error message)
3. Check any TxApproved or other success flags for final discovery of approved operation

### Verifone testing

To simulate a issuer decline using your test account you can send the following Amount ( $12345.67 ) . You will notice that the TxEventType = TxDecline and the RespMsg will describe the decline and the TxnCode will have a Decline Code.

To simulate an Aspen Error using your test account you can send the following Amount ( $12345.68 )

You will notice the TxEventType = AspenError , you will then monitor the ErrCode and ErrMsg

To Simulate our site being unavailable you can always create a Temporary Host Entry for EasyPay5.com to a Fake IP address.

Example : 99.99.99.99 easypay5.com

After you attempt a transaction, you will see a TxEventType = Exception with a particular error code and error message which you can log.

Remember to remove the host entry when finished.


# Client Admin Portal Old

Getting started with the Client Admin Portal

The Client Admin Portal gives the means to create, modify, and remove Virtual Terminal users, create new API tokens, and inspect active or expiring tokens.

***

## Accessing the portal

To get access to the portal and create new accounts, contact the [Number support team](/help/customer-support).&#x20;

You will be asked to provide the full name, e-mail address, and cell phone number for every individual you wish to have access to the portal. Each one of them will receive a text message containing their username and an e-mail containing their password with the URL of the portal.

Our Admin Portal utilizes **two-factor authentication**. Users accessing the portal will be asked to enter their username, password, and a security code that will be sent via a text message to their cell phone.

## Integrator token renewal <a href="#integrator-token-renewal" id="integrator-token-renewal"></a>

There are two methods to generate token renewals.&#x20;

Once you log in, you'll see a menu on the left with a *Manage Tokens* heading.

<figure><img src="/files/3au5sX0x2OZSZSFZhBY4" alt=""><figcaption></figcaption></figure>

The *Active Tokens* option allows you to view all of tokens that have been assigned to your accounts, their expiration date, and their current status. This can be useful for administrators to see what tokens are nearing their expiration. Columns can be sorted by clicking on the column header.

<figure><img src="/files/4TxM18baKH3ynr2JExBt" alt=""><figcaption></figcaption></figure>

The *Token Renewal* option allows you to select the accounts to issue new tokens to. It also provides you with a summary of the total number of active tokens that are assigned to each account.

<figure><img src="/files/xxf53TsyApjbd9BiDiWs" alt=""><figcaption></figcaption></figure>

After selecting the accounts you wish to renew, you will see a summary with new token information.

<figure><img src="/files/7hqe5N0AjQxFwSuMO3dj" alt=""><figcaption></figcaption></figure>

Next, you will be given the option to choose how the token information should be posted. You can copy the text from the screen manually or POST the token to a URL of your choice.&#x20;

{% hint style="info" %}
When renewing multiple tokens, their info will be separated by pipe "|" characters.
{% endhint %}

<figure><img src="/files/mw7QiHgdpJnNdXw6QRBt" alt=""><figcaption></figcaption></figure>

You can select `POST classic` to **post your token to your URL with the classic method** or `POST JSON` button to **make an API call that will send a JSON array of tokens to your URL**.

<figure><img src="/files/8OosCeSE82o9KZBqeJmr" alt=""><figcaption></figcaption></figure>

### POST JSON

When you select `POST JSON`, we will create a JSON array named *TOKENS* and send it directly to the URL you specify. You can obtain this data by accessing the InputStream at your server endpoint.

{% tabs %}
{% tab title="C#" %}

```csharp
string json;
using (var reader = new StreamReader(Request.InputStream))
{
    json = reader.ReadToEnd();
}
```

{% endtab %}
{% endtabs %}

{% code title="JSON array example" overflow="wrap" %}

```json
"Tokens": [{"TokenID":"8961", "AccountCode":"EP8179234", "Token":"AB87E1D81559466E9165FCDA2B5B12C3", "AccountName":"CY FD TEST", "ExpirationDate":"11/22/2026 1:59:54 PM"}, {"TokenID":"8962", "AccountCode":"EP1519128", "Token":"EDB6D3FC1DE44A5C883BC718350C40BC", "AccountName":"CY TSYS TEST", "ExpirationDate":"11/22/2026 1:59:54 PM"}]
```

{% endcode %}

### POST Classic

Once you have made your selection, click on the *Post Token URL* button. **You will be given a window in which you can enter a URL.** If you have already provided us with one, that URL will be entered into the window by default. You may still manually enter a different URL at this point.

<figure><img src="/files/I0L8UoOzuDhHFh8J5VAW" alt=""><figcaption></figcaption></figure>

Once you have the correct posting URL entered, click on the *Post* button. You'll see a parameter appended to your posting URL. **This is what you will use to download your token file.**

<pre class="language-url" data-title="Posting param example" data-overflow="wrap"><code class="lang-url"><strong>?TokenFile=https://easypay5.com/ClientAdminPortalR101/Content/ManageTokens/Tempfile/f7048.txt
</strong></code></pre>

The file will contain the token information in an encrypted format consisting of an initialization vector and the data itself, separated by an equals sign "=".&#x20;

{% hint style="info" %}
When viewing the token from `POST Classic`, the first 12 characters are an initialization vector, including the equal sign "=" separator, the remaining are the encrypted message.
{% endhint %}

{% code title="Token data example" overflow="wrap" %}

```
xts/VQqO3XY=mJjvA64NIeJZRO8T2AwjcBwmiHSyWUPyxOwppWbObhz4Q99Oa/a/xz7dnVccGRtKSU4uee4vKYmRtpJWqOnpvxVyGEPPtliKJrnfqIsVVlrLO3/9PloUBzeorX3d9HvCsgX9QcO7fPGbt/rpbfTLeUtk5OJhguEMbre7g1MX1FlM4xGI3/Hq362Lpg2LIJ1KIXXArBSDhLAq5yAXjRFwjQTzV81UITTEZN+HLNklVIcqpVPa0IFhxg==
```

{% endcode %}

As an integrator, **you will have already been provided with a unique encryption key**, also referred to as an `EIndex`. You can use it to decrypt the token file.&#x20;

Once decrypted, each token would now have the account name, account ID, token, token ID, and expiration date, with multiple tokens being separated by a pipe "|".

{% code title="Decrypted token example" overflow="wrap" %}

```
EASY PAY DYNA PRO TEST,EP4397937,533825D35E2B4EXXXXXXXXXX54A0AF73,4804,2/8/2017 2:50:06 PM|EASYPAY HEALTH CARE TEST,EP9948514,4C9AA0E6194847XXXXXXXXXXC3427D64,4805,2/8/2017 2:50:06 PM
```

{% endcode %}

{% hint style="info" %}
The token ID is a reference number by which the Number support can look up your token should you require any assistance.
{% endhint %}


# Client Admin Portal

Getting started with the Client Admin Portal

The Client Admin Portal allows you to do Admin Tasks such as:

* Create/Modify Virtual Terminal Users&#x20;
* Create/Inspect API Tokens&#x20;
* View Transaction Details
* View Card On File Details

#### Client Admin Portal Modes of Operation

**Merchant/Single Account Admin**

This type of access is provided if you are responsible for a single account. You have unlimited access to create Users and API Tokens. You have full access to all reports. &#x20;

***

**Integrator / Multi Account Admin**

This type of access is granted to Integrators who must process transactions for multiple accounts. You can Create API Tokens , but NOT Virtual Terminal Users. You have Read-Only access to reports.

## Single Sign-On (SSO)

Single Sign-On (SSO) is integrated between the Client Admin Portal and the Virtual Terminal (VT). Client admin credentials allow users to log in to the Virtual Terminal without needing a separate set of VT credentials.

When you receive your client admin credentials, it is recommended that you log in to the Client Admin Portal and change your temporary password to a permanent one. After the one-time password has been changed, the same credentials can be used to access the Virtual Terminal.&#x20;

{% hint style="info" %}
Note: SSO is only available for single-account logins and is not supported for multi-user integrator accounts.&#x20;
{% endhint %}

## Integrator token renewal

{% hint style="info" %}
API tokens are automatically renewed if both of the following conditions are met:

1. The credentials have been successfully authenticated within the last month.
2. The token is set to expire within the next month and has not yet expired.
   {% endhint %}

Once you log in, you'll see a menu on the left with a *Token Renewal* heading.

The Token Renewal function allows you to select the accounts for which to issue new tokens. It also provides a summary including the total number of active tokens assigned to each account. Select the account(s) you wish to renew, then click Next.

<figure><img src="/files/6hFYwIBpilDcZObWkzMS" alt=""><figcaption></figcaption></figure>

After selecting the accounts you wish to renew, you will see a summary with new token information. At this point you can either copy the new token or proceed to the next step for automated processing at your url.

<figure><img src="/files/JvqtatzGSbFV7VBN9qyL" alt=""><figcaption></figcaption></figure>

### Posting the token JSON data to your webhook URL

<figure><img src="/files/y931DmLa6M3eX4sCsQZx" alt=""><figcaption></figcaption></figure>

We will create a JSON array named *TOKENS* and send it directly to the URL you specify. You can obtain this data by accessing the InputStream at your server endpoint.

When you select `POST JSON`, we will create a JSON array named *TOKENS* and send it directly to the URL you specify. You can obtain this data by accessing the InputStream at your server endpoint.

{% tabs %}
{% tab title="C#" %}

```csharp
string json;
using (var reader = new StreamReader(Request.InputStream))
{
    json = reader.ReadToEnd();
}
```

{% endtab %}
{% endtabs %}

{% code title="JSON array example" overflow="wrap" %}

```json
"Tokens": [{"TokenID":"8961", "AccountCode":"EP8179234", "Token":"AB87E1D81559466E9165FCDA2B5B12C3", "AccountName":"CY FD TEST", "ExpirationDate":"11/22/2026 1:59:54 PM"}, {"TokenID":"8962", "AccountCode":"EP1519128", "Token":"EDB6D3FC1DE44A5C883BC718350C40BC", "AccountName":"CY TSYS TEST", "ExpirationDate":"11/22/2026 1:59:54 PM"}]
```

{% endcode %}

<figure><img src="/files/j99OTLE3c2W8dvKeKiz8" alt=""><figcaption></figcaption></figure>

## Manage Fees

To manage a Merchant's Fees, click on the *Manage Fees* link. Acknowledge the Disclaimer to view the list of Merchants.

<figure><img src="/files/V8s3dqkfSSur93QMKuzZ" alt=""><figcaption></figcaption></figure>

Click the go link next to a respective merchant to get to the edit screen, where you can edit fee type, rate, cards allowed and notations.

<figure><img src="/files/Sf3Iw3cio2tdBmLBIJsj" alt=""><figcaption></figcaption></figure>

## Reports

(Transactions, ACH Transactions, Cards on File, ACH on File)

Once you log in, you'll see a menu on the left with a *Reports* heading. Expand this to see all the subheadings. All pages in this section function the same way.

<figure><img src="/files/mfJv7tGCF7PGuXdJtxxy" alt=""><figcaption></figcaption></figure>

These pages allow you to filter all transactions (or COF) by date, txstatus,txtype and search by various field types. After adjusting your criteria, press the *Refresh Data* button to see the applicable reports.

<figure><img src="/files/nFDUM9fXwhc5lnYsevHE" alt=""><figcaption></figcaption></figure>

After finding the transaction or COF desired, you can click on the *Details* link to see the in depth information.

<figure><img src="/files/ZyKio5j2oYbpoIDUdprM" alt=""><figcaption></figcaption></figure>


# Testing

Test your integration before going live.

<figure><img src="/files/BNDDcnHuuNmKfrIkGXaU" alt=""><figcaption></figcaption></figure>

Before you go live, you'll need to test your integration, and the Number team will need to validate it.&#x20;

To help you with that, we've compiled all the information regarding transaction and consent verification, sandbox cards and test data, penny codes, and return codes into this section.

Here are the articles in this section:

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Testing Overview ></strong></td><td><a href="/pages/wUVboI4eOhJWCOyp3wqM">/pages/wUVboI4eOhJWCOyp3wqM</a></td></tr><tr><td><strong>Global Payments Testing ></strong></td><td><a href="/pages/8kffWViK5hCECrzP0h6q">/pages/8kffWViK5hCECrzP0h6q</a></td></tr><tr><td><strong>First Data Testing ></strong></td><td><a href="/pages/6gsYOpCclH4j0cm3H82y">/pages/6gsYOpCclH4j0cm3H82y</a></td></tr><tr><td><strong>ACH Testing ></strong></td><td><a href="/pages/jPcKMr1UodE6cMQDYz75">/pages/jPcKMr1UodE6cMQDYz75</a></td></tr></tbody></table>


# Testing Overview

Transaction and consent verification using the Virtual Terminal.

## Testing integration <a href="#testing-integration" id="testing-integration"></a>

After API, PayForm, or widget integration, it is important to login to our Virtual Terminal and make sure the transactions and consents appear correct. The Number Support Team can provide you with Virtual Terminal credentials.

{% hint style="info" %}
An example user name for the Virtual Terminal can look like this: **VT4914533**
{% endhint %}

For more information about the Virtual Terminal, see the [Virtual Terminal](/documentation/getting-started/integration-options/virtual-terminal) guide. You can access Virtual Terminal using the link below.

<figure><img src="/files/iVFmK2Cu2IeNgKC8IAxq" alt=""><figcaption></figcaption></figure>

***

## Verifying transactions <a href="#verifying-transactions" id="verifying-transactions"></a>

Once logged in, expand the *Transactions* tab in the navigation on the left, then click on *Search*.

<figure><img src="/files/izpl4EM1RfABKIZtFfkW" alt=""><figcaption></figcaption></figure>

This will show the list of transactions created. Select the transaction to be verified, and click on *Full Detail* button under *Transaction Operations*. A pop up will open to show all the information about the transaction, account holder, and the end customer.

Make sure the amount, last four digits of the credit card, card type, and expiration date are correct.

<figure><img src="/files/7ZJ2aJfIvf6EqsyhVVZN" alt=""><figcaption></figcaption></figure>

### Testing declines <a href="#testing-declines" id="testing-declines"></a>

There are scenarios where the transaction can get declined due to various reasons like insufficient funds, card not allowed, lost/stolen card, etc. In such cases, the transaction would appear as *FAILED*.

{% hint style="info" %}
You can find penny codes for testing declines in the [Global Payments Testing](/documentation/testing/global-payments-testing) section.
{% endhint %}

You can click *Full Detail* to try to find out the reason for decline by checking `TxStatus`, `Flags,` and other values.

### Testing partial auth <a href="#doing-a-partial-authorization-with-aspen" id="doing-a-partial-authorization-with-aspen"></a>

#### Partial auth testing data <a href="#partial-auth-testing-data" id="partial-auth-testing-data"></a>

To test a partial authorization, you can use one of these cards:

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><strong>4788 2500 0002 8291</strong></td><td><a href="/files/4WAMdYKoy2zK810bs7gT">/files/4WAMdYKoy2zK810bs7gT</a></td></tr><tr><td><strong>4055 0111 1111 1111</strong></td><td><a href="/files/4WAMdYKoy2zK810bs7gT">/files/4WAMdYKoy2zK810bs7gT</a></td></tr><tr><td><strong>6011 0009 9550 0000</strong></td><td><a href="/files/KqLbqu8tEkA7X8ZKKMmq">/files/KqLbqu8tEkA7X8ZKKMmq</a></td></tr><tr><td><strong>6011 2121 0000 0087</strong></td><td><a href="/files/KqLbqu8tEkA7X8ZKKMmq">/files/KqLbqu8tEkA7X8ZKKMmq</a></td></tr><tr><td><strong>5454 5454 5454 5454</strong></td><td><a href="/files/NfuZ26NdM8pUWAI3vg6Q">/files/NfuZ26NdM8pUWAI3vg6Q</a></td></tr><tr><td><strong>5405 2222 2222 2226</strong></td><td><a href="/files/NfuZ26NdM8pUWAI3vg6Q">/files/NfuZ26NdM8pUWAI3vg6Q</a></td></tr><tr><td><strong>5473 0000 0000 0007</strong></td><td><a href="/files/NfuZ26NdM8pUWAI3vg6Q">/files/NfuZ26NdM8pUWAI3vg6Q</a></td></tr><tr><td><strong>3714 4963 5398 431</strong></td><td><a href="/files/WNacEG1cwaX2b9tiQ2mD">/files/WNacEG1cwaX2b9tiQ2mD</a></td></tr></tbody></table>

{% hint style="info" %}
Using the test cards, if you enter the amount of $2.78, you should get partial approval for $2.57, and if you enter the amount of $3.26, you should get a partial approval for $1.26.
{% endhint %}

### Testing receipts <a href="#testing-receipts" id="testing-receipts"></a>

The receipt can also be printed in the Virtual Terminal by expanding the *Receipts* dropdown and clicking the *Merchant* or *Customer* button.

<figure><img src="/files/aXnRVrqJSNqtlSPf0MmP" alt=""><figcaption></figcaption></figure>

***

## Verifying consents <a href="#verifying-consents" id="verifying-consents"></a>

Click on the *Reports* menu and choose *Consents.*

Select the consent that needs to be verified from the grid. Click the *Full Detail* button and make sure the consent, account holder, and end customer details look correct.

<figure><img src="/files/zrcMzBG8ZN1CH9LoRzYW" alt=""><figcaption></figcaption></figure>

To view the consent agreement, click on the *Merchant Consent* or *Customer Consent*.

<figure><img src="/files/wlc0ZtjHtbjPbRoi4nhZ" alt=""><figcaption></figcaption></figure>


# Global Payments Testing

Cards for testing, response code reference, and penny codes for Global Payments.

## Test cards

You can use the cards below to receive a **full CVV match** during testing.

<table data-full-width="false"><thead><tr><th width="134">Card brand</th><th width="204">Card number</th><th width="108">EXP Date</th><th width="73">CVV</th><th width="513">Track Data</th></tr></thead><tbody><tr><td><img src="/files/4WAMdYKoy2zK810bs7gT" alt="" data-size="original"></td><td>4012 0000 9876 5439</td><td>12/28</td><td>999</td><td>%B4012000098765439^TSYS PAYMENT^25121011796251900000?;4012000098765439=25121011796251900000?</td></tr><tr><td><img src="/files/4WAMdYKoy2zK810bs7gT" alt="" data-size="original"></td><td>4012 8818 8881 8888</td><td>12/28</td><td>999</td><td>%B4012881888818888^TSYS PAYMENT^25121011796251900000?;4012881888818888=25121011796251900000?</td></tr><tr><td><img src="/files/NfuZ26NdM8pUWAI3vg6Q" alt="" data-size="original"></td><td>5146 3150 0000 0055</td><td>12/28</td><td>998</td><td>%B5146315000000055^TSYS PAYMENT^251210100000?;5146315000000055=251210100000?</td></tr><tr><td><img src="/files/NfuZ26NdM8pUWAI3vg6Q" alt="" data-size="original"></td><td>5146 3122 0000 0035</td><td>12/28</td><td>998</td><td>%B5146312200000035^TSYS PAYMENT^251210100000?;5146312200000035=251210100000?</td></tr><tr><td><img src="/files/NfuZ26NdM8pUWAI3vg6Q" alt="" data-size="original"></td><td>5146 3126 2000 0045</td><td>12/28</td><td>998</td><td>%B5146312620000045^TSYS PAYMENT^251210100000?;5146312620000045=251210100000?</td></tr><tr><td><img src="/files/WNacEG1cwaX2b9tiQ2mD" alt="" data-size="original"></td><td>3714 4963 5392 376</td><td>12/28</td><td>9997</td><td>%B371449635392376^TSYS PAYMENT^251210100000?;371449635392376=251210100000?</td></tr><tr><td><img src="/files/KqLbqu8tEkA7X8ZKKMmq" alt="" data-size="original"></td><td>6011 0009 9302 6909</td><td>12/28</td><td>996</td><td>%B6011000993026909^TSYS PAYMENT^251210100000?;6011000993026909=251210100000?</td></tr></tbody></table>

***

## Penny codes

When using previously specified test cards, you can test for all various types of responses using the following penny codes. Each penny code specifies the request value for a specific response.

{% hint style="info" %}
You may use test cards in conjunction with penny codes to confirm that your application handles all different types of response codes correctly.&#x20;
{% endhint %}

{% tabs %}
{% tab title="Visa" %}

<table><thead><tr><th width="162">Request value</th><th width="143">Response code</th><th width="397">Response text</th></tr></thead><tbody><tr><td>$0.00</td><td>85</td><td>Card Ok</td></tr><tr><td>$0.01</td><td>01</td><td>Call Issuer</td></tr><tr><td>$0.02</td><td>02</td><td>Call Issuer, Special Cond.</td></tr><tr><td>$0.03</td><td>28</td><td>File Temp. Unavailable</td></tr><tr><td>$0.04</td><td>91</td><td>Issuer Unavailable or Inoperative, No STIP</td></tr><tr><td>$0.05</td><td>04</td><td>Pick Up Card</td></tr><tr><td>$0.06</td><td>07</td><td>Pick Up Card, Special Cond.</td></tr><tr><td>$0.07</td><td>41</td><td>Pick Up Card, Lost</td></tr><tr><td>$0.08</td><td>43</td><td>Pick Up Card, Stolen</td></tr><tr><td>$0.09</td><td>06</td><td>General Error</td></tr><tr><td>$0.10</td><td>79</td><td>Already Reversed</td></tr><tr><td>$0.11</td><td>13</td><td>Invalid amount</td></tr><tr><td>$0.12</td><td>83</td><td>Can't Verify PIN</td></tr><tr><td>$0.13</td><td>86</td><td>Can't Verify PIN</td></tr><tr><td>$0.14</td><td>14</td><td>Invalid Account Number</td></tr><tr><td>$0.15</td><td>82</td><td>Incorrect CVV</td></tr><tr><td>$0.16</td><td>N3</td><td>Cashback Not Available</td></tr><tr><td>$0.17</td><td>06</td><td>General Error</td></tr><tr><td>$0.18</td><td>EC</td><td>CID Format Error</td></tr><tr><td>$0.19</td><td>80</td><td>No Financial Impact</td></tr><tr><td>$0.20</td><td>05</td><td>Decline</td></tr><tr><td>$0.21</td><td>51</td><td>Decline</td></tr><tr><td>$0.22</td><td>N4</td><td>Decline</td></tr><tr><td>$0.23</td><td>61</td><td>EXC APPR AMT LIM</td></tr><tr><td>$0.24</td><td>62</td><td>Decline</td></tr><tr><td>$0.25</td><td>65</td><td>EXC W/D FREQ LIM</td></tr><tr><td>$0.26</td><td>93</td><td>Decline</td></tr><tr><td>$0.27</td><td>81</td><td>Encryption Error</td></tr><tr><td>$0.28</td><td>06</td><td>General Error</td></tr><tr><td>$0.29</td><td>54</td><td>Expired Card</td></tr><tr><td>$0.30</td><td>92</td><td>Invalid Routing</td></tr><tr><td>$0.31</td><td>12</td><td>Invalid Trans</td></tr><tr><td>$0.32</td><td>78</td><td>No Account</td></tr><tr><td>$0.33</td><td>21</td><td>No action taken</td></tr><tr><td>$0.34</td><td>76</td><td>Unsolic Reversal</td></tr><tr><td>$0.35</td><td>77</td><td>No action taken</td></tr><tr><td>$0.36</td><td>52</td><td>No Check Account</td></tr><tr><td>$0.37</td><td>39</td><td>No Credit Acct</td></tr><tr><td>$0.38</td><td>53</td><td>No Save Acct</td></tr><tr><td>$0.39</td><td>15</td><td>No Such Issuer</td></tr><tr><td>$0.40</td><td>75</td><td>PIN Exceeded</td></tr><tr><td>$0.41</td><td>19</td><td>RE-ENTER</td></tr><tr><td>$0.42</td><td>63</td><td>SEC Violation</td></tr><tr><td>$0.43</td><td>57</td><td>Txn not permitted</td></tr><tr><td>$0.44</td><td>58</td><td>Serv Not Allowed</td></tr><tr><td>$0.45</td><td>96</td><td>System Error</td></tr><tr><td>$0.46</td><td>03</td><td>Term ID Error</td></tr><tr><td>$0.47</td><td>55</td><td>Wrong PIN</td></tr><tr><td>$0.48</td><td>N7</td><td>CVV Mismatch</td></tr><tr><td>$0.49</td><td>85</td><td>Card OK</td></tr><tr><td>$0.50*</td><td>00</td><td>APPROVAL</td></tr><tr><td>$0.54</td><td>94</td><td>Duplicate Transaction</td></tr><tr><td>$0.96</td><td>R0</td><td>Stop Recurring</td></tr><tr><td>$0.97</td><td>R1</td><td>Revoke Auth Order</td></tr><tr><td>$1.12</td><td>05</td><td>Decline</td></tr><tr><td>$1.13</td><td>05</td><td>Decline</td></tr><tr><td>$1.30</td><td>00</td><td>Approval</td></tr><tr><td>$1.31</td><td>00</td><td>Approval</td></tr><tr><td>$1.34</td><td>30</td><td>Msg Format Error</td></tr><tr><td>$10.00</td><td>00</td><td>Approval</td></tr><tr><td>$32.48</td><td>00</td><td>Approval</td></tr><tr><td>$32.88</td><td>25</td><td>No Card Number</td></tr><tr><td>$1.34</td><td>30</td><td>Msg Format Error</td></tr><tr><td>$32.85</td><td>11</td><td>Approval</td></tr><tr><td>$64.01</td><td>89</td><td>Ineligible GIV</td></tr><tr><td>$64.02</td><td>H6</td><td>Fail Get BDK</td></tr><tr><td>$64.03</td><td>H7</td><td>Fail Get KPEI</td></tr><tr><td>$64.04</td><td>H8</td><td>Encryption Error</td></tr><tr><td>$64.05</td><td>N9</td><td>System Error</td></tr><tr><td>$64.06</td><td>N6</td><td>N6 Error</td></tr><tr><td>$64.10</td><td>46</td><td>Closed Account</td></tr><tr><td>$64.11</td><td>59</td><td>Suspected Fraud</td></tr><tr><td>$64.12</td><td>6P</td><td>Verification Data Failed</td></tr></tbody></table>
{% endtab %}

{% tab title="Mastercard" %}

<table><thead><tr><th width="160">Request value</th><th width="144">Response code</th><th width="397">Response text</th></tr></thead><tbody><tr><td>$0.01</td><td>01</td><td>Call Issuer</td></tr><tr><td>$0.05</td><td>04</td><td>Capture Card</td></tr><tr><td>$0.07</td><td>41</td><td>Lost Card</td></tr><tr><td>$0.08</td><td>43</td><td>Stolen Card</td></tr><tr><td>$0.14</td><td>14</td><td>Invalid Account</td></tr><tr><td>$0.29</td><td>54</td><td>Expired Card</td></tr><tr><td>$0.30</td><td>92</td><td>Invalid Routing</td></tr><tr><td>$0.31</td><td>12</td><td>Invalid Transaction</td></tr><tr><td>$0.39</td><td>15</td><td>No Such Issuer</td></tr><tr><td>$32.85</td><td>08</td><td>Honor With ID</td></tr></tbody></table>
{% endtab %}

{% tab title="American Express" %}

<table><thead><tr><th width="153">Request value</th><th width="145">Response code</th><th width="397">Response text</th></tr></thead><tbody><tr><td>$0.05</td><td>04</td><td>Pick Up Card</td></tr><tr><td>$0.11</td><td>13</td><td>Invalid amount</td></tr><tr><td>$0.14</td><td>14</td><td>Invalid Account Number</td></tr><tr><td>$0.18</td><td>EC</td><td>CID Format Error</td></tr><tr><td>$0.19</td><td>80</td><td>No Financial Impact</td></tr><tr><td>$0.20</td><td>05</td><td>Decline</td></tr><tr><td>$0.29</td><td>54</td><td>Expired Card</td></tr><tr><td>$0.44</td><td>58</td><td>Serv Not Allowed</td></tr><tr><td>$1.00</td><td>00</td><td>Approved and completed</td></tr><tr><td>$1.01</td><td>00</td><td>Approved and completed</td></tr><tr><td>$1.02</td><td>11</td><td>VIP approval</td></tr><tr><td>$1.03</td><td>08</td><td>Honor MasterCard with ID</td></tr><tr><td>$1.04</td><td>03</td><td>Invalid Merchant ID</td></tr><tr><td>$1.05</td><td>01</td><td>Refer to issuer</td></tr><tr><td>$1.06</td><td>01</td><td>Refer to issuer</td></tr><tr><td>$1.07</td><td>05</td><td>Do not honor</td></tr><tr><td>$1.08</td><td>05</td><td>Do not honor</td></tr><tr><td>$1.09</td><td>03</td><td>Invalid Merchant ID</td></tr><tr><td>$1.10</td><td>06</td><td>General error</td></tr><tr><td>$1.11</td><td>75</td><td>Allowable number of PIN-entry tries exceeded</td></tr><tr><td>$1.12</td><td>55</td><td>Incorrect PIN</td></tr><tr><td>$1.13</td><td>57</td><td>Transaction not permitted - Card</td></tr><tr><td>$1.14</td><td>96</td><td>System malfunction</td></tr><tr><td>$1.15</td><td>91</td><td>Issuer or switch unavailable</td></tr><tr><td>$12.00</td><td>00</td><td>Approved and completed</td></tr><tr><td>$15.00</td><td>10</td><td>Partial approval for the authorized amount returned in Group III version 022</td></tr></tbody></table>
{% endtab %}

{% tab title="Discover" %}

<table><thead><tr><th width="155">Request value</th><th width="145">Response code</th><th width="397">Response text</th></tr></thead><tbody><tr><td>$10.01</td><td>06</td><td> General error</td></tr><tr><td>$10.02</td><td>06</td><td> General error</td></tr><tr><td>$10.03</td><td>03</td><td> Invalid Merchant ID</td></tr><tr><td>$10.04</td><td>04</td><td> Pick up card (no fraud)</td></tr><tr><td>$10.05</td><td>05</td><td> Do not honor</td></tr><tr><td>$10.07</td><td>07</td><td> Pick up card, special condition (fraud account)</td></tr><tr><td>$10.08</td><td>06</td><td> General error</td></tr><tr><td>$10.10</td><td>10</td><td>Partial approval for the authorized amount returned in Group III version 022</td></tr><tr><td>$10.11</td><td>00</td><td> Approved and completed</td></tr><tr><td>$10.12</td><td>12</td><td> Invalid transaction</td></tr><tr><td>$10.13</td><td>13</td><td>Invalid amount</td></tr><tr><td>$10.14</td><td>14</td><td>Invalid card number</td></tr><tr><td>$10.15</td><td>06</td><td>General error</td></tr><tr><td>$10.19</td><td>19</td><td>Re-enter transaction</td></tr><tr><td>$10.30</td><td>30</td><td>Transaction was improperly formatted</td></tr><tr><td>$10.31</td><td>15</td><td>No such issuer</td></tr><tr><td>$10.33</td><td>06</td><td>General error</td></tr><tr><td>$10.34</td><td>06</td><td>General error</td></tr><tr><td>$10.35</td><td>06</td><td>General error</td></tr><tr><td>$10.36</td><td>06</td><td>General error</td></tr><tr><td>$10.37</td><td>06</td><td>General error</td></tr><tr><td>$10.38</td><td>75</td><td>Allowable number of PIN-entry tries exceeded</td></tr><tr><td>$10.39</td><td>39</td><td>No credit account</td></tr><tr><td>$10.40</td><td>12</td><td>Invalid transaction</td></tr><tr><td>$10.41</td><td>41</td><td>Lost card, pick up (fraud account)</td></tr><tr><td>$10.43</td><td>43</td><td>Stolen card, pick up (fraud account)</td></tr><tr><td>$10.51</td><td>05</td><td>Do not honor</td></tr><tr><td>$10.53</td><td>53</td><td>No savings account</td></tr><tr><td>$10.54</td><td>54</td><td>Expired card</td></tr><tr><td>$10.55</td><td>55</td><td>Incorrect PIN</td></tr><tr><td>$10.56</td><td>14</td><td>Invalid card number</td></tr><tr><td>$10.57</td><td>57</td><td>Transaction not permitted - Card</td></tr><tr><td>$10.58</td><td>58</td><td>Transaction not permitted - Terminal</td></tr><tr><td>$10.59</td><td>05</td><td>Do not honor</td></tr><tr><td>$10.60</td><td>01</td><td>Refer to issuer</td></tr><tr><td>$10.61</td><td>61</td><td>Exceeds approval amount limit</td></tr><tr><td>$10.62</td><td>62</td><td>Invalid service code, restricted</td></tr><tr><td>$10.63</td><td>63</td><td>Security violation</td></tr><tr><td>$10.66</td><td>77</td><td>Inconsistent, reversed or repeat data</td></tr><tr><td>$10.65</td><td>65</td><td>Exceeds withdrawal frequency limit</td></tr><tr><td>$10.66</td><td>01</td><td>Refer to issuer</td></tr><tr><td>$10.67</td><td>04</td><td>Pick up card (no fraud)</td></tr><tr><td>$10.68</td><td>06</td><td>General error</td></tr><tr><td>$10.67</td><td>04</td><td>Pick up card (no fraud)</td></tr><tr><td>$10.68</td><td>06</td><td>General error</td></tr><tr><td>$10.75</td><td>75</td><td>Allowable number of PIN-entry tries exceeded</td></tr><tr><td>$10.76</td><td>14</td><td>Invalid card number</td></tr><tr><td>$10.77</td><td>14</td><td>Invalid card number</td></tr><tr><td>$10.78</td><td>14</td><td>Invalid card number</td></tr><tr><td>$10.79</td><td>85</td><td>No reason to decline</td></tr><tr><td>$10.87</td><td>91</td><td>Issuer or switch unavailable</td></tr><tr><td>$10.91</td><td>91</td><td>Issuer or switch unavailable</td></tr><tr><td>$10.92</td><td>92</td><td>Destination not found</td></tr><tr><td>$10.93</td><td>93</td><td>Violation, cannot complete</td></tr><tr><td>$10.94</td><td>94</td><td>Unable to locate, no match</td></tr><tr><td>$10.96</td><td>96</td><td>System malfunction</td></tr><tr><td>$10.97</td><td>D3</td><td>Transaction failure due to missing or invalid 3D-Secure cryptogram</td></tr></tbody></table>
{% endtab %}
{% endtabs %}

***

## AVS responses <a href="#address-verification-service-responses" id="address-verification-service-responses"></a>

Below you'll find a reference list to every possible Address Verification Service (AVS) response value.

<table><thead><tr><th width="177">Response Code</th><th width="159">Customer zip</th><th width="397">Response text</th></tr></thead><tbody><tr><td>Z</td><td>85284</td><td>Zip Match</td></tr><tr><td>U</td><td>99999</td><td>Ver Unavailable</td></tr><tr><td>G</td><td>99998</td><td>Ver Unavailable</td></tr><tr><td>B</td><td>999970001</td><td>Address Match</td></tr><tr><td>C</td><td>999970002</td><td>Serv Unavailable</td></tr><tr><td>D</td><td>999970003</td><td>Exact Match</td></tr><tr><td>I</td><td>999970004</td><td>Ver Unavailable</td></tr><tr><td>M</td><td>999970005</td><td>Exact Match</td></tr><tr><td>P</td><td>999970006</td><td>Zip Match</td></tr><tr><td>A</td><td>999970007</td><td>Address Match</td></tr><tr><td>Y</td><td>999970008</td><td>Exact Match</td></tr></tbody></table>

To receive a **full AVS and CVV match**, please use the following test card and address:

<table><thead><tr><th>Card brand</th><th width="207">Card number</th><th width="105">EXP Date</th><th width="85">CVV</th><th width="99">Address</th><th>Zip code</th><th data-hidden data-type="files"></th></tr></thead><tbody><tr><td><h3><img src="/files/4WAMdYKoy2zK810bs7gT" alt=""></h3></td><td>4012 0000 9876 5439</td><td>12/28</td><td>999</td><td>8320</td><td>85284</td><td><a href="/files/4WAMdYKoy2zK810bs7gT">/files/4WAMdYKoy2zK810bs7gT</a></td></tr></tbody></table>

***

## Partial authorization <a href="#partial-authorization-with-global-tsys" id="partial-authorization-with-global-tsys"></a>

### Partial auth test cards <a href="#partial-authorization-test-data" id="partial-authorization-test-data"></a>

To test partial authorization, use these cards and request values:

<table><thead><tr><th width="158">Card brand</th><th width="208">Card number</th><th width="96">EXP date</th><th width="70">CVV</th><th width="100">Request</th><th>Partial approval</th></tr></thead><tbody><tr><td><h3><img src="/files/wOMfkVciFjfWhXwmE7Xc" alt="" data-size="original"></h3></td><td>6011 0009 9302 6909</td><td>01/28</td><td>999</td><td>$10.10</td><td>$10.00</td></tr><tr><td><h3><img src="/files/rgifPIiHkSSZfL2LoPiJ" alt="" data-size="original"></h3></td><td>5146 3126 2000 0045</td><td>01/28</td><td> 998</td><td>$11.10</td><td>$5.55</td></tr></tbody></table>

***

## Decline codes

Below you'll find a reference list to every possible decline code value.

<table><thead><tr><th width="164">Response code</th><th width="218">Authorization response</th><th width="368">Response definition</th></tr></thead><tbody><tr><td>00</td><td>APPROVAL</td><td>Approved and completed</td></tr><tr><td>01</td><td>CALL</td><td>Refer to issuer</td></tr><tr><td>02</td><td>CALL</td><td>Refer to issuer - Special condition</td></tr><tr><td>03</td><td>TERM ID ERROR</td><td>Invalid Merchant ID</td></tr><tr><td>04</td><td>HOLD-CALL</td><td>Pick up card (no fraud)</td></tr><tr><td>05</td><td>DECLINE</td><td>Do not honor</td></tr><tr><td>06</td><td>ERROR</td><td>General error</td></tr><tr><td>07</td><td>HOLD-CALL</td><td>Pick up card, special condition (fraud account)</td></tr><tr><td>08</td><td>APPROVAL</td><td>Honor MasterCard with ID</td></tr><tr><td>10</td><td>PARTIAL APPROVAL</td><td>Partial approval for the authorized amount returned in Group III version 022</td></tr><tr><td>11</td><td>APPROVAL</td><td>VIP approval</td></tr><tr><td>12</td><td>INVALID TRANS</td><td>Invalid transaction</td></tr><tr><td>13</td><td>AMOUNT ERROR</td><td>Invalid amount</td></tr><tr><td>14</td><td>CARD NO. ERROR</td><td>Invalid card number</td></tr><tr><td>15</td><td>NO SUCH ISSUER</td><td>No such issuer</td></tr><tr><td>19</td><td>RE ENTER</td><td>Re-enter transaction</td></tr><tr><td>21</td><td>NO ACTION TAKEN</td><td>Unable to back out transaction</td></tr><tr><td>25</td><td>NO CARD NUMBER</td><td>Unable to locate the account number</td></tr><tr><td>28</td><td>NO REPLY</td><td>File is temporarily unavailable</td></tr><tr><td>30</td><td>MSG FORMAT ERROR</td><td>Transaction was improperly formatted</td></tr><tr><td>39</td><td>NO CREDIT ACCT</td><td>No credit account</td></tr><tr><td>41</td><td>HOLD-CALL</td><td>Lost card, pick up (fraud account)</td></tr><tr><td>43</td><td>HOLD-CALL</td><td>Stolen card, pick up (fraud account)</td></tr><tr><td>46</td><td>CLOSED ACCOUNT</td><td>Closed account</td></tr><tr><td>51</td><td>DECLINE</td><td>Insufficient funds</td></tr><tr><td>52</td><td>NO CHECK ACCOUNT</td><td>No checking account</td></tr><tr><td>53</td><td>NO SAVE ACCOUNT</td><td>No savings account</td></tr><tr><td>54</td><td>EXPIRED CARD</td><td>Expired card</td></tr><tr><td>55</td><td>WRONG PIN</td><td>Incorrect PIN</td></tr><tr><td>57</td><td>SERV NOT ALLOWED</td><td>Transaction not permitted - Card</td></tr><tr><td>58</td><td>SERV NOT ALLOWED</td><td>Transaction not permitted - Terminal</td></tr><tr><td>59</td><td>SUSPECTED FRAUD</td><td>Suspected fraud</td></tr><tr><td>61</td><td>EXP APPR AMT LIM</td><td>Exceeds approval amount limit</td></tr><tr><td>62</td><td>DECLINE</td><td>Invalid service code, restricted</td></tr><tr><td>63</td><td>SEC VIOLATION</td><td>Security violation</td></tr><tr><td>65</td><td>EXC W/D FREQ LIM</td><td>Exceeds withdrawal frequency limit</td></tr><tr><td>6P</td><td>VERIF DATA FAILD</td><td>Verification data failed</td></tr><tr><td>75</td><td>PIN EXCEEDED</td><td>Allowable number of PIN-entry tries exceeded</td></tr><tr><td>76</td><td>UNSOLIC REVERSAL</td><td>Unable to locate, no match</td></tr><tr><td>77</td><td>NO ACTION TAKEN</td><td>Inconsistent, reversed or repeat data</td></tr><tr><td>78</td><td>NO ACCOUNT</td><td>Blocked, first used transaction from new cardholder, and card not properly unblocked</td></tr><tr><td>79</td><td>ALREADY REVERSED</td><td>Already reversed at switch</td></tr><tr><td>80</td><td>NO IMPACT</td><td>No Financial impact (used in reversal responses to decline originals)</td></tr><tr><td>81</td><td>ENCRYPTION ERROR</td><td>Cryptographic error</td></tr><tr><td>82</td><td>INCORRECT CVV</td><td>CVV data is not correct OR Offline PIN authentication interrupted</td></tr><tr><td>83</td><td>CAN'T VERIFY PIN</td><td>Cannot verify PIN</td></tr><tr><td>85</td><td>CARD OK</td><td>No reason to decline</td></tr><tr><td>86</td><td>CAN'T VERIFY PIN</td><td>Cannot verify PIN</td></tr><tr><td>91</td><td>NO REPLY</td><td>Issuer or switch unavailable</td></tr><tr><td>92</td><td>INVALID ROUTING</td><td>Destination not found</td></tr><tr><td>93</td><td>DECLINE</td><td>Violation, cannot complete</td></tr><tr><td>94</td><td>DUPLICATE TRANS</td><td>Unable to locate, no match</td></tr><tr><td>96</td><td>SYSTEM ERROR</td><td>System malfunction</td></tr><tr><td>A1</td><td>ACTIVATED</td><td>POS device authentication successful</td></tr><tr><td>A2</td><td>NOT ACTIVATED</td><td>POS device authentication not successful</td></tr><tr><td>A3</td><td>DEACTIVATED</td><td>POS device deactivation successful</td></tr><tr><td>B1</td><td>SRCHG NOT ALLOWED</td><td>Surcharge amount not permitted on debit cards or EBT food stamps</td></tr><tr><td>B2</td><td>SRCHRG NOT ALLOWED</td><td>Surcharge amount not supported by debit network issuer</td></tr><tr><td>CV</td><td>FAILURE CV</td><td>Card Type Verification Error</td></tr><tr><td>D3</td><td>SECUR CRYPT FAIL</td><td>Transaction failure due to missing or invalid 3D-Secure cryptogram</td></tr><tr><td>E1</td><td>ENCR NOT CONFIGD</td><td>Encryption is not configured</td></tr><tr><td>E2</td><td>TERM NOT AUTHENT</td><td>Terminal is not authenticated</td></tr><tr><td>E3</td><td>DECRYPT FAILURE</td><td>Data could not be decrypted</td></tr><tr><td>EA</td><td>ACCT LENGTH ERR</td><td>Verification error</td></tr><tr><td>EB</td><td>CHECK DIGIT ERR</td><td>Verification error</td></tr><tr><td>EC</td><td>CID FORMAT ERROR</td><td>Verification error</td></tr><tr><td>H1</td><td>SERV NOT ALLOWED</td><td>Contact Merchant Services/ Technical Support</td></tr><tr><td>H2</td><td>SERV NOT ALLOWED</td><td>Contact Merchant Services/ Technical Support</td></tr><tr><td>H3</td><td>SERV NOT ALLOWED</td><td>Contact Merchant Services/ Technical Support</td></tr><tr><td>H4</td><td>SERV NOT ALLOWED</td><td>Contact Merchant Services/ Technical Support</td></tr><tr><td>H5</td><td>SERV NOT ALLOWED</td><td>Contact Merchant Services/ Technical Support</td></tr><tr><td>H6</td><td>SERV NOT ALLOWED</td><td>Contact Merchant Services/ Technical Support</td></tr><tr><td>H7</td><td>SERV NOT ALLOWED</td><td>Contact Merchant Services/ Technical Support</td></tr><tr><td>H8</td><td>SERV NOT ALLOWED</td><td>Contact Merchant Services/ Technical Support</td></tr><tr><td>H9</td><td>SERV NOT ALLOWED</td><td>Contact Merchant Services/ Technical Support</td></tr><tr><td>HV</td><td>FAILURE HV</td><td>Hierarchy Verification Error</td></tr><tr><td>K0</td><td>TOKEN RESPONSE</td><td>Token request was processed</td></tr><tr><td>K1</td><td>TOKEN NOT CONFIG</td><td>Tokenization is not configured</td></tr><tr><td>K2</td><td>TERM NOT AUTHEN</td><td>Terminal is not authenticated</td></tr><tr><td>K3</td><td>TOKEN FAILURE</td><td>Data could not be de-tokenized</td></tr><tr><td>M0</td><td>DOM DBT NOT ALWD</td><td>Mastercard: Canada region-issued Domestic Debit Transaction not allowed</td></tr><tr><td>N3</td><td>CACHBACK NOT AVL</td><td>Cash back service not available</td></tr><tr><td>N4</td><td>DECLINE</td><td>Exceeds issuer withdrawal limit</td></tr><tr><td>N7</td><td>CVV2 MISMATCH</td><td>CVV2 Value supplied is invalid</td></tr><tr><td>P0</td><td>SERV NOT ALLOWED</td><td>Contact Merchant Services/ Technical Support</td></tr><tr><td>P1</td><td>SERV NOT ALLOWED</td><td>Contact Merchant Services/ Technical Support</td></tr><tr><td>P2</td><td>SERV NOT ALLOWED</td><td>Contact Merchant Services/ Technical Support</td></tr><tr><td>P3</td><td>SERV NOT ALLOWED</td><td>Contact Merchant Services/ Technical Support</td></tr><tr><td>P4</td><td>SERV NOT ALLOWED</td><td>Contact Merchant Services/ Technical Support</td></tr><tr><td>P5</td><td>SERV NOT ALLOWED</td><td>Contact Merchant Services/ Technical Support</td></tr><tr><td>P6</td><td>SERV NOT ALLOWED</td><td>Contact Merchant Services/ Technical Support</td></tr><tr><td>P7</td><td>MISSING SERIAL NUM</td><td>The terminal has not yet completed the boarding process. The Serial Number has not been set up.</td></tr><tr><td>Q1</td><td>CARD AUTH FAIL</td><td>Card authentication failed</td></tr><tr><td>R0</td><td>STOP RECURRING</td><td>Customer requested stop of specific recurring payment</td></tr><tr><td>R1</td><td>STOP RECURRING</td><td>Customer requested stop of all recurring payments from specific merchant</td></tr><tr><td>R3</td><td>STOP ALL RECUR</td><td>All recurring payments have been canceled for the card number in the request</td></tr><tr><td>S0</td><td>INACTIVE CARD</td><td>The PAN used in the transaction is inactive.</td></tr><tr><td>S1</td><td>MOD 10 FAIL</td><td>The Mod-10 check failed.</td></tr><tr><td>S5</td><td>DCLN NO PRE AUTH</td><td>Decline - no preauthorization found.</td></tr><tr><td>S9</td><td>MAX BALANCE</td><td>Maximum working balance exceeded</td></tr><tr><td>SA</td><td>SHUT DOWN</td><td>The Authorization Server is shut down.</td></tr><tr><td>SB</td><td>INVALID STATUS</td><td>Invalid card status - status is other than active</td></tr><tr><td>SC</td><td>UNKNOWN STORE</td><td>Unknown dealer/store code - special edit.</td></tr><tr><td>SD</td><td>TOO MANY RCHRGS</td><td>Maximum number of recharges is exceeded.</td></tr><tr><td>SE</td><td>ALREADY USED</td><td>Card was already used.</td></tr><tr><td>SF</td><td>NOT MANUAL</td><td>Manual transactions not allowed.</td></tr><tr><td>SH</td><td>TYPE UNKNOWN</td><td>Transaction type was unknown.</td></tr><tr><td>SJ</td><td>INVALID TENDER</td><td>An invalid tender type was submitted.</td></tr><tr><td>SK</td><td>CUSTOMER TYPE</td><td>An invalid customer type was submitted.</td></tr><tr><td>SL</td><td>PIN LOCKED</td><td>PIN was locked.</td></tr><tr><td>SM</td><td>MAX REDEMPTS</td><td>The maximum number of redemptions was exceeded.</td></tr><tr><td>SP</td><td>MAX PAN TRIES</td><td>The maximum number of PAN tries was exceeded.</td></tr><tr><td>SR</td><td>ALREADY ISSUED</td><td>The card was already issued.</td></tr><tr><td>SS</td><td>NOT ISSUED</td><td>The card was not issued.</td></tr><tr><td>T0</td><td>APPROVAL</td><td>First check is okay and has been converted.</td></tr><tr><td>T1</td><td>CANNOT CONVERT</td><td>The check is okay but cannot be converted. This is a declined transaction.</td></tr><tr><td>T2</td><td>INVALIDABA</td><td>Invalid ABA number, not an ACH participant.</td></tr><tr><td>T3</td><td>AMOUNT ERROR</td><td>Amount greater than the limit.</td></tr><tr><td>V1</td><td>FAILURE VM</td><td>Daily threshold exceeded.</td></tr></tbody></table>

<br>


# First Data Testing

Cards for testing, response code reference, and penny codes for First Data.

*You can order EMV test cards directly from the First Data Test Pack 2 available on OmniPay’s store. This pack includes a set of preconfigured test cards designed for EMV certification and integration testing, making it easy to validate transaction flows in your environment:*

<https://omnipaystore.com/product/first-data-test-pack-2/>

## Test Cards <a href="#test-cards" id="test-cards"></a>

You can use the below cards for testing with First Data.

<table data-header-hidden data-full-width="false"><thead><tr><th width="134"></th><th width="146">Card brand</th><th width="468">Card Number</th></tr></thead><tbody><tr><td><img src="/files/4WAMdYKoy2zK810bs7gT" alt="" data-size="original"></td><td>Visa</td><td>4005 5200 0000 0939</td></tr><tr><td><img src="/files/NfuZ26NdM8pUWAI3vg6Q" alt="" data-size="original"></td><td>MasterCard</td><td>5405 0011 1111 1116</td></tr><tr><td><img src="/files/KqLbqu8tEkA7X8ZKKMmq" alt="" data-size="original"></td><td>Discover</td><td>6011 2087 0111 1117</td></tr><tr><td><img src="/files/WNacEG1cwaX2b9tiQ2mD" alt="" data-size="original"></td><td>Amex</td><td>3759 8765 4111 116</td></tr></tbody></table>

{% hint style="info" %}
To get AVS and CVV match use the following:

**Address** - 1307 Broad Hollow Road

**Zip** - 11747

**CVV** - 123

**CVV FOR AMEX** - 1234
{% endhint %}

***

## Response codes <a href="#response-codes" id="response-codes"></a>

Below you'll find a reference list to every possible response code value.

<table><thead><tr><th width="162">Response code	</th><th>Description</th></tr></thead><tbody><tr><td>000</td><td>Approve</td></tr><tr><td>001</td><td>Schema Validation Error</td></tr><tr><td>002</td><td>Approve for partial amount</td></tr><tr><td>003</td><td>Approve VIP</td></tr><tr><td>100</td><td>Do not honor</td></tr><tr><td>101</td><td>Expired card</td></tr><tr><td>102</td><td>Suspected fraud</td></tr><tr><td>103</td><td>Unable to process TeleCheck recurring transaction with this payment type (not associated with insufficient or uncollected funds)</td></tr><tr><td>104</td><td>Restricted card</td></tr><tr><td>105</td><td>Call acquirer's security department</td></tr><tr><td>106</td><td>Allowable PIN tries exceeded</td></tr><tr><td>107</td><td>Call for authorization</td></tr><tr><td>108</td><td>Refer to issuer's special conditions</td></tr><tr><td>109</td><td>Invalid merchant. The merchant is not in the merchant database or the merchant is not permitted to use this particular card</td></tr><tr><td>110</td><td>Invalid amount</td></tr><tr><td>111</td><td>Invalid Host Totals Date</td></tr><tr><td>112</td><td>DES Encryption not allowed from the device / terminal</td></tr><tr><td>113</td><td>Host Totals are Incomplete</td></tr><tr><td>114</td><td>Invalid account type</td></tr><tr><td>116</td><td>Not sufficient funds</td></tr><tr><td>117</td><td>Incorrect PIN or PIN length error</td></tr><tr><td>118</td><td>No card record</td></tr><tr><td>119</td><td>Transaction not permitted to cardholder</td></tr><tr><td>120</td><td>Transaction not permitted to terminal</td></tr><tr><td>121</td><td>Exceeds withdrawal amount limit</td></tr><tr><td>122</td><td>Security violation</td></tr><tr><td>123</td><td>Exceeds withdrawal frequency limit</td></tr><tr><td>124</td><td>Violation of law</td></tr><tr><td>129</td><td>Suspected counterfeit card</td></tr><tr><td>130</td><td>Invalid terminal</td></tr><tr><td>131</td><td>Invalid account number</td></tr><tr><td>132</td><td>Unmatched card expiry date</td></tr><tr><td>133</td><td>The TPP ID was not found</td></tr><tr><td>134</td><td>Not sufficient funds</td></tr><tr><td>150</td><td>Invalid merchant set up</td></tr><tr><td>151</td><td>Activation failed</td></tr><tr><td>152</td><td>Exceeds limit</td></tr><tr><td>153</td><td>Already redeemed</td></tr><tr><td>154</td><td>Over monthly limit</td></tr><tr><td>155</td><td>Recharge amount exceeded</td></tr><tr><td>156</td><td>Max number of recharges exceeded</td></tr><tr><td>157</td><td>Invalid entry</td></tr><tr><td>208</td><td>Lost Card / Lost Check</td></tr><tr><td>209</td><td>Stolen card</td></tr><tr><td>211</td><td>Invalid SKU number.</td></tr><tr><td>212</td><td>Missing conditional data.</td></tr><tr><td>213</td><td>Invalid account number for card type.</td></tr><tr><td>214</td><td>Invalid payment type/card type for merchant ID.</td></tr><tr><td>215</td><td>Invalid transaction for Merchant ID.</td></tr><tr><td>216</td><td>Invalid TransArmor request. Not supported for given Payment Type, or Merchant is not enabled for Transarmor</td></tr><tr><td>217</td><td>Missing or invalid secure payment data.</td></tr><tr><td>218</td><td>Merchant ID not enabled for Secure Code.</td></tr><tr><td>219</td><td>Invalid Merchant Category Code</td></tr><tr><td>220</td><td>Customer service phone number missing.</td></tr><tr><td>221</td><td>Merchant not enabled for soft descriptors, account updater or optimization processing.</td></tr><tr><td>222</td><td>Partial auth not allowed.</td></tr><tr><td>223</td><td>Customer under 18 years old.</td></tr><tr><td>224</td><td>Account blocked – possible compromise.</td></tr><tr><td>225</td><td>Bill-to address does not match ship-to.</td></tr><tr><td>226</td><td>Invalid preapproval number.</td></tr><tr><td>227</td><td>Invalid email address.</td></tr><tr><td>228</td><td>Need more ID – request full SSN.</td></tr><tr><td>229</td><td>Previously declined/closed account.</td></tr><tr><td>230</td><td>One time stop payment requested by cardholder.</td></tr><tr><td>231</td><td>Stop payment requested for all payments.</td></tr><tr><td>232</td><td>Stop all payments – account closed.</td></tr><tr><td>233</td><td>Auth response date not valid.</td></tr><tr><td>234</td><td>Issuance under minimum amount.</td></tr><tr><td>235</td><td>Outstanding auth – funds on hold.</td></tr><tr><td>236</td><td>Activation amount incorrect.</td></tr><tr><td>237</td><td>Deny – new card issued.</td></tr><tr><td>238</td><td>BIN blocked.</td></tr><tr><td>242</td><td>Customer opt-out.</td></tr><tr><td>243</td><td>Institution does not accept ACH payments.</td></tr><tr><td>244</td><td>Original transaction not approved.</td></tr><tr><td>245</td><td>Invalid MICR data.</td></tr><tr><td>246</td><td>Declined due to high risk.</td></tr><tr><td>247</td><td>Declined due to stand-in rules.</td></tr><tr><td>248</td><td>Conditional Approval – Hold shipping for 24 hours</td></tr><tr><td>250</td><td>Re-authorization request is declined. Original Auth could not be found.</td></tr><tr><td>251</td><td>Re-authorization request is declined. The customer account number, merchant id, or amount did not match the original authorization.</td></tr><tr><td>252</td><td>Re-authorization request is declined. The amount significantly exceeds the original request amount.</td></tr><tr><td>253</td><td>Re-authorization request is declined. The timeframes for re-authorization have been exceeded.</td></tr><tr><td>254</td><td>Counter Offer to Supply Personal Guaranty.</td></tr><tr><td>300</td><td>Invalid EAN or SCV.</td></tr><tr><td>301</td><td>Lock has expired on prepaid card.</td></tr><tr><td>302</td><td>Account closed. The account was closed, probably because the account balance was $0.00</td></tr><tr><td>303</td><td>Unknown account. The account could not be located or the account does not exist in the account table</td></tr><tr><td>304</td><td>Inactive account. The account has not been activated by an approved location</td></tr><tr><td>308</td><td>Already active. The card is already active and does not need to be reactivated</td></tr><tr><td>311</td><td>Not lost or stolen</td></tr><tr><td>315</td><td>Bad mag stripe. The mag stripe could not be parsed for account information</td></tr><tr><td>316</td><td>Incorrect location. There was a problem with the merchant location</td></tr><tr><td>317</td><td>Max balance exceeded. The transaction, if completed, would cause the account balance to be exceeded by the max_balance as specified in the promotion. Some merchants set the max_balance to a value twice the max transaction amount</td></tr><tr><td>318</td><td>Invalid amount. There was a problem with the amount field in the transaction format – more or less than min/max amounts specified in the promotion for that transaction</td></tr><tr><td>319</td><td>Invalid clerk. The clerk field was either missing, when required, or the content did not match the requirements</td></tr><tr><td>320</td><td>Invalid password</td></tr><tr><td>321</td><td>Invalid new password. The new password does not meet the minimum security criteria</td></tr><tr><td>322</td><td>Exceeded account reloads. The clerk/user/location was only permitted to reload some number of accounts. That number was exceeded. (See your Business Manager in order to extend this limit.)</td></tr><tr><td>323</td><td>Password retry exceeded. The user account has been frozen because the user attempted access and was denied. Seek management assistance</td></tr><tr><td>326</td><td>Incorrect transaction version or format number for POS transactions</td></tr><tr><td>327</td><td>Request not permitted by this account</td></tr><tr><td>328</td><td>Request not permitted by this merchant location</td></tr><tr><td>329</td><td>Bad_repay_date</td></tr><tr><td>330</td><td>Bad checksum. The checksum provided is incorrect</td></tr><tr><td>331</td><td>Balance not available (denial). Due to an internal Fiserv Prepaid Closed Loop issue, information from this account could not be retrieved</td></tr><tr><td>332</td><td>Account locked</td></tr><tr><td>333</td><td>No previous transaction. The void or reversal transaction could not be matched to a previous (original) transaction. In the case of a redemption, the corresponding locking transaction could not be identified</td></tr><tr><td>334</td><td>Already reversed</td></tr><tr><td>336</td><td>Bad Authorization ID. The Authorization ID test failed</td></tr><tr><td>337</td><td>Too many transactions requested</td></tr><tr><td>338</td><td>No transactions available/no more transactions available. There are no transactions for this account or there are no transactions as determined by the specified first transaction number</td></tr><tr><td>339</td><td>Transaction history not available</td></tr><tr><td>340</td><td>New password required</td></tr><tr><td>341</td><td>Invalid status change. The status change requested (e.g. lost/stolen, freeze active card) cannot be performed</td></tr><tr><td>342</td><td>Void of activation after account activity</td></tr><tr><td>343</td><td>No phone service. Attempted a calling card transaction on an account which is not configured for calling card activity</td></tr><tr><td>344</td><td>Internet access disabled</td></tr><tr><td>345</td><td>Invalid Date or Time</td></tr><tr><td>350</td><td>Additional customer authentication required or, Customer Authentication Required (Decline – Discover only)</td></tr><tr><td>351</td><td>Customer PIN authentication required</td></tr><tr><td>355</td><td>Invalid currency. The provided currency is invalid.</td></tr><tr><td>356</td><td>Currency Not Supported</td></tr><tr><td>357</td><td>Currency conversion error</td></tr><tr><td>359</td><td>The terminal transaction number did not match (on a void or reversal).</td></tr><tr><td>367</td><td>Target embossed card entered and Transaction count entered do not match</td></tr><tr><td>368</td><td>No account link</td></tr><tr><td>369</td><td>Invalid time zone</td></tr><tr><td>370</td><td>Account on hold or subscriber not active</td></tr><tr><td>372</td><td>Promo location restricted</td></tr><tr><td>373</td><td>Invalid Card Account</td></tr><tr><td>374</td><td>Product code(s) restricted</td></tr><tr><td>375</td><td>Bad Post Date. The Post Date is not a valid date.</td></tr><tr><td>376</td><td>Account status is void lock</td></tr><tr><td>377</td><td>Already active and reloadable</td></tr><tr><td>378</td><td>Account is Purged. The Account record was purged from the database.</td></tr><tr><td>380</td><td>Bulk activation error</td></tr><tr><td>381</td><td>Bulk activation un-attempted error</td></tr><tr><td>382</td><td>Bulk activation package amount error</td></tr><tr><td>383</td><td>Store location zero not allowed</td></tr><tr><td>384</td><td>Account row locked</td></tr><tr><td>385</td><td>Accepted but not yet processed</td></tr><tr><td>402</td><td>TransArmor Service Unavailable</td></tr><tr><td>403</td><td>TransArmor Invalid Token or Account Number</td></tr><tr><td>404</td><td>TransArmor Key Error</td></tr><tr><td>414</td><td>Void/Full Reversal request unable to process due to network cut-off window elapsed. A Refund transaction is necessary to reconcile the cardholder’s account. Applicable to Debit networks only.</td></tr><tr><td>430</td><td>Prepaid Card Amount Over EU AMLD (Anti-Money Laundering Directive) Limit</td></tr><tr><td>500</td><td>Decline</td></tr><tr><td>501</td><td>Date of Birth Error for Check Processing</td></tr><tr><td>502</td><td>Invalid State Code</td></tr><tr><td>503</td><td>New Account Information</td></tr><tr><td>504</td><td>Do not try again</td></tr><tr><td>505</td><td>Please retry</td></tr><tr><td>506</td><td>Invalid Checking Account Number</td></tr><tr><td>507</td><td>New Account Information available</td></tr><tr><td>508</td><td>Try again later – Declined: Association‘s payment cancellation advice code provided. Applies to recurring authorizations only. These are examples of what may have occurred: the account is over the credit limit try again in 72 hours.</td></tr><tr><td>509</td><td>Do not try again – Applies to recurring authorizations only. The card has expired</td></tr><tr><td>510</td><td>New Account Information – Applies to recurring authorizations only. The card has expired.</td></tr><tr><td>511</td><td>Try again later – Applies to recurring authorizations only. The card has expired. Get the new expiration date and try again.</td></tr><tr><td>512</td><td>Service not allowed or invalid surcharge amount</td></tr><tr><td>513</td><td>Decline. Transaction not permitted to acquirer or terminal.</td></tr><tr><td>514</td><td>Do not try again – Applies to recurring authorizations only. There was security violation.</td></tr><tr><td>515</td><td>Declined. No term record on Fiserv system</td></tr><tr><td>516</td><td>Please retry – Reasons for this error are one of the following: Format Error, Unable to route transaction, Switch or issuer unavailable, System Busy, Timeout</td></tr><tr><td>517</td><td>CVV2 Declined</td></tr><tr><td>518</td><td>Invalid account/date or sales date in future</td></tr><tr><td>519</td><td>Invalid Effective Date</td></tr><tr><td>520</td><td>Reversal Rejected. Do not try again.</td></tr><tr><td>521</td><td>Enter lesser amount</td></tr><tr><td>522</td><td>Cash Back greater than total Transaction amount</td></tr><tr><td>523</td><td>Crypto box is offline</td></tr><tr><td>524</td><td>Debit Switch unavailable Timeout Retry – Communications link to debit/EBT network gateway is down or responded with a “System Malfunction (96)” message.</td></tr><tr><td>525</td><td>Debit/EBT network gateway cannot get through to the ISSUER.</td></tr><tr><td>526</td><td>Undefined Card – Debit/EBT network gateway cannot route card based on Merchant Entitlement</td></tr><tr><td>527</td><td>Network Response indicates that Merchant ID / SE is invalid</td></tr><tr><td>528</td><td>Debit/EBT transaction count exceeds pre-determined limit in specified time/ Withdrawal limit exceeded.</td></tr><tr><td>529</td><td>Resubmission of transaction violates debit/EBT network frequency</td></tr><tr><td>530</td><td>The authorizing network has a problem decrypting the cryptogram in the request</td></tr><tr><td>531</td><td>Retry with 3DS data</td></tr><tr><td>532</td><td>The DUKPT Base Derivation key is missing or incorrect in the PIN pad, PIN key synchronization error, or Master session PIN key is missing.</td></tr><tr><td>533</td><td>Invalid encryption key offset sent by merchant</td></tr><tr><td>534</td><td>Invalid master session key id sent by merchant</td></tr><tr><td>539</td><td>No Checking Account</td></tr><tr><td>540</td><td>Edit Honor</td></tr><tr><td>541</td><td>No Savings Account</td></tr><tr><td>542</td><td>DUKPT: An error while processing the PIN block that is not related to the point-of-sale equipment. Contact the Help Desk for assistance.</td></tr><tr><td>550</td><td>Invalid Vehicle</td></tr><tr><td>551</td><td>Invalid Driver</td></tr><tr><td>552</td><td>Invalid Product</td></tr><tr><td>553</td><td>Exceeds transaction total limit per product class.</td></tr><tr><td>554</td><td>Over daily limit</td></tr><tr><td>555</td><td>Invalid Date/Time</td></tr><tr><td>556</td><td>Exceeds quantity</td></tr><tr><td>557</td><td>Invalid prompt entry</td></tr><tr><td>558</td><td>Invalid Track 2 data</td></tr><tr><td>559</td><td>Voyager ID problem</td></tr><tr><td>560</td><td>Invalid Odometer</td></tr><tr><td>561</td><td>Invalid Restriction Code</td></tr><tr><td>562</td><td>Pay at pump not allowed</td></tr><tr><td>563</td><td>Over fuel limit</td></tr><tr><td>564</td><td>Over cash limit</td></tr><tr><td>565</td><td>Fuel price error</td></tr><tr><td>566</td><td>Y or N required</td></tr><tr><td>567</td><td>Over repair limit</td></tr><tr><td>568</td><td>Over additive limit</td></tr><tr><td>569</td><td>Invalid user</td></tr><tr><td>570</td><td>Before 1400 and can't cut. Wait until 2:00 pm Eastern.</td></tr><tr><td>571</td><td>Cut time too close to 1400</td></tr><tr><td>572</td><td>Checker/Manager not found</td></tr><tr><td>573</td><td>Security insufficient</td></tr><tr><td>574</td><td>No transaction security record</td></tr><tr><td>575</td><td>Insufficient data</td></tr><tr><td>576</td><td>Merchant has mail pending</td></tr><tr><td>577</td><td>No messages pending</td></tr><tr><td>578</td><td>The Visa OCT / MasterCard MoneySend activity has exceeded preset transaction count or amount limit within a rolling 24-hour period for given merchant.</td></tr><tr><td>579</td><td>The Visa OCT / MasterCard MoneySend activity has exceeded preset transaction count or amount limit within a rolling 7-day period for given merchant.</td></tr><tr><td>580</td><td>The Visa OCT / MasterCard MoneySend activity has exceeded preset transaction count or amount limit within a rolling 30-day period for given merchant.</td></tr><tr><td>581</td><td>The Visa OCT / MasterCard MoneySend Funding activity has exceeded preset transaction count or amount limit within a rolling 24- hour period for this account number.</td></tr><tr><td>582</td><td>The Visa OCT / MasterCard MoneySend Funding activity has exceeded preset transaction count or amount limit within a rolling 7- day period for this account number.</td></tr><tr><td>583</td><td>The Visa OCT / MasterCard MoneySend Funding activity has exceeded preset transaction count or amount limit within a rolling 30- day period for this account number.</td></tr><tr><td>584</td><td>The Visa OCT / MasterCard MoneySend Payment activity has exceeded preset transaction count or amount limit within a rolling 24- hour period for this account number.</td></tr><tr><td>585</td><td>The Visa OCT / MasterCard MoneySend Payment activity has exceeded preset transaction count or amount limit within a rolling 7- day period for this account number.</td></tr><tr><td>586</td><td>The Visa OCT / MasterCard MoneySend Payment activity has exceeded preset transaction count or amount limit within a rolling 30- day period for this account number.</td></tr><tr><td>587</td><td>The single transaction amount limit was exceeded for a Visa OCT/ MasterCard MoneySend transaction for given merchant.</td></tr><tr><td>588</td><td>All Visa OCT / MasterCard MoneySend transactions are blocked for a rolling 24 hour period, or 7 day period (current and prior 6 days), or 30 day period (current and prior 29 days) for given merchant.</td></tr><tr><td>601</td><td>Invalid Batch Number/ Invalid Batch ID or Invalid OpenBatch</td></tr><tr><td>602</td><td>No Open Batch</td></tr><tr><td>603</td><td>Close Unavailable</td></tr><tr><td>604</td><td>Close Not Valid</td></tr><tr><td>701</td><td>Approved EMV Key Load</td></tr><tr><td>702</td><td>EMV Key Download Error</td></tr><tr><td>703</td><td>Approved EMV Key Load, more key load data pending</td></tr><tr><td>704</td><td>Pick Up Card</td></tr><tr><td>708</td><td>Honor With Authentication</td></tr><tr><td>721</td><td>Invalid ZIP Code</td></tr><tr><td>722</td><td>Invalid value in the field / Host Totals Declined</td></tr><tr><td>723</td><td>Driver's License or ID is Required</td></tr><tr><td>724</td><td>Referred – Not Active</td></tr><tr><td>726</td><td>Unable to Locate Record On File</td></tr><tr><td>727</td><td>Refer – Call Authorization</td></tr><tr><td>728</td><td>Referred – Skip Trace Info</td></tr><tr><td>729</td><td>Hard Negative Info On File</td></tr><tr><td>731</td><td>Rejected Lost/Stolen Checks</td></tr><tr><td>740</td><td>Totals Unavailable</td></tr><tr><td>767</td><td>Hard Capture; Pick Up</td></tr><tr><td>771</td><td>Amount Too Large</td></tr><tr><td>772</td><td>Duplicate Return</td></tr><tr><td>773</td><td>Unsuccessful</td></tr><tr><td>774</td><td>Duplicate Reversal</td></tr><tr><td>775</td><td>Subsystem Unavailable</td></tr><tr><td>776</td><td>Duplicate Completion</td></tr><tr><td>782</td><td>Count Exceeds Limit</td></tr><tr><td>785</td><td>No reason to decline– applicable to $0.00 verification requests and may be returned on Online Refund responses. Should be treated as an approval.</td></tr><tr><td>790</td><td>Not approved. Used only in Visa bill/recurring payment. Merchant must not resubmit same transaction but may continue billing process in subsequent billing period.</td></tr><tr><td>791</td><td>Not approved. Used only in Visa bill/recurring payment. Merchant must stop recurring payment requests.</td></tr><tr><td>792</td><td>See attendant.</td></tr><tr><td>800</td><td>Deferred authorization not cancelled 801 Over merchandise limit</td></tr><tr><td>802</td><td>Imprint card</td></tr><tr><td>803</td><td>Not on file</td></tr><tr><td>804</td><td>Fuel only</td></tr><tr><td>805</td><td>Velocity exceeded</td></tr><tr><td>806</td><td>Authorization ID needed</td></tr><tr><td>807</td><td>Over non-fuel limit</td></tr><tr><td>808</td><td>Invalid location</td></tr><tr><td>809</td><td>Over card velocity count</td></tr><tr><td>810</td><td>Over card velocity amount</td></tr><tr><td>811</td><td>Over issuer velocity count</td></tr><tr><td>812</td><td>Over issuer velocity amount</td></tr><tr><td>813</td><td>Over merchant daily velocity count</td></tr><tr><td>814</td><td>Over merchant daily velocity amount</td></tr><tr><td>815</td><td>Over merchant daily velocity both</td></tr><tr><td>816</td><td>Over merchant product velocity amount</td></tr><tr><td>817</td><td>Over merchant product velocity count</td></tr><tr><td>818</td><td>Over merchant product velocity both</td></tr><tr><td>819</td><td>Over chain daily velocity count</td></tr><tr><td>820</td><td>Over chain daily velocity amount</td></tr><tr><td>821</td><td>Over chain daily velocity both</td></tr><tr><td>822</td><td>Over chain product velocity count</td></tr><tr><td>823</td><td>Over chain product velocity both</td></tr><tr><td>824</td><td>Over chain product velocity amount</td></tr><tr><td>825</td><td>No chain ID for chain merchant</td></tr><tr><td>826</td><td>Signature required</td></tr><tr><td>827</td><td>Velocity exception error – pay inside</td></tr><tr><td>828</td><td>Exceeds merchant count for period – pay inside</td></tr><tr><td>829</td><td>Exceeds merchant amount for period – pay inside</td></tr><tr><td>830</td><td>Exceeds merchant count and amount for period – pay inside</td></tr><tr><td>831</td><td>Exceeds zip code count for period – pay inside</td></tr><tr><td>832</td><td>Exceeds zip code amount for period – pay inside</td></tr><tr><td>833</td><td>Exceeds zip code count and amount for period – pay inside</td></tr><tr><td>834</td><td>Exceeds state count for period – pay inside</td></tr><tr><td>835</td><td>Exceeds state amount for period – pay inside</td></tr><tr><td>836</td><td>Exceeds state count and amount for period – pay inside</td></tr><tr><td>837</td><td>Exceeds global count for period – pay inside</td></tr><tr><td>838</td><td>Exceeds global amount for period – pay inside</td></tr><tr><td>839</td><td>Exceeds global count and amount for period – pay inside</td></tr><tr><td>840</td><td>Unknown velocity error – pay inside</td></tr><tr><td>902</td><td><p>Invalid transaction. This merchant, card or terminal is not permitted to perform this transaction, or the transaction type is invalid, or Fiserv is unable to route a refund request to the network, or there is an issue with the xml message. </p><p></p><p>If a 902 is returned when submitting a completion for the second time, the first completion submitted has been successfully applied, even if the device did not receive a response in the first completion.</p></td></tr><tr><td>903</td><td>Invalid Reversal Transaction – transaction already settled</td></tr><tr><td>904</td><td>Format error.</td></tr><tr><td>905</td><td>Unsupported message. Transaction was rejected. Call your helpdesk or operations support.</td></tr><tr><td>906</td><td>System Error. There is a problem with the host processing system. Call your helpdesk or operations support.</td></tr><tr><td>907</td><td>Card issuer or switch inoperative or processor not available</td></tr><tr><td>908</td><td>Transaction destination not found for routing.</td></tr><tr><td>909</td><td>System malfunction or timeout</td></tr><tr><td>911</td><td>Card issuer timed out.</td></tr><tr><td>913</td><td>Duplicate transaction.</td></tr><tr><td>914</td><td>Void/Full Reversal request unable to process due to settlement already occurred. A Refund transaction may be necessary to reconcile the cardholder's account.</td></tr><tr><td>915</td><td>Timeout Reversal not supported. Resend the original transaction with the same Reference Number that timed out. Do not retry the timeout reversal</td></tr><tr><td>916</td><td>Void/Full Reversal request unable to process since the Original Authorization was not found.</td></tr><tr><td>920</td><td>Security H/W or S/W error – try again</td></tr><tr><td>921</td><td>Security H/W or S/W error – no action</td></tr><tr><td>923</td><td>Request in progress</td></tr><tr><td>924</td><td>Limit check failed</td></tr><tr><td>940</td><td>Error.</td></tr><tr><td>941</td><td>Invalid issuer.</td></tr><tr><td>942</td><td>Customer cancellation</td></tr><tr><td>944</td><td>Invalid response</td></tr><tr><td>950</td><td>Violation of business arrangement</td></tr><tr><td>954</td><td>CCV failed.</td></tr><tr><td>958</td><td>CCV2 failed</td></tr><tr><td>959</td><td>CAV failed</td></tr><tr><td>963</td><td>Acquirer channel unavailable</td></tr></tbody></table>

### Generating declines <a href="#generating-declines" id="generating-declines"></a>

When using the test cards below, transactions above $100.00 will receive a response with a specific decline code. The transaction amount sent in the transaction request message is used to determine which error response code will be received in your response.&#x20;

To request an error response code, the last three digits of the transaction amount should be the response code you wish to receive. For example, a transaction amount of $101.16 will return a response with the response code of 116.

<table><thead><tr><th>Card Brand</th><th>Number</th><th>CVV</th><th data-hidden></th></tr></thead><tbody><tr><td>Visa</td><td>4005571702222222</td><td>123</td><td></td></tr><tr><td>Pin Debit</td><td>4017779991113335 </td><td>123</td><td></td></tr><tr><td>MasterCard</td><td>5137221111116668</td><td>123</td><td></td></tr><tr><td>Discover</td><td>6011208701117775</td><td>123</td><td></td></tr><tr><td>American Express</td><td>371030089111338</td><td>1234</td><td></td></tr><tr><td>Diners Club</td><td>36185900011112</td><td>123</td><td></td></tr></tbody></table>

***

## Partial authorization <a href="#partial-authorization-test-data" id="partial-authorization-test-data"></a>

### Partial auth test cards <a href="#partial-authorization-test-data" id="partial-authorization-test-data"></a>

To test a partial authorization, use these cards and request values:

<table><thead><tr><th width="164">Card brand</th><th width="195">Card number</th><th width="104">EXP date</th><th width="67">CVV</th><th width="94">Request</th><th>Partial approval</th></tr></thead><tbody><tr><td><h3><img src="/files/KqLbqu8tEkA7X8ZKKMmq" alt=""></h3></td><td>6011 2087 0333 1119</td><td>12/28</td><td>-</td><td>$1169.10</td><td>$584.55</td></tr><tr><td><h3><img src="/files/4WAMdYKoy2zK810bs7gT" alt=""></h3></td><td>4005 5717 0222 2222</td><td>12/28</td><td> -</td><td>$612.64</td><td>$306.32</td></tr></tbody></table>

## Address Verification Services <a href="#address-verification-services" id="address-verification-services"></a>

To receive a FULL AVS AND CVV MATCH, please use the following address, zip code, card numbers and CVV:

**ADDRESS:** 1307 Broad Hollow Road\
**ZIP:** 11747

<table data-header-hidden data-full-width="false"><thead><tr><th width="134"></th><th width="146">Card brand</th><th width="211">Card Number</th><th>CVV</th></tr></thead><tbody><tr><td><img src="/files/4WAMdYKoy2zK810bs7gT" alt="" data-size="original"></td><td>Visa</td><td>4005 5200 0000 0939</td><td>123</td></tr><tr><td><img src="/files/NfuZ26NdM8pUWAI3vg6Q" alt="" data-size="original"></td><td>MasterCard</td><td>5405 0011 1111 1116</td><td>123</td></tr><tr><td><img src="/files/KqLbqu8tEkA7X8ZKKMmq" alt="" data-size="original"></td><td>Discover</td><td>6011 2087 0111 1117</td><td>123</td></tr><tr><td><img src="/files/WNacEG1cwaX2b9tiQ2mD" alt="" data-size="original"></td><td>Amex</td><td>3759 8765 4111 116</td><td>1234</td></tr></tbody></table>


# ACH Testing

Response code reference for ACH.

### Returned check codes <a href="#ach-return-codes" id="ach-return-codes"></a>

Number checks for status change on all *OPEN* ACH transactions daily. Once we detect a status change, we send a report to the merchant. The report shows settled and/or returned checks.&#x20;

Returned checks will show the below mentioned codes. Below table shows how to generate the return codes using the specified routing and account number in the testing environment.

<table><thead><tr><th width="90">Code</th><th width="208">Code description</th><th width="149">Routing</th><th>Account number</th></tr></thead><tbody><tr><td>R01</td><td>Insufficient funds</td><td>021000021</td><td>1234 5678 9012 3451</td></tr><tr><td>R09</td><td>Insufficient collected funds in account</td><td>021000021</td><td>1234 5678 9012 3452</td></tr><tr><td>R09</td><td>Insufficient collected funds in account</td><td>021000021</td><td>1234 5678 9012 3453</td></tr><tr><td>R02</td><td>Receiver's account is closed</td><td>021000021</td><td>1234 5678 9012 3454</td></tr><tr><td>R03</td><td>No account on file</td><td>021000021</td><td>1234 5678 9012 3455</td></tr><tr><td>R05</td><td>Unauthorized CCD</td><td>021000021</td><td>1234 5678 9012 3456</td></tr><tr><td>R07</td><td>ACH authorization has been revoked</td><td>021000021</td><td>1234 5678 9012 3457</td></tr><tr><td>L04</td><td>Refer to Maker ICL</td><td>021000021</td><td>1234 5678 9012 3458</td></tr><tr><td>L09</td><td>Unauthorized ICL</td><td>021000021</td><td>1234 5678 9012 3459</td></tr><tr><td>R01</td><td>Insufficient Funds</td><td>122000661</td><td>1234 5678 9012 3450</td></tr><tr><td>R09</td><td>Insufficient collected funds in account</td><td>122000661</td><td>1234 5678 9012 3451</td></tr><tr><td>R02</td><td>Receiver's account is closed</td><td>122000661</td><td>1234 5678 9012 3452</td></tr><tr><td>R05</td><td>Unauthorized CCD</td><td>122000661</td><td>1234 5678 9012 3453</td></tr><tr><td>L04</td><td>Refer to Maker ICL</td><td>122000661</td><td>1234 5678 9012 3454</td></tr><tr><td>L09</td><td>Unauthorized ICL</td><td>122000661</td><td>1234 5678 9012 3455</td></tr><tr><td>C01</td><td>Account number</td><td>122000661</td><td>1234 5678 9012 3456</td></tr><tr><td>R08</td><td>Payment on this item has been stopped</td><td>122000661</td><td>1234 5678 9012 3457</td></tr><tr><td>R01</td><td>Insufficient Funds</td><td>122000661</td><td>1234 5678 9012 3458</td></tr><tr><td>C03</td><td>Transit/Routing Number &#x26; Account Number</td><td>122000661</td><td>1234 5678 9012 3459</td></tr><tr><td>R01</td><td>Insufficient Funds</td><td>011100106</td><td>1234 5678 9012 3450</td></tr><tr><td>R09</td><td>Insufficient collected funds in account</td><td>011100106</td><td>1234 5678 9012 3451</td></tr><tr><td>R02</td><td>Receiver's account is closed</td><td>011100106</td><td>1234 5678 9012 3452</td></tr><tr><td>R05</td><td>Unauthorized CCD</td><td>011100106</td><td>1234 5678 9012 3453</td></tr><tr><td>L04</td><td>Refer to Maker ICL</td><td>011100106</td><td>1234 5678 9012 3454</td></tr><tr><td>L09</td><td>Unauthorized ICL</td><td>011100106</td><td>1234 5678 9012 3455</td></tr><tr><td>C01</td><td>Account number</td><td>011100106</td><td>1234 5678 9012 3456</td></tr><tr><td>R08</td><td>Payment on this item has been stopped</td><td>011100106</td><td>1234 5678 9012 3457</td></tr><tr><td>R01</td><td>Insufficient Funds</td><td>011100106</td><td>1234 5678 9012 3458</td></tr><tr><td>C03</td><td>Transit/Routing Number &#x26; Account Number</td><td>011100106</td><td>1234 5678 9012 3459</td></tr></tbody></table>

***

### Complete list of return codes

Below you'll find a reference list to every possible return code value.

<table><thead><tr><th width="523">Return Description</th><th width="226">Return Code</th></tr></thead><tbody><tr><td>Incorrect bank account number</td><td>C01</td></tr><tr><td>Incorrect transit/routing number</td><td>C02</td></tr><tr><td>Incorrect transit/routing number and bank account number</td><td>C03</td></tr><tr><td>Bank account name change</td><td>C04</td></tr><tr><td>Incorrect payment code</td><td>C05</td></tr><tr><td>Incorrect bank account number and transit code</td><td>C06</td></tr><tr><td>Incorrect transit/routing number, bank account number and payment code</td><td>C07</td></tr><tr><td>Incorrect individual ID number</td><td>C09</td></tr><tr><td>Incorrect company name</td><td>C10</td></tr><tr><td>Incorrect company identification</td><td>C11</td></tr><tr><td>Incorrect company name and company ID</td><td>C12</td></tr><tr><td>Fraudulent ICL</td><td>L06</td></tr><tr><td>ICL Hold</td><td>L07</td></tr><tr><td>ICL Other</td><td>L08</td></tr><tr><td>Unauthorized ICL</td><td>L09</td></tr><tr><td>Non-Negotiable Item</td><td>L88</td></tr><tr><td>Other</td><td>L99</td></tr><tr><td>Insufficient funds</td><td>R01</td></tr><tr><td>Receiver's account is closed</td><td>R02</td></tr><tr><td>No account on file</td><td>R03</td></tr><tr><td>Invalid account number</td><td>R04</td></tr><tr><td>Unauthorized CCD</td><td>R05</td></tr><tr><td>Returned at bank's request</td><td>R06</td></tr><tr><td>ACH authorization has been revoked</td><td>R07</td></tr><tr><td>Payment on this item has been stopped</td><td>R08</td></tr><tr><td>Insufficient collected funds in account</td><td>R09</td></tr><tr><td>Customer advises not authorized</td><td>R10</td></tr><tr><td>Check truncation return (specify)</td><td>R11</td></tr><tr><td>Branch sold to another financial institution</td><td>R12</td></tr><tr><td>RDFI is not an ACH member(If this was a check by p</td><td>R13</td></tr><tr><td>Representative payee deceased or no longer able to</td><td>R14</td></tr><tr><td>Beneficiary or account holder other than represent</td><td>R15</td></tr><tr><td>Account funds have been frozen</td><td>R16</td></tr><tr><td>Item returned because of invalid data</td><td>R17</td></tr><tr><td>Improper effective date</td><td>R18</td></tr><tr><td>Amount field error</td><td>R19</td></tr><tr><td>Non-transaction account</td><td>R20</td></tr><tr><td>Invalid company identification</td><td>R21</td></tr><tr><td>Invalid individual ID number</td><td>R22</td></tr><tr><td>Payment refused by biller</td><td>R23</td></tr><tr><td>Duplicate entry</td><td>R24</td></tr><tr><td>Addenda record error</td><td>R25</td></tr><tr><td>Mandatory field error</td><td>R26</td></tr><tr><td>Trace number error</td><td>R27</td></tr><tr><td>Routing/transit number check digit error</td><td>R28</td></tr><tr><td>Corporate customer advises not authorized</td><td>R29</td></tr><tr><td>Receiver not participant in check truncation program</td><td>R30</td></tr><tr><td>Permissible return entry</td><td>R31</td></tr><tr><td>RDFI non-settlement</td><td>R32</td></tr><tr><td>Return of item</td><td>R33</td></tr><tr><td>Limited participation ODFI</td><td>R34</td></tr><tr><td>Return of improper debit entry</td><td>R35</td></tr><tr><td>Return of improper credit entry</td><td>R36</td></tr><tr><td>Source Presented for Payment</td><td>R37</td></tr><tr><td>Stop payment on source document</td><td>R38</td></tr><tr><td>Improper Source Document</td><td>R39</td></tr><tr><td>Return of item by government agency</td><td>R40</td></tr><tr><td>Invalid tansaction code</td><td>R41</td></tr><tr><td>Routing/transit number check digit error</td><td>R42</td></tr><tr><td>Invalid account number</td><td>R43</td></tr><tr><td>Invalid individual ID</td><td>R44</td></tr><tr><td>Invalid individual name or company name</td><td>R45</td></tr><tr><td>Invalid representative payee indicator code</td><td>R46</td></tr><tr><td>Duplicate enrollment</td><td>R47</td></tr><tr><td>Reserved</td><td>R49</td></tr><tr><td>State law affecting RCK acceptance</td><td>R50</td></tr><tr><td>Item is ineligible</td><td>R51</td></tr><tr><td>Stop payment on item</td><td>R52</td></tr><tr><td>Item and A.C.H. Entry Presented for Payment</td><td>R53</td></tr><tr><td>Misrouted return</td><td>R61</td></tr><tr><td>Incorrect trace number</td><td>R62</td></tr><tr><td>Incorrect dollar amount</td><td>R63</td></tr><tr><td>Incorrect individual identification</td><td>R64</td></tr><tr><td>Incorrect tranaction code</td><td>R65</td></tr><tr><td>Incorrect company identification</td><td>R66</td></tr><tr><td>Duplicate return</td><td>R67</td></tr><tr><td>Untimely return</td><td>R68</td></tr><tr><td>Multiple error return - return contains multiple errors</td><td>R69</td></tr><tr><td>Permissible return entry not accepted</td><td>R70</td></tr><tr><td>Misrouted dishonored return</td><td>R71</td></tr><tr><td>Untimely return</td><td>R72</td></tr><tr><td>Timely original return</td><td>R73</td></tr><tr><td>Corrected return</td><td>R74</td></tr><tr><td>Cross-border payment coding error</td><td>R80</td></tr><tr><td>Non-participant in cross-border program</td><td>R81</td></tr><tr><td>Invalid foreign receiving depository financial institution</td><td>R82</td></tr><tr><td>Foreign receiving depository financial institution</td><td>R83</td></tr><tr><td>Indicates a returned PAC (pre-authorized check)</td><td>R98</td></tr><tr><td>Indicates a returned PAC (pre-authorized check)</td><td>R99</td></tr><tr><td>Other</td><td>RCC</td></tr></tbody></table>

\
\ <br>


# Resources

<figure><img src="/files/Gp75unP7Q4aL4dDgbNIn" alt=""><figcaption></figcaption></figure>

Here are the articles in this section:

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Tools and Downloads ></strong></td><td><a href="/pages/1SjXE7n2Pt9oWxISzJrh">/pages/1SjXE7n2Pt9oWxISzJrh</a></td></tr><tr><td><strong>Vocabulary ></strong></td><td><a href="/pages/cJyaPgdvNa7TmZtu3pDR">/pages/cJyaPgdvNa7TmZtu3pDR</a></td></tr><tr><td><strong>Querying ></strong></td><td><a href="/pages/Kr6dE0Iz5bFlxuBjqrbN">/pages/Kr6dE0Iz5bFlxuBjqrbN</a></td></tr><tr><td><strong>Error Codes ></strong></td><td><a href="/pages/jLZ7w3f9CXbblhtFzytG">/pages/jLZ7w3f9CXbblhtFzytG</a></td></tr><tr><td><strong>Software Requirements ></strong></td><td><a href="/pages/ncD5psnhxiDcVfAaUZMG">/pages/ncD5psnhxiDcVfAaUZMG</a></td></tr></tbody></table>


# Tools and Downloads

Compilation of all tools and downloads from the documentation

## API

All links and downloads for the REST API.

### REST API downloads

## Mobile SDK

All links and downloads for the mobile SDKs.

***

## Payment widgets

All links and downloads for the PayForm and the legacy widget.

### PayForm links

### Widget links

***

## Verifone

All links and downloads for the Verifone card reader:

### Verifone service for browser implementation

[Verifone Middleware Installer](https://easypay1.com/deploy/MiddleWare/EPVerifoneSetup_E2E_1041.zip)

### Verifone example web site&#x20;

[Sample Verifone Website](https://easypay1.com/JqueryVerifone/)

[Sample Verifone Website Content](https://easypay1.com/docs/jquery_verifone.zip)

### Verifone SDK reference

[USB drivers and Logging Package](https://easypay1.com/deploy/SetupVerifoneDrivers/Setup_USB_log_win11.zip)

[SDK Interface](https://easypay1.com/deploy/VerifoneSDK/EP.Enterprise.Vx820Lib2.zip)

### Verifone Sample for SDK

[Sample Program Executable](https://easypay1.com/Deploy/VerifoneSDK/WinFrm.zip)

[Sample Program Source Code](https://easypay1.com/Deploy/VerifoneSDK/SourceCode_WinFrm.zip)

***

## Virtual Terminal

All links and downloads for the Virtual Terminal.

{% embed url="<https://easypay5.com/reset>" %}
VT terminal reset
{% endembed %}


# Vocabulary

A glossary of key payment terms and terms specific to Number

### Payment terms

A general list of terms specific to the payment industry.

#### A

* **Authorizing payments**: The process of verifying cardholder information and checking funds to securely approve transactions.

#### C

* **Card present**: Transactions where the physical card is present during the payment process, typically requiring a card reader.
* **Consent**: Permission granted by the customer to store their card information for future transactions.
* **Crediting (refunds)**: The return of funds to a customer's account after a transaction has been completed, typically occurring when a product is returned or a charge is disputed.

#### I

* **ISVs (Independent Software Vendors)**: Companies that develop software applications that may integrate with payment processing services.

#### M

* **Manual entry (card not-present)**: The process of accepting payments by manually entering card details.
* **Merchants**: Businesses or individuals that sell goods or services and accept payments from customers.

#### P

* **PayFac (Payment Facilitator)**: A service provider that allows merchants to accept payments without needing to establish a direct relationship with a payment processor.
* **Payment processor**: A company that handles transactions between the merchant and the customer's bank, facilitating payment processing.

#### R

* **Recurring payments (payment plans)**: Automated scheduling of regular payments over time, ideal for subscriptions or installment plans.
* **Reporting**: The generation of summaries and analyses of transaction data to help merchants track financial activities and manage cash flow.

#### S

* **SaaS providers**: Companies that offer software solutions delivered over the Internet, often including payment processing functionalities.
* **Settlements**: The finalization of a transaction by transferring funds from the buyer to the seller.
* **Store card on file**: The secure storage of a customer's card details for future transactions, often requiring annual consent.
* **Surcharge payments**: An extra fee added to the transaction amount by businesses.

#### V

* **Verifone**: A brand of payment terminals and devices used for processing card present transactions.
* **Void (reversal)**: This act will cancel a previously approved authorization prior to nightly settlement

***

### Number terms

A list of terms specific to Number services or other terms in context of Number services..

#### A

* **Account code**: The unique key which represents your Number account. This code will never change throughout the life of your account. Each Account Code is 2 letters and 7 numbers.

#### C

* **Client Admin Portal**: A web interface for managing Virtual Terminal users and API tokens, allowing administrators to create, modify, and remove user accounts while ensuring secure access through two-factor authentication.

#### L

* **Lockouts**: A lock caused by entering incorrect password or username 6 times in a row when attempting to authenticate. Depending on the source and type of the lockout, a single Virtual Terminal user might be locked out or everyone in your office.

#### M

* **MID (Merchant ID)**: Each Number account can support multiple merchant records, each with their unique identifier. Each record can be a separate location center which will generate a separate daily settlement report.

#### P

* **PayForm**: A modern tool for securely collecting cardholder data, allowing customization and real-time updates to your system.

#### S

* **Session key**: A unique key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.&#x20;

#### T

* **Token**: A 32-characater hexadecimal string generated from the Client Admin Portal which acts as a password when authenticating to our APIs. Tokens expire after a 2 year period and can be renewed from the Client Admin Portal.

#### V

* **Virtual Terminal**: A web application that provides various credit card processing functionalities, including authorizations, voids, credits, and reporting.

#### W

* **Widget 3DES encryption key**: Encryption key used in conjunction with 3DES cryptography to encrypt data for use in our web widgets. Each integrator is assigned a unique key and an index.&#x20;
* **Widget AES encryption key**: Encryption key used in conjunction with AES cryptography to encrypt data for use in our web widgets. Each integrator is assigned a unique key and an index.&#x20;


# Querying

Reference to the Number query language

### Introduction

Number provides a robust query language for filtering specific records using the APIs.&#x20;

#### Example

To return all settled transaction records created in June 2024, you can use the query below:

```sql
(A=1)&&(C>='6/1/2024')&&(C<'7/1/2024')&&(B=2)
```

#### Format

Queries in the Number query language consist of the following:

{% stepper %}
{% step %}

#### Filters and values

Each letter represents a query parameter (filter). You can follow it up by&#x20;

* an equal sign "=" for equality comparison,
* ">", ">=", "<", and "<=" for comparison of numeric values and dates,
* the "*LIKE*" keyword for SQL-like string comparison.

**Use single quotes for text and date values.**&#x20;
{% endstep %}

{% step %}

#### Logical operators

You can build and join logical terms with two ampersand characters "&&" for **logical AND** or two pipe characters "||" for **logical OR**.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
Refer to the variable charts below or the API reference for query composition. They list and describe all of the query parameters that you can use in each scenario.
{% endhint %}

***

### Reconciliation

Reconciliation is the process of ensuring that the transaction records in your system match those in the Number database. **This is important for maintaining accurate financial records and can be done periodically, such as once a day or week.**

When using Number's widgets, it may be desirable to perform periodic reconciliation. A typical reconciliation query might include specific parameters to filter records based on criteria like merchant ID, transaction status, and date range to avoid excessive data retrieval, which could lead to errors.

{% hint style="info" %}
For effective reconciliation, it is recommended to periodically query the database and utilize webhooks for real-time notifications to keep your records up to date .
{% endhint %}

#### Example

Here is a typical Reconciliation query

```sql
(A=2)&&(U='WID')&&(C>='6/1/2024')&&((B=1)||(B=2))
```

* `(A=2)` is used to return records created under merchant record 2
* `(U='WID')` is used to pull records with an `ORIGIN` of widget
* `(C>='6/1/2024')` is a date range to avoid returning an exceessive records&#x20;
* `((B=1)||(B=2))` is used to pull back *OPEN* or *SETTLED* transactions

***

### Transaction query

Obtain specific transaction records using Number's query language.&#x20;

{% code title="Query example" overflow="wrap" %}

```sql
(G=1)&&(B>'10/20/2024')
```

{% endcode %}

<table><thead><tr><th width="114">Variable</th><th width="153">Parameter</th><th>Description</th></tr></thead><tbody><tr><td>A</td><td>MERCHANT ID</td><td>The merchant record you are interested in, e.g. <code>(A=1)</code>.</td></tr><tr><td>B</td><td>TRANSACTION STATUS</td><td>The status of the transaction, e.g. <code>(B=1)</code>. <br><br>* -1: <em>ALL</em> <br>* 1: <em>OPEN</em> <br>* 2: <em>SETTLED</em> <br>* 3: <em>FAILED</em> <br>* 4: <em>LOCKED</em> <br>* 5: <em>VOID</em></td></tr><tr><td>C</td><td>DATE CREATED</td><td>The date the transaction was created, e.g. <code>(C>='7/5/2024 12:00:00 AM')</code>.</td></tr><tr><td>D</td><td>LAST NAME</td><td>Last name of the account holder, e.g. <code>(D LIKE '%MITH')</code> for all names that end with '<em>MITH</em>'.</td></tr><tr><td>E</td><td>TRANSACTION LOCK</td><td>Lock status of the transaction, e.g. <code>(E&#x3C;>'0')</code> for locked transactions.</td></tr><tr><td>F</td><td>BATCH LOG ID</td><td>Reference to a batch settlement record, e.g. <code>(F=817)</code>.</td></tr><tr><td>H</td><td>TRANSACTION ID</td><td>The unique identifier for the transaction, e.g. <code>(H=58258)</code>.</td></tr><tr><td>J</td><td>FIRST NAME</td><td>First name of the account holder, e.g. <code>(J LIKE 'ROB%')</code> for all names that start with '<em>ROB</em>'.</td></tr><tr><td>K</td><td>TRANSACTION TYPE</td><td>The type of transaction, e.g. <code>(K=-1)</code>. <br><br>* -1: <em>ALL</em> <br>* 1: <em>CCAUTHONLY</em> <br>* 2: <em>CCSALE</em> <br>* 3: <em>CCFORCE</em> <br>* 4: <em>CCVOICE</em> <br>* 5: <em>CCADJUST</em> <br>* 6: <em>CCCREDIT</em></td></tr><tr><td>L</td><td>AMOUNT</td><td>The $ amount of the transaction, e.g. <code>(L>100.00)</code>.</td></tr><tr><td>M</td><td>CLIENT REFERENCE ID (PATIENT ID)</td><td>User-defined value on the transaction.</td></tr><tr><td>N</td><td>RPGUID</td><td>User-defined value on the transaction.</td></tr><tr><td>P</td><td>CONSENT ID</td><td>The consent ID of card on file the transactions were charged against, e.g. <code>(P=15875)</code>.</td></tr><tr><td>Q</td><td>CREDIT CARD LAST 4</td><td>The last 4 digits of a credit card, e.g. <code>(Q='4123')</code>.</td></tr><tr><td>R</td><td>APPROVAL CODE</td><td>The approval code for the transaction, e.g. <code>(R='TAS626')</code>.</td></tr><tr><td>S</td><td>CUSTOMER LAST NAME</td><td>The last name of the customer, e.g. <code>(S='SMITH')</code>.</td></tr><tr><td>T</td><td>CUSTOMER FIRST NAME</td><td>The first name of the customer, e.g. <code>(T='FOSTER')</code>.</td></tr><tr><td>U</td><td>ORIGIN</td><td>The origin of the transaction, e.g. <code>(U='API')</code>. <br><br>* "<em>API</em>": REST API <br>* "<em>WID</em>": Widget <br>* "<em>VT</em>": Virtual Terminal <br>* "<em>MOBL</em>": Mobile SDK <br>* "<em>SDK</em>": Verifone <br>* "<em>AUTO</em>": Automatically scheduled from a payment plan</td></tr><tr><td>W</td><td>BATCH NUMBER</td><td>The batch number for the batch settlement, e.g. <code>(W=762)</code>.</td></tr></tbody></table>

***

### Consent query

Obtain specific consent records using Number's query language

{% code title="Query example" overflow="wrap" %}

```sql
(G=1)&&(B>'10/20/2024')
```

{% endcode %}

<table><thead><tr><th width="113">Variable</th><th width="154">Parameter</th><th>Description</th></tr></thead><tbody><tr><td>A</td><td>MERCHANT ID</td><td>The merchant record you are interested in, e.g. <code>(A=1)</code>.</td></tr><tr><td>B</td><td>START DATE</td><td>The date the consent becomes active, e.g. <code>(B>='10/20/2024')</code>.</td></tr><tr><td>C</td><td>END DATE</td><td>The date the consent expires, e.g. <code>(C&#x3C;='10/20/2024')</code>.</td></tr><tr><td>D</td><td>ACCOUNT HOLDER LAST NAME</td><td>Last name of the account holder, e.g. <code>(D LIKE '%MITH')</code> for all names that end with '<em>MITH</em>'.</td></tr><tr><td>E</td><td>CREATED ON</td><td>The date the consent was created, e.g. <code>(E&#x3C;='10/20/2024')</code>.</td></tr><tr><td>F</td><td>CUSTOMER REFERENCE ID (PATIENT ID)</td><td>User-defined value on the consent.</td></tr><tr><td>G</td><td>CONSENT TYPE</td><td>The type of consent, e.g. <code>(G='-1')</code>. <br><br>* -1: <em>ALL</em> <br>* 1: <em>ANNUAL</em> <br>* 2: <em>ONE-TIME</em> <br>* 3: <em>RECURRING</em> <br>* 4: <em>SUBSCRIPTION</em></td></tr><tr><td>H</td><td>ENABLED</td><td>Indicates whether the consent is currently enabled, e.g. <code>(H=1)</code>.</td></tr><tr><td>J</td><td>RPGUID</td><td>User-defined value on the consent.</td></tr><tr><td>K</td><td>ACCOUNT HOLDER FIRST NAME</td><td>First name of the account holder, e.g. <code>(K LIKE 'ROB%')</code> for all names that start with '<em>ROB</em>'.</td></tr><tr><td>Z</td><td>CONSENT ID</td><td>The unique identifier for the consent, e.g. <code>(Z=15875)</code>.</td></tr></tbody></table>

***

### Recurring schedule query <a href="#recurring-schedule-query" id="recurring-schedule-query"></a>

Obtain specific recurring schedule records using Number's query language.

{% code title="Query example" overflow="wrap" %}

```sql
(H=3)&&(C>='10/20/2024')
```

{% endcode %}

<table><thead><tr><th width="111">Variable</th><th width="146">Parameter</th><th>Description</th></tr></thead><tbody><tr><td>A</td><td>CONSENT ID</td><td>The unique identifier for the consent associated with the recurring schedule, e.g. <code>(A=545)</code>.</td></tr><tr><td>B</td><td>STATUS</td><td>The status of the recurring schedule, e.g. <code>(B=-1)</code>. <br><br>* -1: <em>ALL</em> <br>* 1: <em>SCHEDULED</em> <br>* 2: <em>PAID</em> <br>* 3: <em>FAILED</em> <br>* 4: <em>CANCELLED</em></td></tr><tr><td>C</td><td>DUE DATE</td><td>The date the next payment is due, e.g. <code>(C='10/20/2024')</code>.</td></tr><tr><td>D</td><td>ACCOUNT HOLDER LAST NAME</td><td>Last name of the account holder, e.g. <code>(D LIKE '%MITH')</code> for all names that end with '<em>MITH</em>'.</td></tr><tr><td>E</td><td>MERCHANT ID</td><td>The unique identifier for the merchant associated with the recurring schedule, e.g. <code>(E=1)</code>.</td></tr><tr><td>F</td><td>ACCOUNT NUMBER LAST 4</td><td>The last 4 digits of the account number associated with the recurring schedule, e.g. <code>(F='1234')</code>.</td></tr><tr><td>G</td><td>SCHEDULE ID</td><td>The unique identifier for the recurring schedule, e.g. <code>(G=12)</code>.</td></tr><tr><td>H</td><td>TYPE</td><td>The type of recurring schedule, e.g. <code>(H=-1)</code>. <br><br>* -1: <em>ALL</em> <br>* 3: <em>RECURRING</em> <br>* 4: <em>SUBSCRIPTION</em></td></tr></tbody></table>

***

### Batch log query <a href="#batch-log-query" id="batch-log-query"></a>

Obtain specific batch log records using Number's query language.

<table><thead><tr><th width="114">Variable</th><th width="159">Parameter</th><th>Description</th></tr></thead><tbody><tr><td>A</td><td>MERCHANT ID</td><td>The merchant record you are interested in, e.g. <code>(A=545)</code>.</td></tr><tr><td>B</td><td>STATUS</td><td>The status of the batch log, e.g. <code>(B=-1)</code>. <br><br>* -1: <em>ALL</em> <br>* 1: <em>FAILED</em> <br>* 2: <em>APPROVED</em></td></tr><tr><td>C</td><td>CREATED ON</td><td>The date the batch log was created, e.g. <code>(C>='3/2/2024')&#x26;&#x26;(C&#x3C;='4/2/2024')</code>.</td></tr><tr><td>D</td><td>BATCH LOG ID</td><td>The unique identifier for the batch log, e.g. <code>(D=1777)</code>.</td></tr><tr><td>E</td><td>BATCH NUMBER</td><td>The batch number for the batch log, e.g. <code>(E=185)</code>.</td></tr></tbody></table>


# Error Codes

Links to error code reference

## Transaction response codes

When using our services, you might end up with a transaction that was declined. This is usually signaled by a response with a `TxApproved` value of false and a decline code in the `ErrCode` field. You can then display the `RespMsg` to the user to explain the error.

If you want to be able to tell when a specific type of error occurs, you can use our decline code reference and handle them accordingly.

### Global Payments decline codes

These codes are used when processing transactions through the Global Payments system. For Global Payments transaction decline codes, see[Global Payments Testing](/documentation/testing/global-payments-testing#decline-codes).

### First Data decline codes

These codes are relevant when dealing with transactions processed by First Data. For First Data transaction decline codes, see [First Data Testing](/documentation/testing/first-data-testing#response-codes).

### ACH decline codes

These codes are specifically for Automated Clearing House (ACH) transactions. For ACH decline codes, see [ACH Testing](/documentation/testing/ach-testing#complete-list-of-return-codes).


# Software Requirements

Minimum software requirements for running Number services

Number software is a collection of lightweight software products that can be customized to run on most platforms with minimal resource requirements. Although Number has a solution for most platforms, we do recommend the following requirements to run our products efficiently.

### Computer specifications <a href="#recommend-computer-specifications" id="recommend-computer-specifications"></a>

Processor minimum: Intel i5 Gen 5 and AMD Ryzen 5\
RAM minimum: 8GB (4GB free)

### Operating systems <a href="#operating-systems" id="operating-systems"></a>

* Microsoft Windows 8.1+
* MacOS Sierra 10.12+

### Browsers <a href="#browsers" id="browsers"></a>

* Microsoft Edge v122.00+
* Google Chrome v122.0.626.1.111+
* Mozilla Firefox v123.01+
* Safari version v17.3.1+


# REST API

The API reference for the REST API

<figure><img src="/files/rCdzeSocro3YzSDJ3apg" alt=""><figcaption></figcaption></figure>

Our REST API can be used to integrate any frontend or backend application with Number and use all of our payment services. This way, you have full control over the presentation, and we'll handle the complex payment processes.\
\
We recommend following [our REST API integration guide](/documentation/getting-started/integration-options/rest-api) to get started. It'll teach you all of the generic concepts you need to correctly authenticate, consume API responses, and how to recognize and handle errors, alongside code examples.


# Authentication

Authenticate user and retrieve session key

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/Authenticate>

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "AcctCode": "EP911XXXX",
  "Token": "2148B239CF6846BDA5D141BF4A4CFBE8"
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "AuthenticateResult": {
    "AuthSuccess": true,
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "MerchantList": [
      {
        "Address": "45 spring street portland Maine 04101",
        "Descrip": "Test Merchant 1",
        "ID": 1,
        "Location": "Test Merchant 1",
        "TermID": "006"
      }
    ],
    "RespMsg": "SessKey Expires|4/18/2019 7:29:47 AM",
    "SessKey": "B9F24903C3BA4770AE303032303541303032353437",
    "ThisUser": {
      "APILocationID": 2210,
      "AccountCode": "EP9116875",
      "AcctID": 205,
      "Alias": "vidya_Venkatraman",
      "CreatedBy": "ADMIN : vidya Venkatraman",
      "DateCreated": "2024-12-01T11:19:01.000Z",
      "DateModified": "2024-12-01T11:19:01.000Z",
      "Description": "EP DEV ACCT",
      "ExpirationDate": "2024-12-01T11:19:01.000Z",
      "ID": 2547,
      "IsExpired": false,
      "IsLockedOut": false,
      "TokenDescription": "EP DEV ACCT"
    }
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**AcctCode** string <mark style="color:purple;">optional</mark>

Account code that never changes

Example: `EP911XXXX`

***

**Token** string <mark style="color:purple;">optional</mark>

Token that expires every 2 years

Example: `2148B239CF6846BDA5D141BF4A4CFBE8`
{% endtab %}
{% endtabs %}


# ACH

{% columns %}
{% column %}
{% content-ref url="/pages/KnNvUL41EFvwA48I3eqY" %}
[Create an ACH Sale](/api-reference/rest-api/ach/create-an-ach-sale)
{% endcontent-ref %}

{% content-ref url="/pages/4MzYgFnjmiP0j8KfkC2g" %}
[Apply credit to an ACH transaction](/api-reference/rest-api/ach/apply-credit-to-an-ach-transaction)
{% endcontent-ref %}

{% content-ref url="/pages/B2qEwUlTQoiRMrzHvltd" %}
[Void an ACH transaction](/api-reference/rest-api/ach/void-an-ach-transaction)
{% endcontent-ref %}
{% endcolumn %}

{% column %}
{% content-ref url="/pages/TyMmyJmaqjfepO6mmHey" %}
[Create an ACH Combo Sale and Consent](/api-reference/rest-api/ach/create-an-ach-combo-sale-and-consent)
{% endcontent-ref %}

{% content-ref url="/pages/ge1yGeJ8KhGOlDJm7WDT" %}
[Process payment with ACH annual consent](/api-reference/rest-api/ach/process-payment-with-ach-annual-consent)
{% endcontent-ref %}
{% endcolumn %}
{% endcolumns %}


# Create an ACH Sale

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/ACH/Sale>

**For member variable "AccountType" use the following values:**

1. Personal Checking = 1
2. Personal Saving = 2
3. Business Checking = 3
4. Business Saving = 4

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "ChargeDetails": {
    "AccountNumber": "878460000256",
    "RoutingNumber": "211274515",
    "Amount": 10.25,
    "AccountType": 1
  },
  "AcctHolder": {
    "Firstname": "Sally",
    "Lastname": "Smith",
    "Company": "",
    "Title": "",
    "Url": "",
    "BillIngAdress": {
      "Address1": "123 Test Road",
      "Address2": "",
      "City": "Portland",
      "State": "ME",
      "ZIP": "04005",
      "Country": "USA"
    },
    "Email": "testing@easypaysolutions.com",
    "Phone": "8775558472"
  },
  "EndCustomer": {
    "Firstname": "Sally",
    "Lastname": "Smith",
    "Company": "",
    "Title": "",
    "Url": "",
    "BillIngAdress": {
      "Address1": "123 Test Road",
      "Address2": "",
      "City": "Portland",
      "State": "ME",
      "ZIP": "04005",
      "Country": "USA"
    },
    "Email": "testing@easypaysolutions.com",
    "Phone": "8775558472"
  },
  "PurchItems": {
    "ServiceDescrip": "FROM API TESTER",
    "ClientRefID": "12456AA",
    "RPGUID": "3d3424a6-c5f3-4c28"
  },
  "MerchID": 1
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ACHTransactionResult": {
    "AuthID": "69017501",
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "RespMsg": "TxID 1381 Approved",
    "TxApproved": true,
    "TxID": 1381,
    "uniqueTranID": "16790131F349BCBA"
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**ChargeDetails** object <mark style="color:purple;">optional</mark>

> **AccountNumber** string <mark style="color:purple;">optional</mark>
>
> The account number associated with the bank account from which funds will be withdrawn.
>
> Example: `878460000256`
>
> ***
>
> **RoutingNumber** string <mark style="color:purple;">optional</mark>
>
> The routing number of the bank, used to identify the financial institution for the transaction.
>
> Example: `211274515`
>
> ***
>
> **Amount** number · float <mark style="color:purple;">optional</mark>
>
> The $ amount to be charged, specified in decimal format.
>
> Example: `10.25`
>
> ***
>
> **AccountType** integer · enum <mark style="color:purple;">optional</mark>
>
> The type of bank account. Possible values are:
>
> * 1: Personal Checking.
> * 2: Personal Saving.
> * 3: Business Checking.
> * 4: Business Saving.

**AcctHolder** object <mark style="color:purple;">optional</mark>

> **Firstname** string <mark style="color:purple;">optional</mark>
>
> Example: `Sally`
>
> ***
>
> **Lastname** string <mark style="color:purple;">optional</mark>
>
> Example: `APIACH`
>
> ***
>
> **Company** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **Title** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **Url** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **BillIngAdress** object <mark style="color:purple;">optional</mark>
>
> ***
>
> **Email** string <mark style="color:purple;">optional</mark>
>
> Example: `testing@easypaysolutions.com`
>
> ***
>
> **Phone** string <mark style="color:purple;">optional</mark>
>
> Example: `8775558472`

**EndCustomer** object <mark style="color:purple;">optional</mark>

> **Firstname** string <mark style="color:purple;">optional</mark>
>
> Example: `Sally`
>
> ***
>
> **Lastname** string <mark style="color:purple;">optional</mark>
>
> Example: `APIACH`
>
> ***
>
> **Company** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **Title** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **Url** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **BillIngAdress** object <mark style="color:purple;">optional</mark>
>
> ***
>
> **Email** string <mark style="color:purple;">optional</mark>
>
> Example: `testing@easypaysolutions.com`
>
> ***
>
> **Phone** string <mark style="color:purple;">optional</mark>
>
> Example: `8775558472`

**PurchItems** object <mark style="color:purple;">optional</mark>

> **ServiceDescrip** string <mark style="color:purple;">optional</mark>
>
> A description of the service or item.
>
> Example: `FROM API TESTER`
>
> ***
>
> **ClientRefID** string <mark style="color:purple;">optional</mark>
>
> A reference ID provided by the client for tracking purposes.
>
> Example: `12456AA`
>
> ***
>
> **RPGUID** string <mark style="color:purple;">optional</mark>
>
> A custom, user-defined reference ID or value.
>
> Example: `adf98580-b4ab-42fc-bb99-01c89964afe9`

**MerchID** integer <mark style="color:purple;">optional</mark>

Example: `1`
{% endtab %}
{% endtabs %}


# Create an ACH Combo Sale and Consent

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/ACH/Combo>

This method creates both an ACH sale and consent. To create a consent only without processing the sale, set the Amount to zero.

**For member variable "AccountType" use the following values:**

1. Personal Checking = 1
2. Personal Saving = 2
3. Business Checking = 3
4. Business Saving = 4

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "ChargeDetails": {
    "AccountNumber": "878460000256",
    "RoutingNumber": "211274515",
    "Amount": 10.25,
    "AccountType": 1
  },
  "AcctHolder": {
    "Firstname": "Sally",
    "Lastname": "Smith",
    "Company": "",
    "Title": "",
    "Url": "",
    "BillIngAdress": {
      "Address1": "123 Test Road",
      "Address2": "",
      "City": "Portland",
      "State": "ME",
      "ZIP": "04005",
      "Country": "USA"
    },
    "Email": "testing@easypaysolutions.com",
    "Phone": "8775558472"
  },
  "EndCustomer": {
    "Firstname": "Sally",
    "Lastname": "Smith",
    "Company": "",
    "Title": "",
    "Url": "",
    "BillIngAdress": {
      "Address1": "123 Test Road",
      "Address2": "",
      "City": "Portland",
      "State": "ME",
      "ZIP": "04005",
      "Country": "USA"
    },
    "Email": "testing@easypaysolutions.com",
    "Phone": "8775558472"
  },
  "PurchItems": {
    "ServiceDescrip": "FROM API TESTER",
    "ClientRefID": "12456AA",
    "RPGUID": "3d3424a6-c5f3-4c28"
  },
  "MerchID": 1
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ACHTransaction_ComboResult": {
    "AuthID": "69017501",
    "ConsentID": 1247,
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "RespMsg": "TxID 1381 Approved and ConsentID 1247 Created",
    "TxApproved": true,
    "TxID": 1381,
    "uniqueTranID": "16790131F349BCBA"
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**ChargeDetails** object <mark style="color:purple;">optional</mark>

> **AccountNumber** string <mark style="color:purple;">optional</mark>
>
> The account number associated with the bank account from which funds will be withdrawn.
>
> Example: `878460000256`
>
> ***
>
> **RoutingNumber** string <mark style="color:purple;">optional</mark>
>
> The routing number of the bank, used to identify the financial institution for the transaction.
>
> Example: `211274515`
>
> ***
>
> **Amount** number · float <mark style="color:purple;">optional</mark>
>
> The $ amount to be charged, specified in decimal format.
>
> Example: `10.25`
>
> ***
>
> **AccountType** integer · enum <mark style="color:purple;">optional</mark>
>
> The type of bank account. Possible values are:
>
> * 1: Personal Checking.
> * 2: Personal Saving.
> * 3: Business Checking.
> * 4: Business Saving.

**AcctHolder** object <mark style="color:purple;">optional</mark>

> **Firstname** string <mark style="color:purple;">optional</mark>
>
> Example: `Sally`
>
> ***
>
> **Lastname** string <mark style="color:purple;">optional</mark>
>
> Example: `APIACH`
>
> ***
>
> **Company** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **Title** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **Url** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **BillIngAdress** object <mark style="color:purple;">optional</mark>
>
> ***
>
> **Email** string <mark style="color:purple;">optional</mark>
>
> Example: `testing@easypaysolutions.com`
>
> ***
>
> **Phone** string <mark style="color:purple;">optional</mark>
>
> Example: `8775558472`

**EndCustomer** object <mark style="color:purple;">optional</mark>

> **Firstname** string <mark style="color:purple;">optional</mark>
>
> Example: `Sally`
>
> ***
>
> **Lastname** string <mark style="color:purple;">optional</mark>
>
> Example: `APIACH`
>
> ***
>
> **Company** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **Title** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **Url** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **BillIngAdress** object <mark style="color:purple;">optional</mark>
>
> ***
>
> **Email** string <mark style="color:purple;">optional</mark>
>
> Example: `testing@easypaysolutions.com`
>
> ***
>
> **Phone** string <mark style="color:purple;">optional</mark>
>
> Example: `8775558472`

**PurchItems** object <mark style="color:purple;">optional</mark>

> **ServiceDescrip** string <mark style="color:purple;">optional</mark>
>
> A description of the service or item.
>
> Example: `FROM API TESTER`
>
> ***
>
> **ClientRefID** string <mark style="color:purple;">optional</mark>
>
> A reference ID provided by the client for tracking purposes.
>
> Example: `12456AA`
>
> ***
>
> **RPGUID** string <mark style="color:purple;">optional</mark>
>
> A custom, user-defined reference ID or value.
>
> Example: `adf98580-b4ab-42fc-bb99-01c89964afe9`

**MerchID** integer <mark style="color:purple;">optional</mark>

Example: `1`
{% endtab %}
{% endtabs %}


# Apply credit to an ACH transaction

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/ACH/ApplyCredit>

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "TxID": 2,
  "CreditAmount": 15.25
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ACH_ApplyCreditResult": {
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "RespMsg": "APPROVED 67210758 TXID 000041",
    "TxApproved": true,
    "TxID": 41
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**TxID** integer <mark style="color:purple;">optional</mark>

Example: `2`

***

**CreditAmount** number · float <mark style="color:purple;">optional</mark>

Example: `15.25`
{% endtab %}
{% endtabs %}


# Process payment with ACH annual consent

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/ACH/ProcPayment>

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "ConsentID": 21,
  "ProcessAmount": 5.1
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ACHConsentAnnual_ProcPaymentResult": {
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "RespMsg": "APPROVED 67210748 TXID 000035",
    "TxApproved": true,
    "TxID": 72,
    "uniqueTranID": "16790131F349BCBA"
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**ConsentID** integer <mark style="color:purple;">optional</mark>

Example: `21`

***

**ProcessAmount** number · float <mark style="color:purple;">optional</mark>

Example: `5.1`
{% endtab %}
{% endtabs %}


# Void an ACH transaction

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/ACH/Void>

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "TxID": 35
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ACHTransaction_VoidResult": {
    "AuthID": "67210748",
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOK": true,
    "RespMsg": "VOID APPROVED 67210748 TXID 35",
    "TxApproved": true,
    "TxID": 35
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**TxID** integer <mark style="color:purple;">optional</mark>

Example: `35`
{% endtab %}
{% endtabs %}


# Card Operations

{% columns %}
{% column width="50%" %}
{% content-ref url="/pages/CsmSTRfxM65m6lhulG5A" %}
[Process a Card Sale](/api-reference/rest-api/card-operations/process-a-card-sale)
{% endcontent-ref %}

{% content-ref url="/pages/L2tWJviyMGw55rU3obCF" %}
[Process a Card Sale with Surcharge](/api-reference/rest-api/card-operations/process-card-sale-surcharge)
{% endcontent-ref %}

{% content-ref url="/pages/2UN0fpPtwy2nGGlIFjnB" %}
[Void a Transaction](/api-reference/rest-api/card-operations/void-a-transaction)
{% endcontent-ref %}
{% endcolumn %}

{% column width="50%" %}
{% content-ref url="/pages/oGNZ7wfUaQKCe92LZk3R" %}
[Process a Refund](/api-reference/rest-api/card-operations/process-a-refund)
{% endcontent-ref %}

{% content-ref url="/pages/mIUOkLIdbQGmBaUi7xmi" %}
[Incremental Auth](/api-reference/rest-api/card-operations/authentication)
{% endcontent-ref %}
{% endcolumn %}
{% endcolumns %}


# Incremental Auth

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/CardSale/IncrementAuth>

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "OrigAuthTxID": 111,
  "AdditionalAmt": 5.0,
  "Finalize": 0
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "CreditCardSale_IncrementalResult": {
    "AVSresult": "Y",
    "AcquirerResponseEMV": null,
    "Amts": {
      "OrigAuthAmt": 10.0000,
      "ThisAuthAmt": 5.0,
      "TotalAuthAmt": 15.0000
    },
    "CVVresult": "",
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "IsPartialApproval": false,
    "RespMsg": "APPROVED OK8343",
    "TxApproved": true,
    "TxID": 112,
    "TxnCode": "OK8343"
  }
}
```

{% endtab %}

{% tab title="Notes" %}
To Implement Incremental Auth you can follow these steps:

* To Begin, you will need to create an AUTHORIZATION (AuthOnly) for a specific amount using the PayForm. (see [Incremental Authorizations](/documentation/getting-started/integration-options/payform/incremental-authorizations))
* You will need to take note of the ORIGINAL returned TxID as this must be sent in all \
  subsequent Incremental Authorizations using this API method.  &#x20;
* You can Increment the Authorization multiple times.
* When you are finished incrementing the authorization you have placed on the Cardholder account, you can then set the Finalize Flag to 1 . This will place the total authorized amount in the queue for settlement.  NO funds will be transferred until you have finalized the Authorization.
* You can set the finalize flag with a zero amount if you simply want to finalize without an additional increment.&#x20;
* Always send the ORIGINAL TXID in any case so that the system can reference all the activity properly.
* The API call returns the Total authorized amount each time you increment or Finalize or Both.
  {% endtab %}
  {% endtabs %}


# Process a Card Sale

Process a card sale with card present

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/CardSale/CardPresent>

*<mark style="color:red;">**For PCI compliant merchants only (AOC on file with Number required)**</mark>*

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "Track": "%B4788250000028291^VISA TEST/GOOD^231010100733000000?;4895390000000013=151210100000733?",
  "AcctHolder": {
    "Firstname": "Sean",
    "Lastname": "Wood",
    "Company": "",
    "Title": "",
    "Url": "",
    "BillIngAdress": {
      "Address1": "123 Fake St.",
      "Address2": "",
      "City": "PORTLAND",
      "State": "ME",
      "ZIP": "04106",
      "Country": "USA"
    },
    "Email": "robert@easypaysolutions.com",
    "Phone": "8777248472"
  },
  "EndCustomer": {
    "Firstname": "Sean",
    "Lastname": "Wood",
    "Company": "",
    "Title": "",
    "Url": "",
    "BillIngAdress": {
      "Address1": "123 Fake St.",
      "Address2": "",
      "City": "PORTLAND",
      "State": "ME",
      "ZIP": "04106",
      "Country": "USA"
    },
    "Email": "robert@easypaysolutions.com",
    "Phone": "8777248472"
  },
  "Amounts": {
    "TotalAmt": 10,
    "SalesTax": 0,
    "Surcharge": 0,
    "Tip": 0,
    "CashBack": 0,
    "ClinicAmount": 0,
    "VisionAmount": 0,
    "PrescriptionAmount": 0,
    "DentalAmount": 0,
    "TotalMedicalAmount": 0
  },
  "PurchItems": {
    "ServiceDescrip": "FROM API TESTER",
    "ClientRefID": "",
    "RPGUID": "a8e2bbfc-e423-4a84-a9e9-2a6e08153368"
  },
  "MerchID": 1
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "CreditCardSale_CardPresentResult": {
    "AVSresult": "Y",
    "AcquirerResponseEMV": null,
    "CVVresult": "",
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "IsPartialApproval": false,
    "RequiresVoiceAuth": false,
    "RespMsg": "APPROVED 092682",
    "ResponseApprovedAmount": "-1Pl",
    "ResponseAuthorizedAmount": -1,
    "ResponseBalanceAmount": -1,
    "TxApproved": true,
    "TxID": 44,
    "TxnCode": 92682
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**Track** string <mark style="color:purple;">optional</mark>

Example: `%B4788250000028291^VISA TEST/GOOD^231010100733000000?;4895390000000013=151210100000733?`

***

**AcctHolder** object <mark style="color:purple;">optional</mark>

> **AccountNum** string <mark style="color:purple;">optional</mark>
>
> The unique account number associated with the account holder.
>
> Example: `wj8HlAYlMJI=jvje9l7qZuEFiDDeEDDym6ZdlL0DX8HX`
>
> ***
>
> **AcctMask** string <mark style="color:purple;">optional</mark>
>
> The masked version of the account number for security purposes.
>
> Example: `4111XXXXXXXX1111`
>
> ***
>
> **Address1** string <mark style="color:purple;">optional</mark>
>
> The primary address line of the account holder.
>
> Example: `123 Fake St`
>
> ***
>
> **Address2** string <mark style="color:purple;">optional</mark>
>
> The secondary address line of the account holder, if applicable.
>
> ***
>
> **CardType** string <mark style="color:purple;">optional</mark>
>
> The type of card associated with the account (e.g., Visa, MasterCard).
>
> Example: `VI`
>
> ***
>
> **City** string <mark style="color:purple;">optional</mark>
>
> The city where the account holder resides.
>
> Example: `PORTLAND`
>
> ***
>
> **Company** string <mark style="color:purple;">optional</mark>
>
> The name of the company associated with the account holder, if applicable.
>
> ***
>
> **CreatedOn** string <mark style="color:purple;">optional</mark>
>
> Date and time in Microsoft JSON date format (Unix timestamp and timezone offset).
>
> Example: `2024-12-01T11:19:01.000Z`
>
> ***
>
> **Email** string <mark style="color:purple;">optional</mark>
>
> The email address of the account holder.
>
> Example: `robert@easypaysolutions.com`
>
> ***
>
> **ExpDate** string <mark style="color:purple;">optional</mark>
>
> The expiration date of the card in MMYY format.
>
> Example: `1023`
>
> ***
>
> **Firstname** string <mark style="color:purple;">optional</mark>
>
> The first name of the account holder.
>
> Example: `Sean`
>
> ***
>
> **ID** integer <mark style="color:purple;">optional</mark>
>
> The unique identifier for the account holder in the system.
>
> Example: `1`
>
> ***
>
> **LastChanged** string <mark style="color:purple;">optional</mark>
>
> Date and time in Microsoft JSON date format (Unix timestamp and timezone offset).
>
> Example: `2024-12-01T11:19:01.000Z`
>
> ***
>
> **LastName** string <mark style="color:purple;">optional</mark>
>
> The last name of the account holder.
>
> Example: `Wood`
>
> ***
>
> **MerchID** integer <mark style="color:purple;">optional</mark>
>
> The unique identifier for the merchant associated with the account.
>
> Example: `1`
>
> ***
>
> **Phone** string <mark style="color:purple;">optional</mark>
>
> The phone number of the account holder.
>
> Example: `8777248472`
>
> ***
>
> **State** string <mark style="color:purple;">optional</mark>
>
> The state where the account holder resides.
>
> Example: `ME`
>
> ***
>
> **Zip** string <mark style="color:purple;">optional</mark>
>
> The postal code for the account holder's address.
>
> Example: `04106`

**EndCustomer** object <mark style="color:purple;">optional</mark>

> **AccountNum** string <mark style="color:purple;">optional</mark>
>
> The unique account number associated with the account holder.
>
> Example: `wj8HlAYlMJI=jvje9l7qZuEFiDDeEDDym6ZdlL0DX8HX`
>
> ***
>
> **AcctMask** string <mark style="color:purple;">optional</mark>
>
> The masked version of the account number for security purposes.
>
> Example: `4111XXXXXXXX1111`
>
> ***
>
> **Address1** string <mark style="color:purple;">optional</mark>
>
> The primary address line of the account holder.
>
> Example: `123 Fake St`
>
> ***
>
> **Address2** string <mark style="color:purple;">optional</mark>
>
> The secondary address line of the account holder, if applicable.
>
> ***
>
> **CardType** string <mark style="color:purple;">optional</mark>
>
> The type of card associated with the account (e.g., Visa, MasterCard).
>
> Example: `VI`
>
> ***
>
> **City** string <mark style="color:purple;">optional</mark>
>
> The city where the account holder resides.
>
> Example: `PORTLAND`
>
> ***
>
> **Company** string <mark style="color:purple;">optional</mark>
>
> The name of the company associated with the account holder, if applicable.
>
> ***
>
> **CreatedOn** string <mark style="color:purple;">optional</mark>
>
> Date and time in Microsoft JSON date format (Unix timestamp and timezone offset).
>
> Example: `2024-12-01T11:19:01.000Z`
>
> ***
>
> **Email** string <mark style="color:purple;">optional</mark>
>
> The email address of the account holder.
>
> Example: `robert@easypaysolutions.com`
>
> ***
>
> **ExpDate** string <mark style="color:purple;">optional</mark>
>
> The expiration date of the card in MMYY format.
>
> Example: `1023`
>
> ***
>
> **Firstname** string <mark style="color:purple;">optional</mark>
>
> The first name of the account holder.
>
> Example: `Sean`
>
> ***
>
> **ID** integer <mark style="color:purple;">optional</mark>
>
> The unique identifier for the account holder in the system.
>
> Example: `1`
>
> ***
>
> **LastChanged** string <mark style="color:purple;">optional</mark>
>
> Date and time in Microsoft JSON date format (Unix timestamp and timezone offset).
>
> Example: `2024-12-01T11:19:01.000Z`
>
> ***
>
> **LastName** string <mark style="color:purple;">optional</mark>
>
> The last name of the account holder.
>
> Example: `Wood`
>
> ***
>
> **MerchID** integer <mark style="color:purple;">optional</mark>
>
> The unique identifier for the merchant associated with the account.
>
> Example: `1`
>
> ***
>
> **Phone** string <mark style="color:purple;">optional</mark>
>
> The phone number of the account holder.
>
> Example: `8777248472`
>
> ***
>
> **State** string <mark style="color:purple;">optional</mark>
>
> The state where the account holder resides.
>
> Example: `ME`
>
> ***
>
> **Zip** string <mark style="color:purple;">optional</mark>
>
> The postal code for the account holder's address.
>
> Example: `04106`

**Amounts** object <mark style="color:purple;">optional</mark>

> **TotalAmt** number <mark style="color:purple;">optional</mark>
>
> The total $ amount to be charged.
>
> Example: `10`
>
> ***
>
> **SalesTax** number <mark style="color:purple;">optional</mark>
>
> Example: `0`
>
> ***
>
> **Surcharge** number <mark style="color:purple;">optional</mark>
>
> The surcharge $ amount added to the base amount, if applicable.
>
> Example: `0`
>
> ***
>
> **Tip number** <mark style="color:purple;">optional</mark>
>
> Example: `0`
>
> ***
>
> **CashBack** number <mark style="color:purple;">optional</mark>
>
> Example: `0`
>
> ***
>
> **ClinicAmount** number <mark style="color:purple;">optional</mark>
>
> Example: `0`
>
> ***
>
> **VisionAmount** number <mark style="color:purple;">optional</mark>
>
> Example: `0`
>
> ***
>
> **PrescriptionAmount** number <mark style="color:purple;">optional</mark>
>
> Example: `0`
>
> ***
>
> **DentalAmount** number <mark style="color:purple;">optional</mark>
>
> Example: `0`
>
> ***
>
> **TotalMedicalAmount** number <mark style="color:purple;">optional</mark>
>
> Example: `0`

**PurchItems** object <mark style="color:purple;">optional</mark>

> **ServiceDescrip** string <mark style="color:purple;">optional</mark>
>
> A description of the service or item.
>
> Example: `FROM API TESTER`
>
> ***
>
> **ClientRefID** string <mark style="color:purple;">optional</mark>
>
> A reference ID provided by the client for tracking purposes.
>
> Example: `12456AA`
>
> ***
>
> **RPGUID** string <mark style="color:purple;">optional</mark>
>
> A custom, user-defined reference ID or value.
>
> Example: `adf98580-b4ab-42fc-bb99-01c89964afe9`

**MerchID** integer <mark style="color:purple;">optional</mark>

Example: `1`
{% endtab %}
{% endtabs %}


# Process a Card Sale with Surcharge

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/CardSale/WithOptions\\>
*<mark style="color:$danger;">**For PCI compliant merchants only (AOC on file with Number required)**</mark>*

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "MerchID": 1,
  "ccCardInfo": {
    "AccountNumber": "4111111111111111",
    "ExpMonth": 10,
    "ExpYear": 2028,
    "CSV": "122"
  },
  "AcctHolder": {
    "Firstname": "Sean",
    "Lastname": "Testing",
    "Company": "",
    "Title": "",
    "Url": "",
    "BillingAddress": {
      "Address1": "123 Fake St.",
      "Address2": "",
      "City": "PORTLAND",
      "State": "ME",
      "ZIP": "04106",
      "Country": "USA"
    },
    "Email": "robert@easypaysolutions.com",
    "Phone": "8777248472"
  },
  "EndCustomer": {
    "Firstname": "Sean",
    "Lastname": "Testing",
    "Company": "",
    "Title": "",
    "Url": "",
    "BillingAddress": {
      "Address1": "123 Fake St.",
      "Address2": "",
      "City": "PORTLAND",
      "State": "ME",
      "ZIP": "04106",
      "Country": "USA"
    },
    "Email": "tester@easypaysolutions.com",
    "Phone": "8777248472"
  },
  "Amounts": {
    "BaseAmt": 52,
    "Surcharge": 1.04,
    "TotalAmt": 53.04
  },
  "PurchItems": {
    "ServiceDescrip": "FROM API TESTER",
    "ClientRefID": "1876345",
    "RPGUID": "3d3424a6-c5f3-4c28-a294-490b6f674b41"
  }
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "CreditCardSale_WithOptionsResult": {
    "AVSresult": "Y",
    "AcquirerResponseEMV": null,
    "CVVresult": "",
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "IsPartialApproval": false,
    "RequiresVoiceAuth": false,
    "RespMsg": "APPROVED 099804                 ",
    "ResponseApprovedAmount": -1,
    "ResponseAuthorizedAmount": -1,
    "ResponseBalanceAmount": -1,
    "TxApproved": true,
    "TxID": 41,
    "TxnCode": 99804,
    "ApprovedAmounts": {
      "BaseAmt": 52,
      "Surcharge": 1.04,
      "TotalAmt": 53.04
    }
  }
}
```

{% endtab %}

{% tab title="Body" %}
**MerchID** integer optional

Example: `1`

***

**ccCardInfo** object optional

> **AccountNum** string optional
>
> Example: `4111111111111111`
>
> ***
>
> **ExpMonth** integer optional
>
> Example: `10`
>
> ***
>
> **ExpYear** integer optional
>
> Example: `2028`
>
> ***
>
> **CSV** string optional

**AcctHolder** object optional

> **AccountNum** string optional
>
> The unique account number associated with the account holder.
>
> Example: `wj8HlAYlMJI=jvje9l7qZuEFiDDeEDDym6ZdlL0DX8HX`
>
> ***
>
> **AcctMask** string optional
>
> The masked version of the account number for security purposes.
>
> Example: `4111XXXXXXXX1111`
>
> ***
>
> **Address1** string optional
>
> The primary address line of the account holder.
>
> Example: `123 Fake St`
>
> ***
>
> **Address2** string optional
>
> The secondary address line of the account holder, if applicable.
>
> ***
>
> **CardType** string optional
>
> The type of card associated with the account (e.g., Visa, MasterCard).
>
> Example: `VI`
>
> ***
>
> **City** string optional
>
> The city where the account holder resides.
>
> Example: `PORTLAND`
>
> ***
>
> **Company** string optional
>
> The name of the company associated with the account holder, if applicable.
>
> ***
>
> **CreatedOn** string optional
>
> Date and time in Microsoft JSON date format (Unix timestamp and timezone offset).
>
> Example: `2024-12-01T11:19:01.000Z`
>
> ***
>
> **Email** string optional
>
> The email address of the account holder.
>
> Example: `robert@easypaysolutions.com`
>
> ***
>
> **ExpDate** string optional
>
> The expiration date of the card in MMYY format.
>
> Example: `1023`
>
> ***
>
> **Firstname** string optional
>
> The first name of the account holder.
>
> Example: `Sean`
>
> ***
>
> **ID** integer optional
>
> The unique identifier for the account holder in the system.
>
> Example: `1`
>
> ***
>
> **LastChanged** string optional
>
> Date and time in Microsoft JSON date format (Unix timestamp and timezone offset).
>
> Example: `2024-12-01T11:19:01.000Z`
>
> ***
>
> **LastName** string optional
>
> The last name of the account holder.
>
> Example: `Wood`
>
> ***
>
> **MerchID** integer optional
>
> The unique identifier for the merchant associated with the account.
>
> Example: `1`
>
> ***
>
> **Phone** string optional
>
> The phone number of the account holder.
>
> Example: `8777248472`
>
> ***
>
> **State** string optional
>
> The state where the account holder resides.
>
> Example: `ME`
>
> ***
>
> **Zip** string optional
>
> The postal code for the account holder's address.
>
> Example: `04106`

**EndCustomer** object optional

> **AccountNum** string optional
>
> The unique account number associated with the account holder.
>
> Example: `wj8HlAYlMJI=jvje9l7qZuEFiDDeEDDym6ZdlL0DX8HX`
>
> ***
>
> **AcctMask** string optional
>
> The masked version of the account number for security purposes.
>
> Example: `4111XXXXXXXX1111`
>
> ***
>
> **Address1** string optional
>
> The primary address line of the account holder.
>
> Example: `123 Fake St`
>
> ***
>
> **Address2** string optional
>
> The secondary address line of the account holder, if applicable.
>
> ***
>
> **CardType** string optional
>
> The type of card associated with the account (e.g., Visa, MasterCard).
>
> Example: `VI`
>
> ***
>
> **City** string optional
>
> The city where the account holder resides.
>
> Example: `PORTLAND`
>
> ***
>
> **Company** string optional
>
> The name of the company associated with the account holder, if applicable.
>
> ***
>
> **CreatedOn** string optional
>
> Date and time in Microsoft JSON date format (Unix timestamp and timezone offset).
>
> Example: `2024-12-01T11:19:01.000Z`
>
> ***
>
> **Email** string optional
>
> The email address of the account holder.
>
> Example: `robert@easypaysolutions.com`
>
> ***
>
> **ExpDate** string optional
>
> The expiration date of the card in MMYY format.
>
> Example: `1023`
>
> ***
>
> **Firstname** string optional
>
> The first name of the account holder.
>
> Example: `Sean`
>
> ***
>
> **ID** integer optional
>
> The unique identifier for the account holder in the system.
>
> Example: `1`
>
> ***
>
> **LastChanged** string optional
>
> Date and time in Microsoft JSON date format (Unix timestamp and timezone offset).
>
> Example: `2024-12-01T11:19:01.000Z`
>
> ***
>
> **LastName** string optional
>
> The last name of the account holder.
>
> Example: `Wood`
>
> ***
>
> **MerchID** integer optional
>
> The unique identifier for the merchant associated with the account.
>
> Example: `1`
>
> ***
>
> **Phone** string optional
>
> The phone number of the account holder.
>
> Example: `8777248472`
>
> ***
>
> **State** string optional
>
> The state where the account holder resides.
>
> Example: `ME`
>
> ***
>
> **Zip** string optional
>
> The postal code for the account holder's address.
>
> Example: `04106`

**Amounts** object optional

> **BaseAmt** number - float optional
>
> The base $ amount for the transaction before any additional charges.
>
> Example: `15`
>
> ***
>
> **Surcharge** number - float optional
>
> The surcharge $ amount added to the base amount, if applicable. Adjusted based on the total.
>
> Example: `1.04`
>
> ***
>
> **TotalAmt** number - float optional

**PurchItems** object optional

> **ServiceDescrip** string optional
>
> A description of the service or item.
>
> Example: `FROM API TESTER`
>
> ***
>
> **ClientRefID** string optional
>
> A reference ID provided by the client for tracking purposes.
>
> Example: `12456AA`
>
> ***
>
> **RPGUID** string optional
>
> A custom, user-defined reference ID or value.
>
> Example: `adf98580-b4ab-42fc-bb99-01c89964afe9`

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:$warning;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:$warning;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:$warning;">required</mark>

Example: `application/json`
{% endtab %}
{% endtabs %}


# Process a Refund

Process a refund to a settled charge

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/CardSale/ApplyCredit>

Use this call to process a refund to a settled charge. You will need the Transaction ID and the amount to be refunded.

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "TxID": 56,
  "CreditAmount": 5
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "Transaction_ApplyCreditResult": {
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "RespMsg": "Successful Credit Pending Transaction ID : 000057",
    "TxApproved": true,
    "TxID": 57
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**TxID** integer <mark style="color:purple;">optional</mark>

Transaction ID of the charge to be refunded

Example: `56`

***

**CreditAmount** number · float <mark style="color:purple;">optional</mark>

Amount to be refunded

Example: `5`
{% endtab %}
{% endtabs %}


# Void a Transaction

Void a Transaction

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/CardSale/CardPresent>

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "TxID": 53
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "Transaction_VoidResult": {
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "RespMsg": "Successful Transaction Void TxID : 53 [097706]",
    "TxApproved": true,
    "TxID": 53
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}
{% endtabs %}


# Consent Annual

{% columns %}
{% column width="50%" %}
{% content-ref url="/pages/pQKubKUwx9fzDsrnR3vF" %}
[Calculate surcharging or convenience fees](/api-reference/rest-api/consent-annual/calculate-surcharging-or-convenience-fees)
{% endcontent-ref %}

{% content-ref url="/pages/Mxt7vJEbodxMUXVAwxvv" %}
[Charge a stored card](/api-reference/rest-api/consent-annual/charge-a-stored-card)
{% endcontent-ref %}

{% content-ref url="/pages/TSto2Fg6CMqoh04kBQqx" %}
[Create Annual Consent](/api-reference/rest-api/consent-annual/create-annual-consent)
{% endcontent-ref %}

{% content-ref url="/pages/AbZBDYYCOe9deO1Ewplz" %}
[Annual Consent Stats](/api-reference/rest-api/consent-annual/annual-consent-stats)
{% endcontent-ref %}

{% endcolumn %}

{% column width="50%" %}
{% content-ref url="/pages/XrzYCfyMKiQrCDWtoamK" %}
[Cancel a consent (Card On File)](/api-reference/rest-api/consent-annual/cancel-a-consent-card-on-file)
{% endcontent-ref %}

{% content-ref url="/pages/uOJs8Q3QN764NYLEJcpK" %}
[Modify an annual consent](/api-reference/rest-api/consent-annual/modify-an-annual-consent)
{% endcontent-ref %}

{% content-ref url="/pages/d7NeGVDa1GBQ177v8cEm" %}
[Create an annual consent with manual card entry](/api-reference/rest-api/consent-annual/create-an-annual-consent-with-manual-card-entry)
{% endcontent-ref %}

{% endcolumn %}
{% endcolumns %}


# Calculate surcharging or convenience fees

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/ConsentAnnual/CalcFees>

This API call is for merchant accounts that are specifically configured for surcharge and/or convenience fee processing. Prior to charging a card on file, you may use this method to properly calculate the intended fees (Surcharging or Convenience fees ).

Fees will be calculated based on the merchant configuration and the card type itself. It is important to show the calculated fees at the point of sale so that a cardholder can reject the sale if they desire.

You can specify a Alternate MerchID rather than use the merchant record originally designated when you saved the card. A Value Of ZERO will use the original Merchant record.

Once you have determined your fees you can then call the method named : Charge Stored Card with Options to authorize the sale.

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "ConsentID": 7849,
  "Amount": 52,
  "AlternateMerchID": 0
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ConsentAnnual_CalcFeesResult": {
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "RespMsg": "Fees calculated for CREDIT Card 4663XXXXXXXX2741",
    "Amounts": {
      "BaseAmt": 52,
      "Surcharge": 1.04,
      "TotalAmt": 53.04
    }
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**ConsentID** integer <mark style="color:purple;">optional</mark>

ID for consent associated with the merchant account

Example: `7849`

***

**Amount** number · float <mark style="color:purple;">optional</mark>

Base $ amount for which fees are to be calculated

Example: `52`

***

**AlternateMerchID** integer <mark style="color:purple;">optional</mark>

ID of the merchant to collect the payment funds. Use 0 for the merchant on consent.

Example: `0`
{% endtab %}
{% endtabs %}


# Cancel a consent (Card On File)

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/ConsentAnnual/Cancel>

Use this call to Cancel a consent (Card On File). You will need the ConsentID in order to execute this method.

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "ConsentID": 20
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ConsentAnnual_CancelResult": {
    "CancelSuccess": true,
    "CancelledConsentID": 20,
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "RespMsg": "Successfully DISBALED ConsentID 20 : Card Number Removed"
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**ConsentID** integer <mark style="color:purple;">optional</mark>

ID of the consent to be canceled

Example: `20`
{% endtab %}
{% endtabs %}


# Charge a stored card

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/ConsentAnnual/ChargeStoredCard>

This Method allows the user to charge a stored Card.

**ConsentID:** Please supply the ID of the Consent ( or stored card data )

**AlternateMerchID:** Here you can use ZERO if you plan to charge the same merchant record which was specified when saving the Card Info. You can use a positive integer if you plan to charge a merchant record which differs from the one originally used.

**purchDetails:** If you want to attach new reference data to the transaction you may do so using the following fields:

* ServiceDescrip : description of the transaction
* ClientRefID : your user defined reference ID
* RPGUID : another user defined reference ID&#x20;

If you choose NOT to supply these fields ( use empty string ) the system will pull this data from the original stored card data.

**Amounts:** Here you will supply the amount of the transaction. You may supply FEES but only if these have been properly configured for each Merchant record.

If you don't have FEES configured simply supply the BaseAmt and TotalAmt.

If you do Have Fees Configured you can call the method named: *Calculate Annual Consent Fees* prior to calling this method.

You can specify fee values up to and including those determined using the above method.

If you specify values greater than those calculated above, then your value will be clamped.

*<mark style="color:$danger;">IMPORTANT : Always check your response to determine the fees which are APPROVED as this may differ from what was REQUESTED.</mark>*

**User:** Here you can assign a user to the sale so that we record the person which is initiating the sale within the integrator software.

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "ConsentID": 8,
  "Amounts": {
    "BaseAmt": 52,
    "Surcharge": 1.04,
    "TotalAmt": 53.04
  },
  "purchDetails": {
    "ServiceDescrip": "Annual Checkup",
    "ClientRefID": "174356",
    "RPGUID": "99438332"
  },
  "AlternateMerchID": 0,
  "User": "Samuel"
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ConsentAnnual_ChargeStoredCardResult": {
    "AVSresult": "Y",
    "AcquirerResponseEMV": null,
    "CVVresult": "",
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "IsPartialApproval": false,
    "RequiresVoiceAuth": false,
    "RespMsg": "APPROVED OK1400",
    "ResponseApprovedAmount": 0,
    "ResponseAuthorizedAmount": 53.04,
    "ResponseBalanceAmount": 0,
    "TxApproved": true,
    "TxID": 37,
    "TxnCode": "OK1400",
    "ApprovedAmounts": {
      "BaseAmt": 52,
      "Surcharge": 1.04,
      "TotalAmt": 53.04
    }
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**ConsentID** integer <mark style="color:purple;">optional</mark>

ID of the consent (or stored card data)

Example: `8`

***

**Amounts** object <mark style="color:purple;">optional</mark>

***

**purchDetails** object <mark style="color:purple;">optional</mark>

***

**AlternateMerchID** integer <mark style="color:purple;">optional</mark>

Use 0 for the original merchant record or a positive integer for a different merchant record

Example: `0`

***

**User** string <mark style="color:purple;">optional</mark>

The user initiating the sale. Used for reporting.

Example: `Samuel`
{% endtab %}
{% endtabs %}


# Modify an annual consent

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/ConsentAnnual/Modify>

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "ConsentID": 10,
  "ConsentMods": {
    "ExpMonth": 10,
    "ExpYear": 22,
    "Email": "robert@easypaysolutions.com",
    "Zip": "04106",
    "CustomerRefID": "A1235456",
    "ServiceDescrip": "REST API Testor",
    "RPGUID": "adf98580-b4ab-42fc-bb99-01c89964afe9",
    "NumDays": 365,
    "LimitPerCharge": 10000,
    "LimitLifeTime": 100000
  }
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ConsentAnnual_ModifyResult": {
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "ModifySuccess": true,
    "RespMsg": "Success : Modified Consent ID : 10"
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
ConsentID integer optional

ID of the consent to be modified

Example: `10`

***

**ConsentMods** object <mark style="color:purple;">optional</mark>

> **ExpMonth** integer <mark style="color:purple;">optional</mark>
>
> Expiration month of the card
>
> Example: `10`
>
> ***
>
> **ExpYear** integer <mark style="color:purple;">optional</mark>
>
> Full expiration year of the card or the last 2 digits
>
> Example: `22`
>
> ***
>
> **Email** string · email <mark style="color:purple;">optional</mark>
>
> Email address associated with the consent
>
> Example: `robert@easypaysolutions.com`
>
> ***
>
> **Zip** string <mark style="color:purple;">optional</mark>
>
> ZIP code associated with the consent
>
> Example: `04106`
>
> ***
>
> **CustomerRefID** string <mark style="color:purple;">optional</mark>
>
> Customer reference ID
>
> Example: `A1235456`
>
> ***
>
> **ServiceDescrip** string <mark style="color:purple;">optional</mark>
>
> Description of the service
>
> Example: `REST API Testor`
>
> ***
>
> **RPGUID** string <mark style="color:purple;">optional</mark>
>
> A custom, user-defined reference ID or value.
>
> Example: `adf98580-b4ab-42fc-bb99-01c89964afe9`
>
> ***
>
> **NumDays** integer <mark style="color:purple;">optional</mark>
>
> Number of days for the consent
>
> Example: `365`
>
> ***
>
> **LimitPerCharge** number · float <mark style="color:purple;">optional</mark>
>
> Limit per charge
>
> Example: `10000`
>
> ***
>
> **LimitLifeTime** number · float <mark style="color:purple;">optional</mark>
>
> Lifetime limit
>
> Example: `100000`
> {% endtab %}
> {% endtabs %}


# Create Annual Consent

Create an annual consent with card present

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/ConsentAnnual/Create\\_CP>

*<mark style="color:red;">**For PCI compliant merchants only (AOC on file with Number required)**</mark>*

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "Track": "%B4788250000028291^VISA TEST/GOOD^231010100733000000?;4895390000000013=151210100000733?",
  "ConsentCreator": {
    "MerchID": 1,
    "CustomerRefID": "A1523644",
    "ServiceDescrip": "REST Test",
    "RPGUID": "ad8c349f-a301-4fc8-956c-54b59a3f6440",
    "StartDate": "/Date(1566406242284-0400)/",
    "NumDays": 365,
    "LimitPerCharge": 1000,
    "LimitLifeTime": 100000
  },
  "AcctHolder": {
    "Firstname": "Sean",
    "Lastname": "Wood",
    "Company": "",
    "Title": "",
    "Url": "",
    "BillIngAdress": {
      "Address1": "123 Fake St",
      "Address2": "",
      "City": "PORTLAND",
      "State": "ME",
      "ZIP": "04106",
      "Country": "USA"
    },
    "Email": "robert@easypaysolutions.com",
    "Phone": "8777248472"
  },
  "EndCustomer": {
    "Firstname": "Sean",
    "Lastname": "Wood",
    "Company": "",
    "Title": "",
    "Url": "",
    "BillIngAdress": {
      "Address1": "123 Fake St.",
      "Address2": "",
      "City": "PORTLAND",
      "State": "ME",
      "ZIP": "04106",
      "Country": "USA"
    },
    "Email": "robert@easypaysolutions.com",
    "Phone": "8777248472"
  }
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ConsentAnnual_Create_CPResult": {
    "ConsentID": 28,
    "CreationSuccess": true,
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "PreConsentAuthMessage": "APPROVED 095710                 ",
    "PreConsentAuthSuccess": true,
    "PreConsentAuthTxID": 84,
    "RespMsg": "Success : Created Consent ID : 000028"
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**Track** string <mark style="color:purple;">optional</mark>

Example: `%B4788250000028291^VISA TEST/GOOD^231010100733000000?;4895390000000013=151210100000733?`

***

**ConsentCreator** object <mark style="color:purple;">optional</mark>

> **MerchID** integer <mark style="color:purple;">optional</mark>
>
> Example: `1`
>
> ***
>
> **CustomerRefID** string <mark style="color:purple;">optional</mark>
>
> Example: `A1523644`
>
> ***
>
> **ServiceDescrip** string <mark style="color:purple;">optional</mark>
>
> Example: `REST Test`
>
> ***
>
> **RPGUID** string <mark style="color:purple;">optional</mark>
>
> A custom, user-defined reference ID or value.
>
> Example: `adf98580-b4ab-42fc-bb99-01c89964afe9`
>
> ***
>
> **StartDate** string <mark style="color:purple;">optional</mark>
>
> Date and time in Microsoft JSON date format (Unix timestamp and timezone offset).
>
> Example: `2024-12-01T11:19:01.000Z`
>
> ***
>
> **NumDays** integer <mark style="color:purple;">optional</mark>
>
> Example: `365`
>
> ***
>
> **LimitPerCharge** number · float <mark style="color:purple;">optional</mark>
>
> Example: `1000`
>
> ***
>
> **LimitLifeTime** number · float <mark style="color:purple;">optional</mark>
>
> Example: `100000`

**AcctHolder** object <mark style="color:purple;">optional</mark>

> **Firstname** string <mark style="color:purple;">optional</mark>
>
> Example: `Sally`
>
> ***
>
> **Lastname** string <mark style="color:purple;">optional</mark>
>
> Example: `APIACH`
>
> ***
>
> **Company** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **Title** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **Url** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **BillIngAddress** object <mark style="color:purple;">optional</mark>
>
> ***
>
> **Email** string <mark style="color:purple;">optional</mark>
>
> Example: `testing@easypaysolutions.com`
>
> ***
>
> **Phone** string <mark style="color:purple;">optional</mark>
>
> Example: `8775558472`

**EndCustomer** object <mark style="color:purple;">optional</mark>

> **Firstname** string <mark style="color:purple;">optional</mark>
>
> Example: `Sally`
>
> ***
>
> **Lastname** string <mark style="color:purple;">optional</mark>
>
> Example: `APIACH`
>
> ***
>
> **Company** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **Title string** <mark style="color:purple;">optional</mark>
>
> ***
>
> **Url** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **BillIngAddress** object <mark style="color:purple;">optional</mark>
>
> ***
>
> **Email** string <mark style="color:purple;">optional</mark>
>
> Example: `testing@easypaysolutions.com`
>
> ***
>
> **Phone** string <mark style="color:purple;">optional</mark>
>
> Example: `8775558472`
> {% endtab %}
> {% endtabs %}


# Create an annual consent with manual card entry

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/ConsentAnnual/Create\\_MAN>

*<mark style="color:red;">**For PCI compliant merchants only (AOC on file with Number required)**</mark>*

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "ccCardInfo": {
    "AccountNumber": "4111111111111111",
    "ExpMonth": 10,
    "ExpYear": 2022,
    "CSV": "122"
  },
  "ConsentCreator": {
    "MerchID": 1,
    "CustomerRefID": "A1523644",
    "ServiceDescrip": "REST Test",
    "RPGUID": "4c269391-a698-4e10-a1a8-0353ee80d1a6",
    "StartDate": "/Date(1563800567934-0400)/",
    "NumDays": 365,
    "LimitPerCharge": 1000,
    "LimitLifeTime": 100000
  },
  "AcctHolder": {
    "Firstname": "Sean",
    "Lastname": "Wood",
    "Company": "",
    "Title": "",
    "Url": "",
    "BillIngAdress": {
      "Address1": "123 Fake St",
      "Address2": "",
      "City": "PORTLAND",
      "State": "ME",
      "ZIP": "04106",
      "Country": "USA"
    },
    "Email": "robert@easypaysolutions.com",
    "Phone": "8777248472"
  },
  "EndCustomer": {
    "Firstname": "Sean",
    "Lastname": "Wood",
    "Company": "",
    "Title": "",
    "Url": "",
    "BillIngAdress": {
      "Address1": "123 Fake St.",
      "Address2": "",
      "City": "PORTLAND",
      "State": "ME",
      "ZIP": "04106",
      "Country": "USA"
    },
    "Email": "robert@easypaysolutions.com",
    "Phone": "8777248472"
  }
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ConsentAnnual_Create_MANResult": {
    "ConsentID": 18,
    "CreationSuccess": true,
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "PreConsentAuthMessage": "APPROVED 297311                 ",
    "PreConsentAuthSuccess": true,
    "PreConsentAuthTxID": 61,
    "RespMsg": "Success : Created Consent ID : 000018"
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**ccCardInfo** object <mark style="color:purple;">optional</mark>

> **AccountNumber** string <mark style="color:purple;">optional</mark>
>
> Example: `4111111111111111`
>
> **ExpMonth** integer <mark style="color:purple;">optional</mark>
>
> Example: `10`
>
> **ExpYear** integer <mark style="color:purple;">optional</mark>
>
> Example: `2028`
>
> **CSV** string <mark style="color:purple;">optional</mark>
>
> Example: `122`

**ConsentCreator** object <mark style="color:purple;">optional</mark>

> **MerchID** integer <mark style="color:purple;">optional</mark>
>
> Example: `1`
>
> **CustomerRefID** string <mark style="color:purple;">optional</mark>
>
> Example: `A1523644`
>
> **ServiceDescrip** string <mark style="color:purple;">optional</mark>
>
> Example: `REST Test`
>
> **RPGUID** string <mark style="color:purple;">optional</mark>
>
> A custom, user-defined reference ID or value.
>
> Example: `adf98580-b4ab-42fc-bb99-01c89964afe9`
>
> **StartDate** string <mark style="color:purple;">optional</mark>
>
> Date and time in Microsoft JSON date format (Unix timestamp and timezone offset).
>
> Example: `2024-12-01T11:19:01.000Z`
>
> **NumDays** integer <mark style="color:purple;">optional</mark>
>
> Example: `365`
>
> **LimitPerCharge** number · float <mark style="color:purple;">optional</mark>
>
> Example: `1000`
>
> **LimitLifeTime** number · float <mark style="color:purple;">optional</mark>
>
> Example: `100000`

**AcctHolder** object optional

> **Firstname** string <mark style="color:purple;">optional</mark>
>
> Example: `Sally`
>
> **Lastname** string <mark style="color:purple;">optional</mark>
>
> Example: `APIACH`
>
> **Company** string <mark style="color:purple;">optional</mark>
>
> **Title** string <mark style="color:purple;">optional</mark>
>
> **Url** string <mark style="color:purple;">optional</mark>
>
> **BillIngAddress** object <mark style="color:purple;">optional</mark>
>
> **Email** string <mark style="color:purple;">optional</mark>
>
> Example: `testing@easypaysolutions.com`
>
> **Phone** string <mark style="color:purple;">optional</mark>
>
> Example: `8775558472`

**EndCustomer** object <mark style="color:purple;">optional</mark>

> **Firstname** string <mark style="color:purple;">optional</mark>
>
> Example: `Sally`
>
> **Lastname** string <mark style="color:purple;">optional</mark>
>
> Example: `APIACH`
>
> **Company** string <mark style="color:purple;">optional</mark>
>
> **Title** string <mark style="color:purple;">optional</mark>
>
> **Url** string <mark style="color:purple;">optional</mark>
>
> **BillIngAddress** object <mark style="color:purple;">optional</mark>
>
> **Email** string <mark style="color:purple;">optional</mark>
>
> Example: `testing@easypaysolutions.com`
>
> **Phone** string <mark style="color:purple;">optional</mark>
>
> Example: `8775558472`
> {% endtab %}
> {% endtabs %}


# Annual Consent Stats

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/ConsentAnnual/Stats>

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "ConsentID": 10
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ConsentAnnual_StatsResult": {
    "ErrCode": 0,
    "ErrMsg": null,
    "FunctionOk": true,
    "RespMsg": "Successfully Returned Stats For Consent ID : 10",
    "Stats": {
      "FirstChargeAttempt": "\/Date(-62135578800000-0500)\/",
      "ID": 10,
      "IsEnabled": false,
      "LastChargeAmount": 0,
      "LastChargeAttempt": "\/Date(-62135578800000-0500)\/",
      "LastSettledAmount": 0,
      "LimitLifeTime": 100000.0000,
      "NumChargeAttempts": 0,
      "NumFailed": 0,
      "NumFailedAttempts": 0,
      "NumOpen": 0,
      "NumSettled": 0,
      "NumTx": 0,
      "RemainingInConsent": 100000.0000,
      "TotalDollarsOpen": 0,
      "TotalDollarsSettled": 0
    }
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}
{% endtabs %}


# Consent Recurring

{% columns %}
{% column %}
{% content-ref url="/pages/2rBEj8JYlN5jrfjfIZ5c" %}
[Create a recurring consent with manual card entry](/api-reference/rest-api/consent-recurring/create-a-recurring-consent-with-manual-card-entry)
{% endcontent-ref %}

{% content-ref url="/pages/eoEkdQv0q717mliA7TIB" %}
[Modify a recurring consent](/api-reference/rest-api/consent-recurring/modify-a-recurring-consent)
{% endcontent-ref %}
{% endcolumn %}

{% column %}
{% content-ref url="/pages/PTv1saem6bG5atr0ywxx" %}
[Cancel a recurring consent](/api-reference/rest-api/consent-recurring/cancel-a-recurring-consent)
{% endcontent-ref %}
{% endcolumn %}
{% endcolumns %}


# Create a recurring consent with manual card entry

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/ConsentRecurring/Create>

*<mark style="color:red;">**For PCI compliant merchants only (AOC on file with Number required)**</mark>*

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "ccCardInfo": {
    "AccountNumber": "4111111111111111",
    "ExpMonth": 10,
    "ExpYear": 23,
    "CSV": "123",
    "Track": "%B4788250000028291^VISA TEST/GOOD^231010100733000000?;4895390000000013=151210100000733?"
  },
  "ConsentCreator": {
    "MerchID": 1,
    "CustomerRefID": "A123456",
    "ServiceDescrip": "",
    "RPGUID": "",
    "StartDate": "/Date(1564409121413-0400)/",
    "NumPayments": 10,
    "TotalAmount": 10000,
    "Period": 2
  },
  "AcctHolder": {
    "Firstname": "Sean",
    "Lastname": "Wood",
    "Company": "",
    "Title": "",
    "Url": "",
    "BillIngAdress": {
      "Address1": "123 Fake St",
      "Address2": "",
      "City": "PORTLAND",
      "State": "ME",
      "ZIP": "04106",
      "Country": "USA"
    },
    "Email": "robert@easypaysolutions.com",
    "Phone": "8777248472"
  },
  "EndCustomer": {
    "Firstname": "Sean",
    "Lastname": "Wood",
    "Company": "",
    "Title": "",
    "Url": "",
    "BillIngAdress": {
      "Address1": "123 Fake St.",
      "Address2": "",
      "City": "PORTLAND",
      "State": "ME",
      "ZIP": "04106",
      "Country": "USA"
    },
    "Email": "robert@easypaysolutions.com",
    "Phone": "8777248472"
  }
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ConsentRecurring_CreateResult": {
    "ConsentID": 22,
    "CreationSuccess": true,
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "MySched": [
      {
        "Remaining": 9000,
        "SchedID": 41,
        "paymentAmt": 1000,
        "paymentDate": "2024-12-01T11:19:01.000Z",
        "paymentNo": 1
      }
    ],
    "PreConsentAuthMessage": "APPROVED 298734                 ",
    "PreConsentAuthSuccess": true,
    "PreConsentAuthTxID": 66,
    "RespMsg": "Success : Created Recurring Consent ID : 000022"
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**ccCardInfo** object <mark style="color:purple;">optional</mark>

> **AccountNumber** string <mark style="color:purple;">optional</mark>
>
> Example: `4111111111111111`
>
> ***
>
> **ExpMonth** integer <mark style="color:purple;">optional</mark>
>
> Example: `10`
>
> ***
>
> **ExpYear** integer <mark style="color:purple;">optional</mark>
>
> Example: `2028`
>
> ***
>
> **CSV** string <mark style="color:purple;">optional</mark>
>
> Example: `122`
>
> ***
>
> **Track string** | nullable <mark style="color:purple;">optional</mark>
>
> Example: `%B4788250000028291^VISA TEST/GOOD^231010100733000000?;4895390000000013=151210100000733?`

**ConsentCreator** object <mark style="color:purple;">optional</mark>

> **MerchID** integer <mark style="color:purple;">optional</mark>
>
> Example: `1`
>
> ***
>
> **CustomerRefID** string <mark style="color:purple;">optional</mark>
>
> Example: `A123456`
>
> ***
>
> **ServiceDescrip** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **RPGUID** string <mark style="color:purple;">optional</mark>
>
> A custom, user-defined reference ID or value.
>
> Example: `adf98580-b4ab-42fc-bb99-01c89964afe9`
>
> ***
>
> **StartDate** string <mark style="color:purple;">optional</mark>
>
> Date and time in Microsoft JSON date format (Unix timestamp and timezone offset).
>
> Example: `2024-12-01T11:19:01.000Z`
>
> ***
>
> **NumPayments** integer <mark style="color:purple;">optional</mark>
>
> Example: `10`
>
> ***
>
> **TotalAmount** number · float <mark style="color:purple;">optional</mark>
>
> Example: `10000`
>
> ***
>
> **Period** integer <mark style="color:purple;">optional</mark>
>
> Example: `2`

**AcctHolder** object <mark style="color:purple;">optional</mark>

> **Firstname** string <mark style="color:purple;">optional</mark>
>
> Example: `Sally`
>
> ***
>
> **Lastname** string <mark style="color:purple;">optional</mark>
>
> Example: `APIACH`
>
> ***
>
> **Company** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **Title** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **Url** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **BillIngAddress** object <mark style="color:purple;">optional</mark>
>
> ***
>
> **Email** string <mark style="color:purple;">optional</mark>
>
> Example: `testing@easypaysolutions.com`
>
> ***
>
> **Phone** string <mark style="color:purple;">optional</mark>
>
> Example: `8775558472`

**EndCustomer** object <mark style="color:purple;">optional</mark>

> **Firstname** string <mark style="color:purple;">optional</mark>
>
> Example: `Sally`
>
> ***
>
> **Lastname** string <mark style="color:purple;">optional</mark>
>
> Example: `APIACH`
>
> ***
>
> **Company** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **Title** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **Url** string <mark style="color:purple;">optional</mark>
>
> ***
>
> **BillIngAddress** object <mark style="color:purple;">optional</mark>
>
> ***
>
> **Email** string <mark style="color:purple;">optional</mark>
>
> Example: `testing@easypaysolutions.com`
>
> ***
>
> **Phone** string <mark style="color:purple;">optional</mark>
>
> Example: `8775558472`
> {% endtab %}
> {% endtabs %}


# Cancel a recurring consent

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/ConsentRecurring/Cancel>

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "ConsentID": 23
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ConsentRecurring_CancelResult": {
    "CancelSuccess": true,
    "CancelledConsentID": 23,
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "RespMsg": "Successfully DISBALED ConsentID 23 : Card Number Removed"
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**ConsentID** integer <mark style="color:purple;">optional</mark>

ID of the consent to be cancelled

Example: `23`
{% endtab %}
{% endtabs %}


# Modify a recurring consent

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/ConsentRecurring/Modify>

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "ConsentID": 42,
  "ConsentMods": {
    "ExpMonth": 10,
    "ExpYear": 2028,
    "Email": "sean@easypaysolutions.com",
    "Zip": "04101",
    "CustomerRefID": "A123456",
    "ServiceDescrip": "Test",
    "RPGUID": ""
  }
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ConsentRecurring_ModifyResult": {
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "ModifySuccess": true,
    "RespMsg": "Success : Modified Consent ID : 42"
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**ConsentID** integer <mark style="color:purple;">optional</mark>

ID of the consent to be cancelled

Example: `42`

**ConsentMods** object <mark style="color:purple;">optional</mark>

> **ExpMonth** integer <mark style="color:purple;">optional</mark>
>
> Expiration month of the card
>
> Example: `10`
>
> ***
>
> **ExpYear** integer <mark style="color:purple;">optional</mark>
>
> Expiration year of the card
>
> Example: `2028`
>
> ***
>
> **Email** string · email <mark style="color:purple;">optional</mark>
>
> Email associated with the consent
>
> Example: `sean@easypaysolutions.com`
>
> ***
>
> **Zip** string <mark style="color:purple;">optional</mark>
>
> ZIP code associated with the consent
>
> Example: `04101`
>
> ***
>
> **CustomerRefID** string <mark style="color:purple;">optional</mark>
>
> Customer reference ID
>
> Example: `A123456`
>
> ***
>
> **ServiceDescrip** string <mark style="color:purple;">optional</mark>
>
> Description of the service
>
> Example: `Test`
>
> ***
>
> **RPGUID** string <mark style="color:purple;">optional</mark>
>
> A custom, user-defined reference ID or value.
>
> Example: `adf98580-b4ab-42fc-bb99-01c89964afe9`
> {% endtab %}
> {% endtabs %}


# Consent Subscription

{% columns %}
{% column %}
{% content-ref url="/pages/2jsLIcNZcdbyUDxT41yM" %}
[Modify a consent subscription](/api-reference/rest-api/consent-subscription/modify-a-consent-subscription)
{% endcontent-ref %}
{% endcolumn %}

{% column %}
{% content-ref url="/pages/rVMcF77UOvfgdxUvEwAO" %}
[Cancel a consent subscription](/api-reference/rest-api/consent-subscription/cancel-a-consent-subscription)
{% endcontent-ref %}
{% endcolumn %}
{% endcolumns %}


# Modify a consent subscription

Modify an existing subscription consent

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/ConsentSubscription/Modify>

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "ConsentID": 12,
  "ConsentMods": {
    "ExpMonth": 10,
    "ExpYear": 2022,
    "Email": "noreply@easypaysolutions.com",
    "Zip": "04106",
    "RPGUID": "",
    "CustomerRefID": "A123456",
    "ServiceDescrip": "Test",
    "PaymentAmt": 10,
    "PaymentAdjustDate": "2019-04-29T11:26:11.093Z",
    "OnHold": false
  }
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ErrCode": 0,
  "ErrMsg": "",
  "FunctionOk": true,
  "RespMsg": "Consent successfully modified"
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**ConsentID** integer <mark style="color:purple;">optional</mark>

ID of the consent to be modified

Example: `12`

***

**ConsentMods** object <mark style="color:purple;">optional</mark>

> **ExpMonth** integer <mark style="color:purple;">optional</mark>
>
> Expiration month of the card
>
> Example: `10`
>
> ***
>
> **ExpYear** integer <mark style="color:purple;">optional</mark>
>
> Expiration year of the card
>
> Example: `2022`
>
> ***
>
> **Email** string · email <mark style="color:purple;">optional</mark>
>
> Email associated with the consent
>
> Example: `noreply@easypaysolutions.com`
>
> ***
>
> **Zip** string <mark style="color:purple;">optional</mark>
>
> ZIP code associated with the consent
>
> Example: `04106`
>
> ***
>
> **RPGUID** string <mark style="color:purple;">optional</mark>
>
> A custom, user-defined reference ID or value.
>
> Example: `adf98580-b4ab-42fc-bb99-01c89964afe9`
>
> ***
>
> **CustomerRefID** string <mark style="color:purple;">optional</mark>
>
> Customer reference ID
>
> Example: `A123456`
>
> ***
>
> **ServiceDescrip** string <mark style="color:purple;">optional</mark>
>
> Description of the service
>
> Example: `Test`
>
> ***
>
> **PaymentAmt** number · float <mark style="color:purple;">optional</mark>
>
> Payment $ amount
>
> Example: `10`
>
> ***
>
> **PaymentAdjustDate** string · date-time <mark style="color:purple;">optional</mark>
>
> Date and time for payment adjustment
>
> Example: `2019-04-29T11:26:11.093Z`
>
> ***
>
> **OnHold** boolean <mark style="color:purple;">optional</mark>
>
> Whether the consent is on hold
>
> Example: `false`
> {% endtab %}

{% tab title="Notes" %}
In most cases you may only want to modify a single parameter such as PaymentAdjustDate or OnHold. You can supply a value of -1 or "-1" to any value which you do not want us to alter. The following example shows how to simply remove the hold from ConsentID 21:

```clike
{
"ConsentID": 21,
"ConsentMods": {
    "ExpMonth": -1,
    "ExpYear": -1,
    "Email": "-1",
    "Zip": "-1",
    "RPGUID": "-1",
    "CustomerRefID": "-1",
    "ServiceDescrip": "-1",
    "PaymentAmt": -1,
    "PaymentAdjustDate": "-1",
    "OnHold": false
   }
}
```

{% endtab %}
{% endtabs %}


# Cancel a consent subscription

Cancel an existing subscription consent

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/ConsentSubscription/Cancel>

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
    "ConsentID": 4162
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
    "ConsentSubscription_CancelResult": {
        "CancelSuccess": true,
        "CancelledConsentID": 4162,
        "ErrCode": 0,
        "ErrMsg": "",
        "FunctionOk": true,
        "RespMsg": "Successfully DISABLED ConsentID 4162 : Card Number Removed"
    }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**ConsentID** integer <mark style="color:purple;">optional</mark>

ID of the consent to be canceled

Example: `12`

{% endtab %}
{% endtabs %}


# International

{% columns %}
{% column %}
{% content-ref url="/pages/4Fvjx4kvjUW10mN37x3L" %}
[Generate a Receipt](/api-reference/rest-api/international/generate-a-receipt)
{% endcontent-ref %}

{% content-ref url="/pages/ATRh1mea7HBugn8DFSX2" %}
[Process Consent](/api-reference/rest-api/international/process-consent)
{% endcontent-ref %}
{% endcolumn %}

{% column %}
{% content-ref url="/pages/3uJgea9Xw0J1q7cXMLsN" %}
[Query International Transaction](/api-reference/rest-api/international/query-international-transaction)
{% endcontent-ref %}

{% content-ref url="/pages/mPS6ORmpMoEYMbvmMGr6" %}
[Void Credit](/api-reference/rest-api/international/void-credit)
{% endcontent-ref %}
{% endcolumn %}
{% endcolumns %}


# Generate a Receipt

Generate a receipt for an international transaction

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/Intl/ReceiptGenerate>

REFID will be the transaction ID\
*ReceiptType will always be 23 for International*

**Consuming the Response**\
The member named ReceiptHtml holds the receipt data\
Important you must replace all Unicode characters to consume clean HTML\
Example : CleanHtml = Regex.Replace(my, @"\[^\u0000-\u007F]+", string.Empty);

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "REFID": "5eef4782-5be1-11ef-bbc1-46647bd59a7a",
  "ReceiptType": 23,
  "Recipient": 1
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "Intl_ReceiptGenerateResult": {
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "ReceiptHtml": "HTML",
    "RespMsg": "Successfully Returned Transaction Receipt Markup"
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**REFID** string <mark style="color:purple;">optional</mark>

The transaction ID

Example: `5eef4782-5be1-11ef-bbc1-46647bd59a7a`

***

**ReceiptType** integer <mark style="color:purple;">optional</mark>

The type of receipt, 23 for international

Example: `23`

***

**Recipient** integer · enum <mark style="color:purple;">optional</mark>

The targeted recipient type

* 1: Merchant
* 2: Customer
* 3: Both

Example: `1`
{% endtab %}
{% endtabs %}


# Process Consent

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/Intl/ProcPayment>

*This API call is for merchant accounts that are specifically configured for international processing.*

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "TokenID": "a64d8a2a-5994-11ef-95fc-3e580ecac30f",
  "ChargeAmt": 5.0
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "Intl_ProcPaymentResult": {
    "AuthorizedAmt": 5.00,
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "RespMsg": "Successfully charged Consent a64d8a2a-5994-11ef-95fc-3e580ecac30f For $5.00",
    "TransID": "a63f6936-5994-11ef-8613-3e580ecac30f",
    "TxApproved": true,
    "TxnCode": ""
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}
{% endtabs %}


# Query International Transaction

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/Intl/QueryTransaction>

*See Notes for Details*

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "Query": "(F='328217c4-7059-11ef-a730-a6469c956913')&&(B=3)&&(E=1) "
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "Intl_Transaction_QueryResult": {
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "NumRecords": 1,
    "RespMsg": "Successfully Returned Transaction Records : 1",
    "Transactions": [
      {
        "Action": "SALE",
        "Address": "generating sale",
        "Amount": 0,
        "Card": "0042",
        "Card_Expiration_Date": "12\/2025",
        "Card_Token": "",
        "City": "Auburn",
        "Country": "US",
        "CreatedOn": "\/Date(1726071401083-0400)\/",
        "Currency": null,
        "Decline_Reason": "",
        "Descriptor": "",
        "Email": ndraper@easypaysolutions.com,
        "Fname": "Nancy",
        "ID": 570,
        "Lname": "Draper",
        "MerchID": 1,
        "Order_ID": "B7A6A9DF",
        "Phone": "",
        "PostalCode": "32658",
        "REFID": "",
        "RPGUID": "",
        "Recurring_Token": "",
        "Result": "SUCCESS",
        "Schedule_ID": null,
        "State": "ME",
        "Status": "SETTLED",
        "Trans_Date": "Sep 11 2024  4:16PM",
        "Trans_ID": "328217c4-7059-11ef-a730-a6469c956913",
        "bank_date": null,
        "chargeback_date": null,
        "reason_code": null
      }
    ]
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Notes" %}

#### Query Strings:

EasyPay provides a robust query language which provides a means for you to obtain specific records.

In order to Create a Query you will build logical terms and join them with Logical AND or Logical OR.

Use && for Logical AND

Use || for Logical OR

For instance, Let's say you want to return all records from merchant record 1 which were created in JUNE.

HERE IS THE QUERY: (A=1)&&(C>='6/1/2024')&&(C<'7/1/2024') (notice that any TEXT or DATES use a single Quote delimiter while numeric items do not)

Each Letter represents a variable and the following chart shows each meaning.

| A | MerchID        |
| - | -------------- |
| B | Status         |
| C | CreatedON      |
| D | LastName       |
| E | Result         |
| F | TransID        |
| J | FirstName      |
| L | Amount         |
| M | REFID          |
| Q | CardNum Last 4 |
| N | RPGUID         |
| W | ConsentID      |
|   |                |

EasyPay stores a copy of the transactional data on its servers. For international transactions data is stored in such a way that we may have multiple records in our system for a single credit card authorization or OrderID. Two Fields of Interest are **Result and Status**.

| Seq | OrderID  | Action | Result   | Status   |
| --- | -------- | ------ | -------- | -------- |
| 1   | 09B370DD | SALE   | REDIRECT | REDIRECT |
| 2   | 09B370DD | SALE   | REDIRECT | 3DS      |
| 3   | 09B370DD | SALE   | SUCCESS  | SETTLED  |

The above table shows three records we record as we process a single transaction on the International Processing Servers. As you request transaction information you are most likely only interested in the last entry which shows SUCCESS and SETTLED as the other two are simply intermediate steps.

The following shows query enum values for RESULT and STATUS and ACTION

<table data-header-hidden><thead><tr><th valign="top"></th><th valign="top"></th><th data-hidden valign="top"></th></tr></thead><tbody><tr><td valign="top"><strong>E Result Values</strong></td><td valign="top"></td><td valign="top"></td></tr><tr><td valign="top">ALL</td><td valign="top">-1</td><td valign="top"></td></tr><tr><td valign="top">SUCCESS</td><td valign="top">1</td><td valign="top"></td></tr><tr><td valign="top">DECLINED</td><td valign="top">2</td><td valign="top"></td></tr><tr><td valign="top">REDIRECT</td><td valign="top">3</td><td valign="top"></td></tr><tr><td valign="top">ACCEPTED</td><td valign="top">4</td><td valign="top"></td></tr><tr><td valign="top">ERROR</td><td valign="top">5</td><td valign="top"></td></tr><tr><td valign="top">UNDEFINED</td><td valign="top">6</td><td valign="top"></td></tr><tr><td valign="top"><strong>B Status Values</strong></td><td valign="top"></td><td valign="top"></td></tr><tr><td valign="top">ALL</td><td valign="top">-1</td><td valign="top"></td></tr><tr><td valign="top">PENDING</td><td valign="top">1</td><td valign="top"></td></tr><tr><td valign="top">REDIRECT</td><td valign="top">2</td><td valign="top"></td></tr><tr><td valign="top">SETTLED</td><td valign="top">3</td><td valign="top"></td></tr><tr><td valign="top">REVERSAL</td><td valign="top">4</td><td valign="top"></td></tr><tr><td valign="top">REFUND</td><td valign="top">5</td><td valign="top"></td></tr><tr><td valign="top">DECLINED</td><td valign="top">6</td><td valign="top"></td></tr><tr><td valign="top">PENDING</td><td valign="top">7</td><td valign="top"></td></tr><tr><td valign="top">CHARGEBACK</td><td valign="top">8</td><td valign="top"></td></tr><tr><td valign="top">VOID</td><td valign="top">9</td><td valign="top"></td></tr><tr><td valign="top"><strong>G Action Values</strong></td><td valign="top"></td><td valign="top"></td></tr><tr><td valign="top">ALL</td><td valign="top">-1</td><td valign="top"></td></tr><tr><td valign="top">SALES</td><td valign="top">1</td><td valign="top"></td></tr><tr><td valign="top">CREDITVOID</td><td valign="top">2</td><td valign="top"></td></tr><tr><td valign="top">RECURRING_SALE</td><td valign="top">3</td><td valign="top"></td></tr></tbody></table>

So, to return all Transactions which are successfully settled please use the following query:

Result ➔ E Use 1 for Success

Status ➔ B Use 3 for Settled

Your query now becomes the following

{\
&#x20; "Query": "(B=3)&&(E=1)"\
}

***

You can further limit your query by specifying a Date Range

{\
&#x20; "Query": "(B=3)&&(E=1)&&(C>’2024-09-01’)"\
}

***

If you want to limit your results to transactions which are REFUNDS then use ACTION CREDITVOID

Or specifically (G=2)

{\
&#x20; "Query": "(B=3)&&(E=1)&&(C>'2024-09-01')&&(G=2)"\
}

***

If you want to limit your results to transactions which are Processed from stored Card use ACTION RECURRING\_SALE

Or specifically (G=3)

{\
&#x20; "Query": "(B=3)&&(E=1)&&(C>'2024-09-01')&&(G=3)"\
}

***

If you are looking for a particular transaction based on its unique TransID, you can do the following:

{\
&#x20; "Query": "(F='328217c4-7059-11ef-a730-a6469c956913')&&(B=3)&&(E=1) "\
}

***

This will return the transaction of interest without returning the intermediate steps as noted above.

If you want to query by Last name on a specific Date

{\
&#x20; "Query": "(C>'2024-09-16')&&(C<'2024-09-17')&&(D='SMITH')&&(B=3)&&(E=1)"\
}

***

If you are looking for a specific Amount

{\
&#x20; "Query": "(L=4.44)&&(B=3)&&(E=1)"\
}

***

If you are looking for a specific Amount within a date range

{\
&#x20; "Query": "(L=4.44)&&(C>'2024-09-16')&&(C<'2024-09-17')&&(B=3)&&(E=1)"\
}

***

If you are looking for a particular Card Number ( use last 4 digits ) for settled records

{\
&#x20; "Query": "(Q='1111')&&(B=3)&&(E=1)"\
}

***

If you are looking for a particular Reference ID

{\
&#x20; "Query": "(M='ABC 888')&&(B=3)&&(E=1)"\
}

***

If you are looking for a particular saved card transaction based on the ConsentID

{\
&#x20; "Query": "(W='c30eca54-75c1-11ef-b9e6-7aa481e33aa5')&&(B=3)&&(E=1)"\
}
{% endtab %}
{% endtabs %}


# Void Credit

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/Intl/VoidCredit>

*This API call is for merchant accounts that are specifically configured for international processing.*

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "TransID": "a88ed0e4-5a3b-11ef-b49b-46647bd59a7a",
  "CreditAmt": 5.0
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "Intl_VoidCredtResult": {
    "CreditAmt": 5.0,
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "RespMsg": "Succesfull VOID\/Credit",
    "TransID": "a88ed0e4-5a3b-11ef-b49b-46647bd59a7a",
    "TxApproved": true
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}
{% endtabs %}


# PayForm

Initialize PayForm

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/CardSale/InitForm>

Call this method to initialize a payment form used for collecting payments, saving card-on-file data, or both. This call can be used to initiate both Credit card payments and ACH. The call returns the URL used to open the form.

For details on configurations and options, view our builder tool at <https://easypay8.com/byopayform/>

{% tabs %}
{% tab title="Sample Request" %}

```jsonc
{
  "InitParams": {
    "MerchID": 1,
    "WTYPE": "PF",
    "PostURL": "https://easypay1.com/swidget/JsonGet.aspx",
    "RedirectURL": "https://easypay8.com/CYWidget/",
    "REF_ID": "A97689#",
    "RPGUID": "92e1e15c-f64a-466b-8733-9b518b9f374c",
    "EndPoint": "PayForm/PF.aspx",
    "EINDEX": "300",
    "Amounts": {
      "Amount": 20,
      "Surcharge": 0,
      "TotalAmt": 20
    },
    "Payer": {
      "Firstname": "John Doe",
      "Lastname": "",
      "BillingAddress": {
        "StreetAddress": "",
        "City": "",
        "State": "",
        "ZIP": "04048",
        "Country": ""
      },
      "Email": "",
      "Phone": ""
    },
    "WidOptions": {
      "eVisible": "0665",
      "eReadOnly": "0040",
      "eStyles": "0001",
      "eSubmission": "0A01",
      "eFeatures": "0000",
      "eColors": "#ffffff,#428bca,#007bff,#212121,#ffffff,#212121,#ffffff"
    }
  }
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "PaymentInitResult": {
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "PaymentUrl": "https://easypay5.com/swidget/?eGUID=239F97C4&CS=021&Digest=tru49A2ncbyvHoaIa6T81Q",
    "RespMsg": "successfully returned payment Url"
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**InitParams** object <mark style="color:purple;">optional</mark>

> **MerchID** integer <mark style="color:orange;">required</mark>
>
> Use 1 unless your account has multiple merchant records. The merchant ID for the transaction.
>
> Example: `1`
>
> ***
>
> **WTYPE** string · enum <mark style="color:orange;">required</mark>
>
> The widget type for the PayForm
>
> * PF: Regular PayForm
> * PA: International PayForm
>
> Example: `PF`
>
> Possible values: `PF  PA`
>
> ***
>
> **PostURL** string <mark style="color:purple;">optional</mark>
>
> The URL where real-time values will be posted after payment completion.
>
> Example: `https://easypay1.com/swidget/JsonGet.aspx`
>
> ***
>
> **RedirectURL** string <mark style="color:purple;">optional</mark>
>
> The URL to redirect to after processing the payment.
>
> Example: `https://easypay8.com/CYWidget/`
>
> ***
>
> **REF\_ID** string <mark style="color:purple;">optional</mark>
>
> A custom, user-defined reference ID or value.
>
> Example: `A97689#`
>
> ***
>
> **RPGUID** string <mark style="color:purple;">optional</mark>
>
> A custom, user-defined reference ID or value.
>
> Example: `adf98580-b4ab-42fc-bb99-01c89964afe9`
>
> ***
>
> **EndPoint** string <mark style="color:orange;">required</mark>
>
> Points to a specific web app on our servers. Should always have the value of PayForm/PF.aspx.
>
> Example: `PayForm/PF.aspx`
>
> ***
>
> **EINDEX** string <mark style="color:purple;">optional</mark>
>
> Integrator key index for encryption assigned when integrator account is first created, received with the initial login credentials
>
> Example: `100`

**Amounts** object <mark style="color:purple;">optional</mark>

> **BaseAmt** number · float <mark style="color:purple;">optional</mark>
>
> The base $ amount for the transaction before any additional charges.
>
> Example: `52`
>
> ***
>
> **Surcharge** number · float <mark style="color:purple;">optional</mark>
>
> The surcharge $ amount added to the base amount, if applicable. Adjusted based on the total.
>
> Example: `1.04`
>
> ***
>
> **TotalAmt** number · float <mark style="color:purple;">optional</mark>
>
> The total $ amount to be charged, which includes the base amount and any surcharges.
>
> Example: `53.04`

**Payer** object <mark style="color:purple;">optional</mark>

> **Firstname** string <mark style="color:purple;">optional</mark>
>
> The first name of the payer.
>
> Example: `John`
>
> ***
>
> **Lastname** string <mark style="color:purple;">optional</mark>
>
> The last name of the payer.
>
> Example: `Doe`
>
> ***
>
> **Email** string <mark style="color:purple;">optional</mark>
>
> The email of the payer.
>
> ***
>
> **Phone** string <mark style="color:purple;">optional</mark>
>
> The phone of the payer.
>
> ***
>
> **BillingAddress** object <mark style="color:purple;">optional</mark>

**WidOptions** object <mark style="color:orange;">required</mark>

> **eVisible** string <mark style="color:orange;">required</mark>
>
> Hex digits controlling field visibility.
>
> Example: `0665`
>
> ***
>
> **eReadOnly** string <mark style="color:orange;">required</mark>
>
> Hex digits dictating read-only fields.
>
> Example: `0040`
>
> ***
>
> **eStyles** string <mark style="color:orange;">required</mark>
>
> Hex digits controlling form styling.
>
> Example: `0001`
>
> ***
>
> **eSubmission** string <mark style="color:orange;">required</mark>
>
> Hex digits controlling submission options.
>
> Example: `0A01`
>
> ***
>
> **eColors** string <mark style="color:orange;">required</mark>
>
> String controlling optional color schemes.
>
> Example: `#ffffff,#428bca,#007bff,#212121,#ffffff,#212121,#ffffff`
> {% endtab %}
> {% endtabs %}


# Query

{% columns %}
{% column %}
{% content-ref url="/pages/RFEQsd6NlsU3wp4FxgPQ" %}
[Account profile](/api-reference/rest-api/query/account-profile)
{% endcontent-ref %}

{% content-ref url="/pages/MqknWpwPpnc2IpwlfZ6p" %}
[Batch logs](/api-reference/rest-api/query/batch-logs)
{% endcontent-ref %}

{% content-ref url="/pages/hyFjHjIjlKZmXVF5EwJc" %}
[Recurring Consents](/api-reference/rest-api/query/recurring-consents)
{% endcontent-ref %}

{% content-ref url="/pages/VLsIjdK4GLBsh3rhlDgu" %}
[Consent General Query](/api-reference/rest-api/query/consent-general-query)
{% endcontent-ref %}

{% content-ref url="/pages/7qJcBiZMur10VnjR50xA" %}
[Receipt Details](/api-reference/rest-api/query/receipt-details)
{% endcontent-ref %}

{% content-ref url="/pages/kA8o3SpaKYduKpLZ9GQ7" %}
[Transaction Full Detail](/api-reference/rest-api/query/transaction-full-detail)
{% endcontent-ref %}

{% content-ref url="/pages/RRInjvjn4C2e3w0dmNhf" %}
[Voice](/api-reference/rest-api/query/voice)
{% endcontent-ref %}

{% content-ref url="/pages/Kyaz0r1b85Q4pwfBcVJV" %}
[Reconcile](/api-reference/rest-api/query/reconcile)
{% endcontent-ref %}

{% endcolumn %}

{% column %}
{% content-ref url="/pages/ySfX4jZGhSsKkLmLoBqZ" %}
[ACH transactions](/api-reference/rest-api/query/ach-transactions)
{% endcontent-ref %}

{% content-ref url="/pages/Gf8kFyTPIxhuQ18gXYsy" %}
[Consent Annual Query](/api-reference/rest-api/query/consent-annual-query)
{% endcontent-ref %}

{% content-ref url="/pages/L32Zn9H1IIMma2bDfuT4" %}
[Recurring Consent Full Detail](/api-reference/rest-api/query/recurring-consent-full-detail)
{% endcontent-ref %}

{% content-ref url="/pages/JWCnqkOIweWYDd9ThBnF" %}
[Recurring Schedules](/api-reference/rest-api/query/recurring-schedules)
{% endcontent-ref %}

{% content-ref url="/pages/WgFSN7O0KUJdMnPaBuhl" %}
[Transaction Search](/api-reference/rest-api/query/transaction-search)
{% endcontent-ref %}

{% content-ref url="/pages/fLDKs2iJ2QQuOnYaV43S" %}
[Transaction Receipt](/api-reference/rest-api/query/transaction-receipt)
{% endcontent-ref %}

{% content-ref url="/pages/6EG2G5vp6aKlsE9amOUR" %}
[Enumeration values](/api-reference/rest-api/query/enumeration-values)
{% endcontent-ref %}

{% endcolumn %}
{% endcolumns %}


# Account profile

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/Query/AccountProfile>

{% tabs %}
{% tab title="Sample Request" %}

```clike
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "AccountProfileQryResult": {
    "AccountProfile": {
      "AccountCode": "EP9116875",
      "AccountName": "EP DEV ACCT",
      "AutoSchedule": true,
      "AutoSettle": true,
      "AutoSettleHour": 0,
      "AutoSettleMinute": 0,
      "BatchReport": false,
      "DateCreated": "2024-12-01T11:19:01.000Z",
      "DateModified": "2024-12-01T11:19:01.000Z",
      "ID": 205,
      "IndustryCode": "",
      "TimeZone": "Dateline Standard Time",
      "TransReport": false
    },
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "RespMsg": "Successfully Returned Account profile for Account ID 205"
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}

{% endtab %}
{% endtabs %}


# ACH transactions

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/Query/ACHTransaction>

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "Query": "(H=1405)"
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ACHTransaction_QueryResult": {
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "NumRecords": 1,
    "RespMsg": "Successfully Returned Transaction Records : 1",
    "Transactions": [
      {
        "AcctHolderID": 1127,
        "AcctLast4": "0277",
        "AcctType": "PersonalChecking",
        "Amt": 30.5,
        "AuthID": "69019079",
        "BatchLogID": 0,
        "BatchNO": 112,
        "BatchStatus": "N",
        "ChangedBy": null,
        "ChangedOn": "2024-12-01T11:19:01.000Z",
        "ConsentID": 0,
        "CreatedBy": "Token 37564",
        "CreatedOn": "2024-12-01T11:19:01.000Z",
        "Credits": 0,
        "CustName": "APIACH Sally",
        "EndCustID": 35348,
        "FirstName": "Sally",
        "ID": 1405,
        "LastName": "APIACH",
        "MerchID": 1,
        "Origin": "API       ",
        "REF_ID": "A97689#",
        "RPGUID": "adf98580-b4ab-42fc-bb99-01c89964afe9",
        "RefTxID": 0,
        "ResolvedOn": "2024-12-01T11:19:01.000Z",
        "ReturnReason": "",
        "SettledOn": "2024-12-01T11:19:01.000Z",
        "TXN_DATETIME": "2024-12-01T11:19:01.000Z",
        "TXstamp": "20240703",
        "TxSTATUS": "OPEN",
        "TxType": "ACHDEBIT",
        "UniqueID": "167901CDE082BC57",
        "UserID": 0,
        "ValMsg": "Success"
      }
    ]
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**Query** string <mark style="color:purple;">optional</mark>

A query string for obtaining specific transaction records using Number's query language. Build logical terms and join them with '&&' for logical AND or '||' for logical OR. Use single quotes for text and date values. Refer to the variable chart for query composition:

* A: MERCHANT ID - The merchant record you are interested in, e.g. (A=1).
* B: TRANSACTION STATUS - The status of the transaction, e.g. (B=1).
  * -1: ALL
  * 1: OPEN
  * 2: SETTLED
  * 3: FAILED
  * 4: RETURNED
  * 5: VOID
* C: DATE CREATED - The date the transaction was created, e.g. (C>='7/5/2024 12:00:00 AM').
* D: LAST NAME - Last name of the account holder, e.g. (D LIKE '%MITH') for all names that end with 'MITH'.
* E: TRANSACTION LOCK - Lock status of the transaction, e.g. (E<>'0') for locked transactions.
* H: TRANSACTION ID - The unique identifier for the transaction, e.g. (H=58258).
* J: FIRST NAME - First name of the account holder, e.g. (J LIKE 'ROB%') for all names that start with 'ROB'.
* K: TRANSACTION TYPE - The type of transaction, e.g. (K=-1).
  * -1: ALL
  * 1: ACHDEBIT
  * 2: ACHCREDIT
* L: AMOUNT - The $ amount of the transaction, e.g. (L>100.00).
* M: CLIENT REFERENCE ID - User-defined value on the transaction.
* N: RPGUID - User-defined value on the transaction.
* P: CONSENT ID - The Consent ID of card on file the transactions were charged against, e.g. (P=15875).
* Q: ACCOUNT NUMBER LAST 4 - The last 4 digits of a credit card, e.g. (Q='4123').
* R: APPROVAL CODE - The approval code for the transaction, e.g. (R='TAS626').
* S: CUSTOMER LAST NAME - The last name of the customer, e.g. (S='SMITH').
* T: CUSTOMER FIRST NAME - The first name of the customer, e.g. (T='FOSTER').
* U: ORIGIN - The origin of the transaction, e.g. (U='API').
  * "API": REST / SOAP API
  * "WID": Widget
  * "VT": Virtual Terminal

Example: `(B=3)&&(E=1)&&(C>'2024-09-01')`
{% endtab %}
{% endtabs %}


# Annual Consent Receipt Query

<mark style="color:orange;">post:</mark> <mark style="color:$info;"><https://easypay5.com/APIcardProc></mark><mark style="color:$info;">Number</mark><mark style="color:$info;">/v1.0.0/Query/ConsentAnnualReceipt</mark>

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "ConsentID": 2,
  "ReceiptType": 2
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ConsentAnnualReceiptQryResult": {
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "ReceiptHtml": "html",
    "RespMsg": "Successfully Returned Transaction Receipt Markup"
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}
{% endtabs %}


# Batch logs

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/Query/BatchLog>

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "Query": "(C>='7/19/2023')&&(C<'7/20/2023')"
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "Batch_Log_QueryResult": {
    "BatchLogs": [
      {
        "BatchAmt": 110,
        "BatchClose": "020224054035",
        "BatchNO": 512,
        "BatchOpen": "020224054031",
        "BatchRecs": 3,
        "Code": "A",
        "CreatedBy": "AUTOSCHED",
        "CreatedOn": "2024-12-01T11:19:01.000Z",
        "FinishedOn": "2024-12-01T11:19:01.000Z",
        "ID": 612,
        "MerchID": 3,
        "Released": 0,
        "SettleResp": "APPROVAL Batch:512:Recs:3:$110.00",
        "TxLOCK": "7A639CD720CE4B14"
      }
    ],
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "NumRecords": 9,
    "RespMsg": "Successfully Returned Batch Log Records : 9"
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**Query** string <mark style="color:purple;">optional</mark>

A query string for obtaining specific batch log records using Number's query language. Build logical terms and join them with '&&' for logical AND or '||' for logical OR. Use single quotes for text and date values. Refer to the variable chart for query composition:

* A: MERCHANT ID - The merchant record you are interested in, e.g. (A=545).
* B: STATUS - The status of the batch log, e.g. (B=-1).
  * -1: ALL
  * 1: FAILED
  * 2: APPROVED
* C: CREATED ON - The date the batch log was created, e.g. (C>='3/2/2024')&&(C<='4/2/2024').
* D: BATCH LOG ID - The unique identifier for the batch log, e.g. (D=1777).
* E: BATCH NUMBER - The batch number for the batch log, e.g. (E=185).

Example: `(B=1)&&(C>='3/2/2024')&&(C<='4/2/2024')`
{% endtab %}
{% endtabs %}


# Consent Annual Full Detail

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/Query/ConsentAnnual\\_FullDetail>

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "ConsentID": 12
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ConsentAnnual_FullDetailResult": {
    "AccounttHolder": {
      "AccountNum": "",
      "AcctMask": "4111XXXXXXXX1111",
      "Address1": "123 Fake St.",
      "Address2": "",
      "CardType": "VI",
      "City": "PORTLAND",
      "Company": "",
      "CreatedOn": "\/Date(1549853386493-0500)\/",
      "Email": "robert@easypaysolutions.com",
      "ExpDate": "1022",
      "Firstname": "Sean",
      "ID": 1,
      "LastChanged": "\/Date(1555496226490-0400)\/",
      "LastName": "Wood",
      "MerchID": 1,
      "Phone": "8777248472",
      "State": "ME",
      "Zip": "04106"
    },
    "ConsentAnnual": {
      "AcctHolderFirstName": "JOHN",
      "AcctHolderID": 1,
      "AcctHolderLastName": "DOE",
      "AcctNo": "1111",
      "AuthTxID": 15,
      "CreatedBy": "vidya_Venkatraman",
      "CreatedOn": "\/Date(1549942786773-0500)\/",
      "CustID": 15,
      "CustomerRefID": "A12345NO-99",
      "EndDate": "\/Date(1581483600000-0500)\/",
      "ID": 12,
      "IsEnabled": true,
      "LimitLifeTime": 1000000.0000,
      "LimitPerCharge": 1000000.0000,
      "MerchID": 1,
      "NumDays": 365,
      "RPGUID": "",
      "ServiceDescrip": "",
      "StartDate": "\/Date(1549947600000-0500)\/"
    },
    "EndCustomer": {
      "Address1": "21 ELM ST.",
      "Address2": "          ",
      "City": "TULSA     ",
      "ClientRefID": "A12345NO-99",
      "Company": "",
      "CreatedOn": "\/Date(1549942786770-0500)\/",
      "Email": "",
      "Firstname": "JOHN",
      "ID": 15,
      "LastChanged": "\/Date(1549942786770-0500)\/",
      "LastName": "DOE",
      "MerchID": 1,
      "Phone": "",
      "Service": "",
      "State": "          ",
      "Zip": "98324          "
    },
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "RespMsg": "Successfully Returned Full Detail For Consent ID : 12"
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}
{% endtabs %}


# Consent Annual Query

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/Query/ConsentAnnual>

Use this call to determine if the purchaser has a card on file. If you have created the consent (card on file) using a reference ID or PatientID then you can use the following Query to return an array of Consents ( Card On File Info ) for a particular patient with this PatientID:\
(F='213456')&&(H=1)&& (C>='01/21/2024')&#x20;

This will return consents with a particular PatientID which are still enabled and have not yet expired ( use todays date ).

You will want to present the user with the last 4 digits of each stored card so they can decide to choose a stored card or simply enter a new one. Number offers multiple ways of querying consent data.

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "Query": "(A=-1)&&(G=1)&&(H='True')"
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ConsentAnnual_QueryResult": {
    "Consents": [
      {
        "AcctHolderFirstName": "JOHN",
        "AcctHolderID": 1,
        "AcctHolderLastName": "DOE",
        "AcctNo": "1111",
        "AuthTxID": 15,
        "CreatedBy": "John_Doe",
        "CreatedOn": "2024-12-01T11:19:01.000Z",
        "CustID": 15,
        "CustomerRefID": "A12345NO-99",
        "EndDate": "2024-12-01T11:19:01.000Z",
        "ID": 12,
        "IsEnabled": true,
        "LimitLifeTime": 1000000,
        "LimitPerCharge": 1000000,
        "MerchID": 1,
        "NumDays": 365,
        "RPGUID": "adf98580-b4ab-42fc-bb99-01c89964afe9",
        "ServiceDescrip": "",
        "StartDate": "2024-12-01T11:19:01.000Z"
      }
    ],
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "NumRecords": 2,
    "RespMsg": "Successfully Returned Consent Records : 2"
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}
{% endtabs %}


# Consent Annual Query APR

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/ConsentAnnual/QueryApr>

Use this call to determine if the purchaser has a card on file. If you have created the consent (card on file) using a reference ID or PatientID then you can use the following Query to return an array of Consents ( Card On File Info ) for a particular patient with this PatientID:\
(F='213456')&&(H=1)&& (C>='01/21/2024')&#x20;

This will return consents with a particular PatientID which are still enabled and have not yet expired ( use todays date ).

You will want to present the user with the last 4 digits of each stored card so they can decide to choose a stored card or simply enter a new one. Number offers multiple ways of querying consent data.

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "Query": "(A=1)&&(J='07e77e99-b16e-4b0f-8935-8d28e3fa28ef')"
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ConsentAnnual_Query_AprResult": {
    "Consents": [
      {
        "AcctFirstName": "MTIP08-1 DMC 13A",
        "AcctLastName": "MTIP08-1 DMC 13A",
        "AcctMask": "5457XXXXXXXX0012",
        "CardExpDate": "1225",
        "CardType": "MC",
        "ConsentType": "A",
        "CreatedOn": "\/Date(1642694960190-0500)\/",
        "CustomerRefID": "197",
        "EndDate": "\/Date(1767157200000-0500)\/",
        "ExpiredConsent": false,
        "ID": 386,
        "IsEnabled": true,
        "LimitLifeTime": 1000.0000,
        "LimitPerCharge": 100.0000,
        "MerchID": 1,
        "ModifiedOn": "\/Date(-62135578800000-0500)\/",
        "RPGUID": "07e77e99-b16e-4b0f-8935-8d28e3fa28ef",
        "Remaining": 1000.0000,
        "StartDate": "\/Date(1642654800000-0500)\/"
      }
    ],
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "NumRecords": 1,
    "RespMsg": "Successfully Returned Consent Records : 1"
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}
{% endtabs %}


# Consent General Query

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/Query/ConsentGeneral>

Query general consent records using specific filter criteria.

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "Query": "(A=-1)&&(G=1)&&(E>='3/29/2023')&&(E<'4/29/2023')"
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ConsentGeneral_QueryResult": {
    "Consents": [
      {
        "AcctHolderFirstName": "Sean",
        "AcctHolderID": 1140,
        "AcctHolderLastName": "Tester",
        "AcctNo": "0055",
        "AuthTxID": 2175,
        "ConsentType": "S",
        "CreatedBy": "Sally_Smith",
        "CreatedOn": "2024-12-01T11:19:01.000Z",
        "CustID": 1165,
        "CustomerRefID": "A1523644",
        "EndDate": "2024-12-01T11:19:01.000Z",
        "ID": 568,
        "IsEnabled": true,
        "MerchID": 1,
        "ModifiedBy": ":",
        "ModifiedOn": "2024-12-01T11:19:01.000Z",
        "NumDays": 2107,
        "RPGUID": "adf98580-b4ab-42fc-bb99-01c89964afe9",
        "ServiceDescrip": "REST Test",
        "StartDate": "2024-12-01T11:19:01.000Z"
      }
    ],
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "NumRecords": 1,
    "RespMsg": "Successfully Returned Consent Records : 1"
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**Query** string <mark style="color:purple;">optional</mark>

A query string for obtaining specific consent records using Number's query language. Build logical terms and join them with '&&' for logical AND or '||' for logical OR. Use single quotes for text and date values. Refer to the variable chart for query composition:

* A: MERCHANT ID - The merchant record you are interested in, e.g. (A=1).
* B: START DATE - The date the consent becomes active, e.g. (B>='10/20/2024').
* C: END DATE - The date the consent expires, e.g. (C<='10/20/2024').
* D: ACCOUNT HOLDER LAST NAME - Last name of the account holder, e.g. (D LIKE '%MITH') for all names that end with 'MITH'.
* E: CREATED ON - The date the consent was created, e.g. (E<='10/20/2024').
* F: CUSTOMER REFERENCE ID - User-defined value on the consent.
* G: CONSENT TYPE - The type of consent, e.g. (G='-1').
  * -1: ALL
  * 1: ANNUAL
  * 2: ONE-TIME
  * 3: RECURRING
  * 4: SUBSCRIPTION
* H: ENABLED - Indicates whether the consent is currently enabled, e.g. (H=1).
* J: RPGUID - User-defined value on the consent.
* K: ACCOUNT HOLDER FIRST NAME - First name of the account holder, e.g. (K LIKE 'ROB%') for all names that start with 'ROB'.
* Z: CONSENT ID - The unique identifier for the consent, e.g. (Z=15875).

Example: `(G=1)&&(B>'10/20/2024')`
{% endtab %}
{% endtabs %}


# Consents Expiring Cards

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/Query/ConsentsExpiringCards>

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "NumDays": 20
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ConsentsExpiringCardsResult": {
    "Consents": [
      {
        "AcctHolderFirstName": "Bruce",
        "AcctHolderID": 78,
        "AcctHolderLastName": "Wayne",
        "AcctNo": "5439",
        "CardExpDate": "/Date(1703998800000-0500)/",
        "CardExpDateMMYY": "1228",
        "ConsentType": null,
        "CreatedBy": "Savannah_Tester",
        "CreatedByOrigin": "API",
        "CreatedOn": "/Date(1695651051350-0400)/",
        "CustID": 77,
        "CustomerRefID": "modify",
        "EndDate": "/Date(1727150400000-0400)/",
        "ID": 55,
        "IsEnabled": true,
        "MerchID": 3,
        "ModifiedOn": "/Date(1695651058587-0400)/",
        "RPGUID": "ConsentSubscription_Modify",
        "ServiceDescrip": "API Modify",
        "StartDate": "/Date(1695614400000-0400)/"
      },
      {
        "AcctHolderFirstName": "Bruce",
        "AcctHolderID": 90,
        "AcctHolderLastName": "Wayne",
        "AcctNo": "5439",
        "CardExpDate": "/Date(1703998800000-0500)/",
        "CardExpDateMMYY": "1228",
        "ConsentType": null,
        "CreatedBy": "Savannah_Tester",
        "CreatedByOrigin": "API",
        "CreatedOn": "/Date(1695733920813-0400)/",
        "CustID": 89,
        "CustomerRefID": "modify",
        "EndDate": "/Date(1727236800000-0400)/",
        "ID": 65,
        "IsEnabled": true,
        "MerchID": 1,
        "ModifiedOn": "/Date(1695733935477-0400)/",
        "RPGUID": "ConsentSubscription_Modify",
        "ServiceDescrip": "API Modify",
        "StartDate": "/Date(1695700800000-0400)/"
      },
      {
        "AcctHolderFirstName": "Test Card 15",
        "AcctHolderID": 843,
        "AcctHolderLastName": "UAT USA",
        "AcctNo": "0133",
        "CardExpDate": "/Date(1703998800000-0500)/",
        "CardExpDateMMYY": "1228",
        "ConsentType": null,
        "CreatedBy": "Savannah_Tester",
        "CreatedByOrigin": "SDK",
        "CreatedOn": "/Date(1700592744063-0500)/",
        "CustID": 862,
        "CustomerRefID": "",
        "EndDate": "/Date(1728964800000-0400)/",
        "ID": 427,
        "IsEnabled": true,
        "MerchID": 6,
        "ModifiedOn": "/Date(1703609621300-0500)/",
        "RPGUID": "",
        "ServiceDescrip": "",
        "StartDate": "/Date(1700542800000-0500)/"
      }
    ],
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "NumRecords": 3,
    "RespMsg": ""
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}
{% endtabs %}


# Consents Expiring Cards 01

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/Query/ConsentsExpiringCards\\_01>

Query general consent records using specific filter criteria.

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "StartDate": "7/10/2023",
  "EndDate": "8/9/2023"
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ConsentsExpiringCards_01Result": {
    "Consents": [
      {
        "AcctHolderFirstName": "Sally",
        "AcctHolderID": 541,
        "AcctHolderLastName": "Smith",
        "AcctNo": "5439",
        "CardExpDate": "/Date(1706677200000-0500)/",
        "CardExpDateMMYY": "0128",
        "ConsentType": null,
        "CreatedBy": "Savannah_Tester",
        "CreatedByOrigin": "WID",
        "CreatedOn": "/Date(1697832095713-0400)/",
        "CustID": 548,
        "CustomerRefID": "12345",
        "EndDate": "/Date(1706677200000-0500)/",
        "ID": 271,
        "IsEnabled": true,
        "MerchID": 3,
        "ModifiedOn": "/Date(-62135578800000-0500)/",
        "RPGUID": "54321",
        "ServiceDescrip": "",
        "StartDate": "/Date(1697774400000-0400)/"
      }
    ],
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "NumRecords": 1,
    "RespMsg": ""
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}
{% endtabs %}


# Enumeration values

Methods related querying general information such as enum values

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/Query/Enum>

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "Query": "TXStatus"
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "Enum_QueryResult": {
    "EnumItems": [
      {
        "EnumText": "ALL",
        "EnumValue": -1
      }
    ],
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "RespMsg": "Successfully Returned Enum Records : 6"
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**Query** string · enum <mark style="color:purple;">optional</mark>

The enumeration type to query.

Example: `TXStatus`

Possible values: `ACHStatus`

`ACHType`

`AConsentType`

`BatchSettleMode`

`BatchSettleStatus`

`ConsentType`

`IntAction`

`IntlAction`

`IntlResult`

`IntlStatus`

`Period`

`ReceiptType`

`Recipient`

`RecurSchedStatus`

`TxStatus`

`TxType`
{% endtab %}
{% endtabs %}


# Receipt Details

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/Query/ReceiptDetail>

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "TxID": 12
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ReceiptDetail_QueryResult": {
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "ReceiptInfo": {
      "AC": null,
      "AID": "A0000000031010",
      "ARC": "00",
      "AcctHolderID": 1,
      "CardHolder": "Sean Wood",
      "CardNumber": "1111",
      "CardType": "VI",
      "EndCustID": 12,
      "EndCustomer": "JOHN DOE",
      "EntryType": "MANUAL",
      "MerchAddress": "45 spring street",
      "MerchCity": "portland",
      "MerchDescrip": "Test Merchant 1",
      "MerchEmail": "vidya",
      "MerchNumber": "700000000768",
      "MerchPhone": "2078548547",
      "MerchState": "Maine",
      "MerchTID": null,
      "MerchZip": "04101",
      "RefID": "",
      "TSI": "F800",
      "TVR": 8000,
      "TxAmount": 0,
      "TxDateTime": "2024-12-01T11:19:01.000Z",
      "TxID": 12,
      "TxStatus": "OPEN",
      "TxType": "CCAUTHONLY",
      "TxnCode": "297620"
    },
    "RespMsg": "Successfully Returned Receipt Detail for TxID 12"
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**TxID** integer <mark style="color:purple;">optional</mark>

Transaction ID for which to retrieve the receipt details

Example: `12`
{% endtab %}
{% endtabs %}


# Reconcile

Reconcile transactions

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/Query/Reconcile>

The reconcile Query is designed to be called at a specific periodic interval, perhaps once per day. We will return all the unique transaction IDs encountered during that interval. The query allows you to reconcile this list with data you have gathered during cardholder data interactions such as PayForm or Verifone Activity. If you find that a particular transaction is missing in your database you can call the TRANSACTION FULL DETAIL to consume any missing information.

You may specify either Credit Card or ACH transactions to be returned in the Query ( see qType parameter ) use "CARD" or "ACH". When choosing dates you can consider the StartDate to be Included in your data request however the EndDate will not. You will receive all data which runs up to but not including the end date. For example choosing the following dates will provide data for a single day on the calendar: "2024-12-01" "2024-12-02"

IMPORTANT: Do not call this method more than once a day. Excessive queries can cause your endpoint to be blocked. The max date range for this method is 31 days. The max records returned is 20,000. If you notice that the NumRecords returned equals 20000 then this means you have maxed out your query and you should use a smaller date range.

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "StartDate": "2024-12-01T00:00:00.000Z",
  "EndDate": "2025-01-01T00:00:00.000Z",
  "qType": "CARD"
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ReconcileResult": {
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "NumRecords": 1,
    "RespMsg": "Successfully Returned Transaction Records : 1",
    "Transactions": [
      {
        "AMOUNT": 10,
        "CreatedOn": "2024-12-01T11:19:01.000Z",
        "Origin": "API",
        "TxID": -1,
        "TxSTATUS": "OPEN"
      }
    ]
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**StartDate** object <mark style="color:purple;">optional</mark>

The start date

Example: `2024-12-01T00:00:00.000Z`

***

**EndDate** object <mark style="color:purple;">optional</mark>

The end date

Example: `2025-01-01T00:00:00.000Z`

***

**qType** string <mark style="color:purple;">optional</mark>

Type of transactions returned

Example: `CARD`
{% endtab %}
{% endtabs %}


# Recurring Consents

<mark style="color:orange;">post:</mark> <https://easypay5.com/APIcardProcNumber/v1.0.0/Query/ConsentRecurring>

{% tabs %}
{% tab title="Sample Request" %}

```clike
{
  "Query": "(E>='12/01/2023')&&(E<'12/31/2023')"
}
```

{% endtab %}

{% tab title="Sample Response" %}

```clike
{
  "ConsentRecurring_QueryResult": {
    "Consents": [
      {
        "AcctHolderFirstName": "VI",
        "AcctHolderID": 1040,
        "AcctHolderLastName": "VI",
        "AcctNo": "8888",
        "AuthTxID": 1835,
        "CreatedBy": "Tester Savannah",
        "CreatedOn": "2024-12-01T11:19:01.000Z",
        "CustID": 1062,
        "CustRefID": "",
        "EndDate": "2024-12-01T11:19:01.000Z",
        "ID": 522,
        "IsEnabled": true,
        "MerchID": 1,
        "ModifiedBy": ":",
        "ModifiedOn": "2024-12-01T11:19:01.000Z",
        "RAmtPaidSoFar": 300,
        "RLastPaymentAmt": 75,
        "RNumPayments": 4,
        "RPGUID": "adf98580-b4ab-42fc-bb99-01c89964afe9",
        "RPaymentAmt": 75,
        "RPeriod": "WEEKLY",
        "RTotalAmt": 300,
        "ServiceDescrip": "",
        "StartDate": "2024-12-01T11:19:01.000Z"
      }
    ],
    "ErrCode": 0,
    "ErrMsg": "",
    "FunctionOk": true,
    "NumRecords": 4,
    "RespMsg": "Successfully Returned Consent Records : 4"
  }
}
```

{% endtab %}

{% tab title="Header Parameters" %}
**SessKey** string <mark style="color:orange;">required</mark>

A unique session key used for authentication in API calls. This key is generated upon successful authentication and must be included in all subsequent requests.

Example: `A1842D663E9A4A72XXXXXXXX303541303234373138`

***

**Content-Type** string <mark style="color:orange;">required</mark>

Example: `application/json`

***

**Accept** string <mark style="color:orange;">required</mark>

Example: `application/json`
{% endtab %}

{% tab title="Body" %}
**Query** string <mark style="color:purple;">optional</mark>

A query string for obtaining specific consent records using Number's query language. Build logical terms and join them with '&&' for logical AND or '||' for logical OR. Use single quotes for text and date values. Refer to the variable chart for query composition:

* A: MERCHANT ID - The merchant record you are interested in, e.g. (A=1).
* B: START DATE - The date the consent becomes active, e.g. (B>='10/20/2024').
* C: END DATE - The date the consent expires, e.g. (C<='10/20/2024').
* D: ACCOUNT HOLDER LAST NAME - Last name of the account holder, e.g. (D LIKE '%MITH') for all names that end with 'MITH'.
* E: CREATED ON - The date the consent was created, e.g. (E<='10/20/2024').
* F: CUSTOMER REFERENCE ID - User-defined value on the consent.
* G: CONSENT TYPE - The type of consent, e.g. (G='-1').
  * -1: ALL
  * 1: ANNUAL
  * 2: ONE-TIME
  * 3: RECURRING
  * 4: SUBSCRIPTION
* H: ENABLED - Indicates whether the consent is currently enabled, e.g. (H=1).
* J: RPGUID - User-defined value on the consent.
* K: ACCOUNT HOLDER FIRST NAME - First name of the account holder, e.g. (K LIKE 'ROB%') for all names that start with 'ROB'.
* Z: CONSENT ID - The unique identifier for the consent, e.g. (Z=15875).

Example: `(G=1)&&(B>'10/20/2024')`
{% endtab %}
{% endtabs %}




---

[Next Page](/llms-full.txt/1)

