Espago - Introduction to Documentation

Introduction home

link Try now

Try out how the Espago API works. Charge your first client followind these steps.

In the first step an iFrame is created, which serves the purpose of sending credit card information to the Espago Gateway. It then fetches the credit card token and submits it to a form.
You can use a mock credit card: 4242 4242 4242 4242, with the expiry date of 02/2025. The CVV code does not matter.
Try it on your own
<!-- iFrame Configuration -->
<script 
  async=""
  data-id="EspagoFrameScript"
  data-key="VrYVaA1CjmRooKh63YYv"
  data-live="false"
  data-button="Pay"
  src="https://js.espago.com/iframe.js">
</script>

<!-- Form with the credit card token -->
<form id="espago_form" 
      action="/charge_client" 
      accept-charset="UTF-8" 
      method="post">
</form>
Next, the true request is sent to the Espago gateway. It consists of user information, the charged amount and currency among other information. Card input contains the credit card token generated by the IFrame.
curl -i https://sandbox.espago.com/api/charges \
 -H "Accept: application/vnd.espago.v3+json" \
 -u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
 -d "amount=10" \
 -d "currency=pln" \
 -d "card=[card_token]" \
 -d "description=Espago docs"
Here is how the response will look like. It is sent using JSON formatting. Id and state are pivotal. More on back requests
{
 "id":"pay_7715NocOaPcNTL9O",
 "description":"Espago docs", 
 "channel":"elavon",
 "amount":"10.00",
 "currency":"pln",
 "state":"executed",
 [...]
}

link Gateway Description

Security

In order to ensure a certain level of security is maintained, it is highly advised to use SSL (HTTPS) certificates on the merchants site. In every viable way of integrating, sensitive data regarding credit cards are sent directly from the client to the Espago gateway, excluding the Merchant’s site. This solution frees the Merchant from the responsibility associated with storing or processing credit card information, while PCI-DSS certification stays limited to filling out a questionnaire after signing a contract with Elavon.

The Architecture of Our API

Our API follows the principles of the REST architectural style. Every operations related to payment managment (status checks etc) have to be perfomed using API Requests (Application Programming Interface) - this very documentation focuses on explaining how to make use of our API. UTF-8 encoding is required in sent data. The API always generates answers in the JSON format.

Request time

A 40 second timeout (the maximal amount of time your site will wait for a response from Espago) is recommended for API requests, although the large majority of payments get processed in less than 2 seconds. We suggest to avoid calling any recurring payments at 3:30-5:30 CEST (01:30- 03:30 UTC) on working days, since we may be performing maintanance work on the Espago gateway.

link Integration methods

There are three ways of integrating with the Espago gateway for payments:

Attaching the iFrame to the merchant’s site


Using the iFrame script (for gathering credit card data) or a form with the use of Espago JS and performing the necessary payment operations through API requests (Read more)

Redirecting clients to the Espago Secure Web Page


Redirecting clients with proper payment parameters. Receiving the response from the Espago gateway and taking care of the user, who’s redirected back to the mechant’s site. (Read more)

Integration through the Przelewy24 system

Espago/Elavon card payments can be one of many or the only payment method available for clients in Przelewy24. In this case integration with the Espago gateway is not necessary. The mechant has to integrate his site only with the Przelewy24 module.

This solution is greatly beneficient when:

  • The merchant is also interested in receiving payments through regular/fast bank transfers
  • The merchant uses a premade online store system (PrestaShop, Magento i inne) and is focused on quick and simple one-time payments
  • The mechant already uses Przelewy24

link Changes and requirements resulting from PSD2

The Espago gateway provides the functions and mechanisms necessary to process payments in compliance with the PSD2 directive. From the perspective of merchants using card payments, the new requirements primarily include two elements:

1. Every online payment initiated by the customer utilizes strong customer authentication (SCA) provided by 3-D Secure;
2. Every subscription or card-on-file registration begins with an SCA payment, and subsequent payments are appropriately marked.

Failure to implement SCA will result in increased payment rejections for cards issued by European banks. It is the responsibility of the merchants to verify and adapt their integration to meet the new requirements.

  1. If you are currently using APIv3 with 3D Secure enabled for one-time payments, no changes are required.
  2. If you already process recurring payments using the “cof=storing” flag (feature added in August 2019), you most likely do not need to make any changes.
  3. If your application uses APIv3 without utilizing 3D Secure, this security feature must be enabled and used for all one-time payments and recurring payments.
  4. If you are still using the old APIv2, a migration to APIv3 is necessary.
  5. If you initiate recurring payments by creating a client profile with a separate request and double authorization, you need to modify the customer registration process to incorporate SCA.

PSD2-Related Change Checklist

To ensure compliance with PSD2 requirements regarding card acceptance, please perform the following checks:

Question Scope Response: YES
List of potential changes
Response: NO
List of potential changes
1. Is your integration based on Espago API v3? Applies to all clients. To verify if your integration uses API v3, check if you’re applying the appropriate request headers. Yes - proceed to check if requirements from subsequent points are fulfilled; No - you need to integrate with API v3: migrate from API v2;
2. Are all cardholder-initiated payments (CIT) using strong customer authentication (SCA)? Applies to all services. Strong customer authentication is provided through the 3-D Secure mechanism offered by Espago. Yes - requirement fulfilled; No - changes are required:

- If API requests include the “skip_3ds” parameter for exemptions, it should be removed. If strong authentication is not possible due to the nature of the payment, utilize the moto mechanism (use the “moto” parameter in the API request).
3. Are recurring, card-on-file, and merchant-initiated payments (MIT) preceded by strong customer authentication at the initiation stage? Applies to services utilizing mechanisms such as:

- Espago Subscriptions

- Recurring, card-on-file, and other payments based on the card on file (COF) mechanism.
Yes - requirement fulfilled; No - you need to adjust the payment process to comply with the requirements described in the Multiple Payments or Espago Subscriptions section, depending on the mechanism used.
Significant change - Client Profile (which can be used for subsequent charges) is created during the initiating payment with the cof=storing parameter, utilizing SCA. There is no need to create it with a separate client profile request.
4. Was the client profile previously created based on the card token, before the first payment? Applies to payments made using a saved client profile (including Espago Subscriptions). Yes - changes are required to align with the requirements described in the Recurring Payments or Espago Subscriptions section. Although it is still possible to create a client profile without invoking SCA payment, in such cases, the first payment using that profile must utilize SCA or be marked as MOTO (it cannot be a recurring payment with the cof=recurring parameter). No - if a client profile created using the cof=storing payment is utilized, the requirement is fulfilled.
5. Have you previously used the automatic card authorization mechanism (option selected in the secure.espago.com panel) when creating a client card token? Applies to payments made using a saved client profile (including Espago Subscriptions). Yes - you need to discontinue this option.

We have introduced a different mechanism that allows you to determine whether a profile can be used for payments: If a client profile was created based on an SCA payment, it includes the sca_payment parameter, indicating a successfully authenticated payment. This serves as the basis for using the client profile for recurring and multiple charges. If the parameter is absent, the profile is not suitable for charges other than cardholder-initiated (with SCA) or MOTO payments.
No - requirement fulfilled;
6. Did the initial payment with 3DS or authorization return immediately upon saving the client card? Applies primarily to merchants with recurring payments starting from a free trial period. Yes - you need to modify the integration so that the initial SCA/3DS payment is not immediately reversed. Reversing the payment will be interpreted by the bank as revoking the customer’s consent for subsequent charges. To save the client card without charging it, use the cof=storing payment with an amount of 0 currency units. No - no changes are necessary;

Integration assignment

link Integration process

Features which should be tested during the integration include:

  • the creation of tokens,
  • charging cards/creating payments
  • displaying the reason of rejection to customers, when the payment is not successful,
  • obtaining information about payment status,
  • Reversal and refunding of the transaction (no need to implement these features at the beginning, but it’s very useful to test curl queries),
  • The creation of customer profiles and managing them (if there is business need, for example in recurring payments or in stores where the customer returns and purchases can be repeated)
  • recieving back-requests

Transitioning to the second and at the same time the last integration step requires you to firstly test your web application in the test environment and submit it to our Support Team for further inspection of your integration (espacially concerning the payment form).
The list of technical and general requirements of Elavon is available in this documentation under the ‘Downloads’ section. A test environment that can be used for viewing and setting parameters or inspecting test payments, requests and responses is available here: https://sandbox.espago.com

In order to switch over to the production environment you have to alter the connection parameters - 5 of them need to be changed:

  1. Gateway address
  2. App ID
  3. API password
  4. Public key
  5. the value of the ‘live’ parameter in the Espago constructor

After integrating into the production environment, the test environment still remains available to use for our clients. At the request of the Seller, the Espago Team can:

  • Add a new service within the Seller’s account (eg. For any currencies)
  • Enable / disable the ability to create and use plans and subscriptions (disabled by default)
  • Enable / disable 3D-Secure (enabled by default) or DCC (disabled by default)
  • Create a new user with access to the panel
  • Provide answers and help solving problems associated with integration

In the case of problems with compability we recommend reading this: detailed compatibility requirements

link First steps

After gaining access to the Merchant Panel, the following steps should be taken:

  1. Navigate to this page:
  2. Click on the ‘Edit’ button to access the site editing panel
  3. Fill in the ‘API password’ and ‘API password confirmation’ inputs - their value is responsible for the correct authorisation of your account and must not be shared with unauthorised persons. You have to also fill in the ‘Email BOK’ field
  4. Accept the changes by clicking on ‘Submit’.

Clicking on the ‘Show’ button should yield a similar result:

link Required request headers

For correct API requests, the following HTTP headers are used:

Headers Required Value
Authorization1 Required Basic app_id:password
Accept Required application/vnd.espago.v3+json

Requests for token creation are authorised with the use of a Public Key and for most services it is handled by Espago JS.
A series of unsuccessful log in attempts results in the account getting temporarily blocked.


Authorization1 - with the parameters of: APP_ID and the password fetched in the “First Steps” section. It concerns all API requests except for token creation.

link Test Cards Data

While testing your integration you need to use the data of the test cards mentioned below. To acheive successful or declined transaction you have to indicate specific card validation date and CVV - see the second and the third table below.

The use of real credit cards is forbidden.

Card number Brand Currency 3-D Secure DCC Required use during integration
4012000000020006 Visa PLN 3DSv2.1.0
Challenge
No Yes
For one time payment and cof=storing
4916978838794412 Visa PLN 3DSv2.1.0
Frictionless: OK
No Yes
4556914091330789 Visa PLN 3DSv2.1.0
Frictionless: Reject
No Yes
5432670000041258 Mastercard PLN Mastercard SecureCode No Yes
4242424242424242 Visa PLN Yes No Yes
4012001037141112 Visa PLN Verified by Visa No No
Since 2022-10 3DSv1 is disabled
375987000000005 American Express PLN Amex SafeKey No If Amex cards expected
4012888888881881 Visa USD Verified by Visa Yes If DCC expected
5555555555554444 Mastercard HKD Mastercard SecureCode Yes If DCC expected
4242421111112239 Visa HKD No Yes If DCC expected
4917484589897107 Visa PLN No No If COF payments expected
- this card requires CVV code
usage in every transaction.
Not suited for the subscriptions
and COF=recurring payments
4916978838794412 Visa PLN 3DSv2.1.0
[Frictionless OK]
No Recommended
4556914091330789 Visa PLN 3DSv2.1.0
[Frictionless Reject]
No Recommended
4012000000020006 Visa PLN 3DSv2.1.0
[Challenge]
o Yes, when testing cof=storing
4012001038443335 Visa PLN 3DSv2.1.0
Frictionless: OK
No No
6771798021000008 Maestro PLN 3DSv2.2.0
Frictionless: OK
No No



The year of expiry is not important as long as it is a future date. You control the outcome of the payment by altering the month of expiry. Thanks to this feature, you are able to test both positive and negative scenarios.

Month (expiration date) Result Issuer response code
01-05 Transaction accepted 00
06 Random outcome, 50% chance of succeeding.
Useful while testing recurring payments.
n/a
07 Transaction rejected 04, 07, 41, 43
08 Transaction rejected 51
09 Transaction rejected 13
10 Transaction rejected 00
11 Transaction rejected 54
12 Transaction rejected 05, 57, 61



CVV code Result in the test gateway
683 Incorrect CVV. Transaction will be rejected due to incorrect CVV.
Other CVVs Correct CVV.


Rejection code control

Card 4012001038443335 allows Merchant to control rejection codes through transaction amount.
The rejection code takes the value of the transaction amount after the decimal point, for example:

Decimal value Rejection code
n.04 04
n.51 51
n.43 43
n.65 65

Where n is a natural number.

link Test connection

To check your connection with Espago API You should send a request to https://sandbox.espago.com/api/test. In response you’ll get parameter state - value passed mean that your connection is configurated properly. Value failed means incorrect connection - then table warnings contains information about reasons of rejection.

Example request

curl -i https://sandbox.espago.com/api/test \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
        request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new(user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD')
response = client.send('api/test', method: :post)
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/test');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');

curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);
{
  "state":"passed",
  "warnings":[]
}
{
  "state":"failed",
  "warnings":[
    {
      "title":"Access denied",
      "message":"Wrong app_id or password."
    },
    {
      "title":"Wrong request headers",
      "message":"Check your 'Accept' header."
    },
        . . .
  ]
}

Secure web page exit_to_app

link Payment initialization

There are two ways to initiate a payment using the secure payment page:
1. HTML form request - by sending from the user’s browser a form containing payment data and a checksum to the / secure_web_page address;
2. Registering the payment in API - registering the payment through sending a POST request to the Espago API endpoint: / api / secure_web_page_register. After registering the payment, it is necessary to redirect the user to the URL address received in response - in the redirect_url parameter.

link Payment initialized using the HTML form

1. Submitting the form

By clicking on the submit button, the client sends a HTML form with hidden fields containing the payment details, through the POST method, to the Espago gateway and gets redirected to the secure web page.

<form accept-charset="UTF-8" action="https://sandbox.espago.com/secure_web_page" id="espago_secure_web_page" method="post">
  <input name="api_version" type="hidden" value="3" />
  <input name="app_id" type="hidden" value="ms_771eUTliRiZ" />
  <input name="kind" type="hidden" value="sale" />
  <input name="session_id" type="hidden" value="1559655843622983577" />
  <input name="amount" type="hidden" value="10.00" />
  <input name="currency" type="hidden" value="PLN" />
  <input name="title" type="hidden" value="payment_id:294" />
  <input name="description" type="hidden" value="Platność - Jan Kowalski" />
  <input name="positive_url" type="hidden" value="http://example.com/payments/ok" />
  <input name="negative_url" type="hidden" value="http://example.com/payments/bad" />
  <input name="ts" type="hidden" value="1444044688" />
  <input name="checksum" type="hidden" value="938ee2f7729ac4ba1a7c98f5ead8b167" />
  <button name="button" type="submit" class="btn espago-blue pulse">Pay</button>
</form>

2. Charging the client

The client fillings the card data form and the payment with 3-D Secure strong authentication is proceeded. When the authorization is completed, a back request is sent to the merchant service with the authorization details.

3. Redirecting to the merchant

Depending upon the payment status, the client gets redirected to one of the two URLs (for the positive or negative authorization result). The merchant service should display the payment status and if the payment is rejected - also a recejt reason..

link Example form

The Secure Web Page method of payment handles most of thew work for you by redirecting the client to the Espago Gateway where they will enter their credit card data. They then get charged the correct amount and get redirected back to your site. You can see a demo in action here: demo.espago.com

You can use a test card with the number: 4242 4242 4242 4242; and expiry date of 02/2025. The CVV number does not matter. (More on test cards)

link Form parameters

Payment parameters are sent through the POST method on the following URL:

sandbox URL: https://sandbox.espago.com/secure_web_page
URL: https://secure.espago.com/secure_web_page

Parameter Description Required Notes
api_version API version done 3
app_id Application ID done
kind Type of transaction done sale or preauth(hold certain amount of money on customer’s card and charge it later)
session_id merchant session ID/transaction ID done Random, unique character string generated by the Merchant
amount transaction amount done two decimal places, separated by a dot
eg. 10.00, 1.23, 1.20
currency currency done
title transaction description done Payment description - will be displayed as a payment title at the top of payment card form, e.g. ‘Order 123/2019’. Should be between 5 and 100 characters.

The ‘title’ parameter from the form will be available as the payment parameter ‘description’ (eg. in the back request).
description client description Description of the customer, not the payment.
email client’s email E-mail of the client. A confirmation email will be sent to this address.
positive_url URL URL to which the client will be forwarded after the correct transaction processing
negative_url URL URL to which the client will be forwarded in case of a transaction error
locale transaction language pl, en, da, ru, sv
reference_number reference number Trans ref text - visible in Elavon reports. Length up to 20 characters, only alphanumeric and -_ (minus and bottom bar).
channel Payment channel Payment channel for this payment request. Defaut value is “elavon_cc”
ts timestamp done
checksum checksum done MD5 checksum for a string comprised of payment parameters (app_id + kind + session_id + amount + currency + ts + checksum_key). The fields’ separator: “|”




An example of the form:

<form id="espago_secure_web_page" action="https://sandbox.espago.com/secure_web_page" accept-charset="UTF-8" method="post">
  <input type="hidden" name="api_version" value="3" />
  <input type="hidden" name="app_id" value="ms_0CvDQqhnS" />
  <input type="hidden" name="kind" value="sale" />
  <input type="hidden" name="session_id" value="2HWSjEs5G4RcXZjqHqWA" />
  <input type="hidden" name="amount" value="42.94" />
  <input type="hidden" name="currency" value="PLN" />
  <input type="hidden" name="title" value="order_165" />
  <input type="hidden" name="description" value="Transaction - john@smith.com 42.94" />
  <input type="hidden" name="email" value="john@smith.com" />
  <input type="hidden" name="positive_url" value="http://example.com/payments/ok"  />
  <input type="hidden" name="negative_url" value="http://example.com/payments/bad"  />
  <input type="hidden" name="ts" value="1559230283" />
  <input type="hidden" name="checksum"value="532839977fb76ca06ea635c7a936c7db" />
  <div class="button">
    <button name="button" type="submit">Buy now!</button>
  </div>
</form>

link Payment initialization through API request

To initiate a payment using a Secure Web Page, send a request to the API using the POST method, and then redirect the customer to the URL received in the response - in the redirect_url parameter.

The API initialized secure web page payment process:

In this endpoint the same parameters as in API “charge” method are used.

Request params
Ścieżka: /api/secure_web_page_register
Metoda: POST

curl -i https://sandbox.espago.com/api/secure_web_page_register /
-X POST \
-H 'Accept: application/vnd.espago.v3+json' \
-u app_id:password \
-d 'amount=199' \
-d 'currency=PLN' \
-d 'description=Payment_123' \
-d 'kind=sale' \
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new(user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD')
response = client.send(
  'api/secure_web_page_register',
  method: :post,
  body: {
    amount: 199,
    currency: 'PLN',
    description: 'Opis transakcji',
    kind: 'sale',
    service_client_id: 'xxxxxx',
    client_description: 'xxxxx'
  }
)

puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/secure_web_page_register');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "amount=199&currency=PLN&description=Payment_123&kind=sale&service_client_id=xxxxxx&client_description=xxxxx");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'app_id' . ':' . 'password');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);
{
  "id": "pay_IZTq8l_qaHuOHH",
  "description": "Payment_123",
  "amount": "199",
  "currency": "PLN",
  "state": "new",
  "created_at": 1550224439,
  "transaction_id": "tn_CLN2HhetI",
  "redirect_url": "https://sandbox.espago.com/secure_web_page/tn_CLN2HhetI"
}

iFrame open_in_browser

link The functioning of Espago iFrame

EspagoFrame script creates an iframe with a modal window where the customer can enter his credit card data. Next, the data is sent to Espago, and the script returns the token ID to the Merchant’s.
An example of this method of integration can be found on this test site demo.espago.com.

1. Calling the iFrame

In the first step the client calls the Espago iFrame clicking on a button (the call has to be made in your script, by the function called: showEspagoFrame()). Next, the client enters his credit card information, which get sent asynchronously to the Espago gateway in order to generate a token.

 <script src="https://js.espago.com/espago-1.3.js"></script>
 <script 
   async=""
   data-id="EspagoFrameScript"
   data-key="VrYVaA1CjmRooKh63YYv"
   data-live="false"
   data-button="Pay"
   src="https://js.espago.com/iframe.js">
 </script>

 <a id="pay_btn">Zapłać</a>
$('#pay_btn').click( () => {
  showEspagoFrame()
})

2. Receiving tokens

After receiving the token, the Espago script searches for a form with an id of: espago_form, and creates a new input therein: <input type="hidden" id="card_token" name="card_token" value="[TOKEN]">. The form is then submitted to the designated URL.

<form id="espago_form" 
      action="/charge_client" 
      accept-charset="UTF-8" 
      method="post">
</form>

If the token was not used, the CVV code from the token will be automatically removed after a maximum of 2 days from creation, and the entire token after 2 months.

3. Charges

After receiving the token, the Merchant’s server should send a request with the POST method to the following URL: https://sandbox.espago.com/api/charges.

curl -i https://sandbox.espago.com/api/charges \
 -H "Accept: application/vnd.espago.v3+json" \
 -u ms_771eUTliRiZ:SeCreT_P@ssw0rD \    # app_id:pass
 -d "amount=10" \
 -d "currency=pln" \
 -d "card=cc_8a1kqN20X6JYeuD-Y" \    # token
 -d "description=Espago docs"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new(user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD')
response = client.send(
  'api/charges',
  method: :post,
  body: {
    amount: 10,
    currency: 'PLN',
    card: 'cc_8a1kqN20X6JYeuD-Y',
    description: 'Espago docs'
  }
)

puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/charges');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "amount=10&currency=pln&card=cc_8a1kqN20X6JYeuD-Y&description=Espago docs");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);

More on charge parameters

4. The response from Espago

After a successful charge request, Espago returns data about the current payment in JSON formatting. The state parameter is key. executed means that the payment has succeded.
Example of a response from Espago:

{
 "id":"pay_772FThyrtalisvgk",
 "description":"Espago docs",
 "channel":"elavon",
 "amount":"10.00",
 "currency":"pln",
 "state":"executed",
 "client":"cli_772coQy1BaW3F0Zn",
 "created_at":1559649971,
 "card":
 {
  "company":"VI",
  "last4":"4242",
  "year":2020,
  "month":2,
  "first_name":"Adam",
  "last_name":"Kowalski",
  "authorized":null,
  "created_at":1559649956
 },
 "issuer_response_code":"00",
 "reversable":true,
 "transaction_id":"tr_7728ogw8v"
}
More on feedback

5. Response - information for the client

After completing the payment it is necessery to inform your clients about the status of their transaction, together with the reason of rejection (if that is the case). Error codes are available in the ‘Downloads’ section.

link iFrame parameters

Parameter Required? Default value Meaning
async done “” No other values are permitted
data-id done EspagoFrameScript No other values are permitted
src done Script URL No other values are permitted
data-key done String, Merchant’s public key
data-live true String, If ‘true’, then requests are sent to production environment. If set to ‘false’, requests are sent to test environment.
data-lang pl String, Form language (for default labels, placeholders) in ISO 639-1 standard. Available: en, pl, bg, cs, da, de, el, es, et, fi, fr, ga, hr, hu, it, lt, lv, mt, nl, no, pt, ro, ru, sk, sl, sv, ua.
data-success function(data) {} A callback function called when the token gets generated. Caution, defining a callback function disables the default action of our script - the ‘card_token’ field will not be appended to the form.
data - string, a generated token from the Espago gateway.
data-error function(data) {} A callback function called when token generation failed.
data - string; Error code received from the Espago gateway together with a description.
data-onclose function() {} A function called when the user closes the dialogue window (by clicking on ‘x’ or pressing ‘Esc’).
data-target espago_form Name of the form to which the ‘card_token’ field will be appended.
Caution - if you decide to submit the form with the ‘success_callback’ parameter, this action will not take place. The token will be submited to this function.
data-title Add your card (en) Form title.
Note - The default value depends on the language value of ‘data-lang’.
data-subtitle The text displayed below the form title and store name (store name is taken automatically from the API Espago).
data-button Save (en) The label that will be displayed inside the form submitting button.
Note - The default value depends on the language value of ‘data-lang’.
data-styler esp String, Optional form styling. If a special version of the iframe has been prepared for the Merchant, after including the iframe parameter, it will be displayed in the ordered graphic design. The styling option is only available after prior arrangement with Espago.

One-time payment attach_money

link Charge parameters

A new charge is created after a POST request is send to https://sandbox.espago.com/api/charges. The transaction needs to be executed with the use of one of the afformentioned methods of passing on card details (make sure you are sending the apprioprate requests with correct parameters).

Parameter Description Details
description Transaction decription Has to consist of 5 to 99 characters.
amount Transaction amount Floating point number, np. 123.45
currency Currency Three-character long currency symbol, compatible with currently used MID
client client ID ID of a client (when charging an existing client)
card token ID ID of a token (in case of a one-time payment)
channel Payment channel Payment channel for this payment request. Defaut value is “elavon_cc”
recurring [optional]
[deprecated]
Parameter is deprecated, you should use cof=storing instead. Adding parameter “recurring=true” enforces classification of transaction in bank as recurring transaction. This results in not checking the 3D-Secure.
complete [optional] Adding parameter “complete=false” enforces making only reservation of payment. See details in separate chapter.
moto [optional] Adding parameter “moto=true” enforces classification of transaction as MOTO (Mail Order/Telephone Order), for example when hotel owner recieved card number for charge from booking service. This results in the omission of 3D-Secure. Before using please contact the Espago Tech Team, using MOTO need to be playced in agreement betwen Merchant and Acquirer.
cvv [optional] Sending CVV in this format - “cvv=cv_xxxxxxxxxx” enables you to add CVV to a payment processed through an already existing client profile (when the original CVV has been “used”). Details in CVV tokens.
positive_url [optional] URL to which the client will be redirected to after successful payment processing
negative_url [optional] URL to which the client will be redirected to after unsuccessful payment processing
reference_number [optional] Trans ref text - visible in Elavon reports. Length up to 20 characters, only alphanumeric and - (minus and underscore).
locale [optional] Language code in ISO 639-1 standard. Two-letter string value. Language used in web page and/or in email notification. If language is not supported, english is used.
email [optional] E-mail address which the notification about this charge’s result should be sent to. If the parameter is used with a customer profile with an e-mail address, the address sent in this parameter has a priority and is used for sending notification. String variable.
skip_email [optional] Disables email notifications - even if you send a request charge with a customer profile with an email address. Boolean (false/true, default: false).
cof [optional] The use of “Card on file” mechanism. Possible parameter values: storing (saving card data in the form of a client profile, which can be used later for payments with tokens, or (when used with client profile) updating referenced sca_payment in client profile), recurring (information for the bank that this payment is a part of a subscription service, for use in payments processed with the use of a client profile), unscheduled (transaction requested by Merchant, for example customer billing for the service). Details in COF section.
recurring_expiry [optional] This parameter will be used if cof has the value of storing.
The date on which the recurring payment expires (no more charges will be carried out)
Accepted Format: YYYYMMDD. If cof=storing and this parameter is not set, then by default card expiry date is used. NOTICE: during 3-D Secure flow, on Bank site this parameter can be displayed.
recurring_freq [optional] This parameter will be used if cof has the value of storing.
Indicates the minimum number of days between recurring charges.
Integer value. If cof=storing and this parameter is not set, then by default recurring_freq=1 is used. NOTICE: during 3-D Secure flow, on Bank site this parameter can be displayed.
authentication_ind [optional] Type of later transactions, described in part 3-D Secure.
challenge_ind [optional] Enforcing SCA, described in part 3-D Secure.
payment_referenced [optional] The reference to a initial payment other than the one saved in the client’s profile. Takes the value of the payment ID. The parameter can only be used with cof = recurring orcof = unscheduled. By default, for recurring payments, the payment saved in the client’s profile is used (visible as sca_payment in the client’s profile), saved during the payment with the parametercof = storing

link Charge example

{
  "amount": 10,
  "currency": "pln",
  "card": "cc_772ahSzjmMnOt4eIk",
  "description": "Espago docs"
}
curl -i https://sandbox.espago.com/api/charges \
 -H "Accept: application/vnd.espago.v3+json" \
 -u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
 -d "amount=10" \
 -d "currency=pln" \
 -d "card=cc_772ahSzjmMnOt4eIk" \
 -d "description=Espago docs"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new(user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD')
response = client.send(
  'api/charges',
  method: :post,
  body: {
    amount: 10,
    currency: 'pln',
    card: 'cc_8a1kqN20X6JYeuD-Y',
    description: 'Espago docs'
  }
)

puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/charges');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "amount=10&currency=pln&card=cc_772ahSzjmMnOt4eIk&description=Espago docs");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);
{
  "id":"pay_773ob8rbBtid0PYd",
  "description":"Espago docs",
  "channel":"elavon",
  "amount":"10.00",
  "currency":"pln",
  "state":"executed",
  "client":"cli_7733nQkDLdlhHmh-",
  "created_at":1561990343,
  "card":{
    "company":"VI",
    "last4":"4242",
    "year":2020,
    "month":2,
    "first_name":"Adam",
    "last_name":"Adam",
    "authorized":null,
    "created_at":1561990328
  },
  "issuer_response_code":"00",
  "reversable":true,
  "transaction_id":"tr_773OKuy0b"
}

More info about responses can be found here.

{
  "id": "pay_772LFdT3JG6KaAir",
  "description": "order_481",
  "channel": "elavon",
  "amount": "9.99",
  "currency": "PLN",
  "state": "new",
  "client": "cli_772mtwcEVYBfRCJ2",
  "created_at": 1560935536,
  "card": { ... },
  "issuer_response_code": "",
  "transaction_id": "tr_772atPpUX",
  "redirect_url": "https://sandbox.espago.com/3d-secure/tr_772atPpUX",
  "tds_redirect_form": { ... }
}

link 3D Secure

3D Secure is a transaction authorisation method used in the web. It redirects users to their bank’s site (or show iFrame) for additional authorisation (through SMS, submitting some credentials or confirmation on mobile phone application).
The use of 3-D Secure transfers from the Seller to the Customer’s Bank possible liability for fraud.
Proper handling of cards with 3D Secure is necessary for correct transaction flow.


Charges for clients using 3D Secure have the status parameter set to new and an additional parameter - redirect_url. It’s value is equal to the URL to which the user should be redirected to (for authorisation on the bank’s site). After redirecting the transaction’s status will be set to tds_redirected.
After successfuly finishing the required authorisation process, the client will be redirected back to the appropriate merchant’s site (postitive URL / negative URL). Details concerning the transaction will be submitted to the back_request URL.

Until 2019, 3-D Secure v1.0.2 was the standard, currently EMV 3-D Secure v2.2.0 is being introduced. From the customer’s point of view, the difference is small, but for the Merchant, there are:
- Many available parameters that could better adjust the 3DS authentication to a given type of transaction or business through paremeter authentication_ind and challenge_ind.
- Authorization on amount “0” EUR/USD/etc, usefull for storing card data with authentication without charging customer.
- In payment with the cof = storing flag, SCA is always enforced (i.e. customer redirection and his conscious authorization of the transaction). In one-off payments, the Bank may, based on the data of the browser and / or mobile device, decide to authorize and redirect the customer to the store immediately without customer’s action (the so-called frictionless flow, e.g. for amounts below EUR 50, at a seller with whom customer has already made purchases, etc.).

For standard payments (one-time, recurring), Espago sets the appropriate parameters for 3-D Secure v2 authentication. In specific situations the Seller has the option to trigger a payment with additional 3DS indications.

Parameter used in charge request Description Notes and values
authentication_ind type of transactions for which authentication applies

Default:
“01” for single payment
“02” for payments with cof=storing
“04” for non-payment authorization (cof=storing and amount=0).
Need to be 2 digits. Possible values:
‘01’: ‘Payment transaction’
‘02’: ‘Recurring transaction’
‘03’: ‘Instalment transaction’
‘04’: ‘Add card’ [usefull when used with unscheduled payments (ex. payments after renting a bike), should be used in initial transaction(cof=storing)
‘05’: ‘Maintain card’
‘06’: ‘Cardholder verification as part of EMV token ID&V’
challenge_ind Forcing mode for Strong Customer Authentication (SCA)

Default:
“01” for single payment
“04” fored allways for payments with cof=storing (no possibility to change challenge_ind during storing)
Need to be 2 digits. Possible values:
‘01’: ‘No preference’
‘02’: ‘No challenge requested’
‘03’: ‘Challenge requested (3DS Requestor preference)’
‘04’: ‘Challenge requested (Mandate, for example due to PSD2)’
‘05’: ‘No challenge requested (transactional risk analysis is already performed)’
‘06’: ‘No challenge requested (Data share only)’
‘07’: ‘No challenge requested (strong consumer authentication performed)’
‘08’: ‘No challenge requested (utilise whitelist exemption if no challenge required)’
‘09’: ‘Challenge requested (whitelist prompt requested if challenge required)’

link eDCC

Dynamic Currency Conversion (DCC) is a service that enables international Visa® and MasterCard® cardholders the choice to pay the bill in their own currency rather than the local currency.

PDCC from Elavon can convert MasterCard® and Visa® credit and debit transactions in up to 45 currencies — more than any other payment processor — you have more opportunity to grow revenue with us.Your customers will be able to see the actual amount they will be charged before finishing the transaction.

The eDCC service will not be called for recurring payments (recurring = true). The cardholder does not take part in the recurring payment, so he can not make a DCC decision. In this case - when using card in a different currency than the currency of the service for recurring payments, currency conversion will be made by card issuer bank - and according to its rules.

1. Information about currency choice

The transaction begins as normal. If the merchant has got the eDCC service, the Espago gateway automatically discerns if the card qualifies for currency conversion.


If the card is suited for DCC transactions, the gateway responds and waits for the customer’s decision. The response in DCC transaction will always show the amount in the merchant’s currency, the conversion rate and the actual amount of charge (in customer’s currency). A payment waiting for the customer’s decision gets the parameter of status=dcc_decision.

If the card is not suited for DCC, the payment continues without interruptions.

curl -i https://sandbox.espago.com/api/charges \
-H "Accept: application/vnd.espago.v3+json" \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
-d "amount=49.99" \
-d "currency=pln" \
-d "client=cli_772uWYtgJXnL_F9I" \ # A customer with a card with a different currency
-d "description=Description"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new(user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD')
response = client.send(
  'api/charges',
  method: :post,
  body: {
    amount: 49.99,
    currency: 'pln',
    client: 'cli_772uWYtgJXnL_F9I',
    description: 'Opis transakcji'
  }
)

puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/charges');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "amount=49.99&currency=pln&client=cli_772uWYtgJXnL_F9I&description=Opis transakcji");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);
{
  "id": "pay_7724xNjCpNPWYevy",
  "description": "order_502",
  "channel": "elavon",
  "amount": "17.98",
  "currency": "PLN",
  "state": "dcc_decision",
  "client": "cli_772KDwdXQIbqpFp3",
  "created_at": 1560942887,
  "card": { ... },
  "issuer_response_code": "",
  "transaction_id": "tr_772_lDLkv",
  "dcc_decision_information": {
    "cardholder_currency_name": "HKD",
    "cardholder_amount": "39.74",
    "conversion_rate": "2.210174",
    "redirect_url": "https://sandbox.espago.com/secure_web_page/tr_772_lDLkv",
    "mark_up_percentage": "300"
  }
}

Parameter Description Notes
cardholder_currency_name Name of the cardholder’s currency in ISO 4217
cardholder_amount The amount in cardholder’s currency
conversion_rate Conversion rate
redirect_url eDCC decision made at Espago Redirect the customer to this URL if th eDCC decision is not to be made on merchant’s site
mark_up_percentage Mark up percentage

2. eDCC descision

To charge the user send a POST request to https://sandbox.espago.com/api/charges/(:id)/dcc_decision

(:id) - Id of the payment awaiting for a DCC decision

Responses are the same as in regular transactions (without eDCC) - only with additional information about the currency and amount.

curl -i https://sandbox.espago.com/api/charges/(ID_TRANSAKCJI)/dcc_decision \
-H "Accept: application/vnd.espago.v3+json" \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
-d "decision=Y"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new(user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD')
payment_id = 'pay_8a1FKrxqzJG9sszX'
response = client.send(
  "api/charges/#{payment_id}/dcc_decision",
  method: :post,
  body: {
    decision: 'Y'
  }
)

puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/charges/(ID_TRANSAKCJI)/dcc_decision');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "decision=Y");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);
{
  "id": "pay_77219xeZ-8xvxUdE",
  "description": "order_523",
  "channel": "elavon",
  "amount": "39.96",
  "currency": "PLN",
  "state": "executed",
  "client": "cli_772KEkYX7Vq54DJe",
  "created_at": 1560949080,
  "issuer_response_code": "00",
  "reversable": true,
  "transaction_id": "tr_7722-YsY6",
  "multicurrency_indicator": "Z",
  "dcc_decision_information": {
    "cardholder_currency_name": "HKD",
    "cardholder_amount": "88.32",
    "conversion_rate": "2.210174"
  }
}

multicurrency_indicator - Information about the transaction currency. Field present only if the payment currency is different from the currency of the site.
N - Card without DCC
Y - DCC canceled by the user
Z - DCC is possible and accepted by the user

Sometimes a customer using 3D Secure may want to pay in another currency. For this reason, you need to take it into consideration the possibility of such a scenario - when a customer first makes a DCC decision and gets redirected to the URL with 3D Secure. After displaying the information about conversion, the Espago gateway responds with a 3D Secure redirection URL, while the payment gets the “tds_prtcpt” status.

Expample response

{
  "id": "pay_7724l5jFs9EP6Xr0",
  "description": "order_526",
  "channel": "elavon",
  "amount": "16.98",
  "currency": "PLN",
  "state": "tds_prtcpt",
  "client": "cli_772TVMYGxKECDKPZ",
  "created_at": 1560953142,
  "issuer_response_code": "",
  "transaction_id": "tr_772C5ke_m",
  "redirect_url": "https://sandbox.espago.com/3d-secure/tr_772C5ke_m",
  "tds_redirect_form": { ... },
  "multicurrency_indicator": "Z",
  "dcc_decision_information": {
    "cardholder_currency_name": "HKD",
    "cardholder_amount": "37.53",
    "conversion_rate": "2.210174"
  }
}

In some situations, when the Seller expects most customers to use eDCC, he can send a request for conversion rates to the Espago gateway. Thanks to this, there is a way to inform the customer about the conversion rate for his transaction before even starting it!

Conversion rates are updated every day at 6:30 PM.

In order to fetch the conversion rates send a GET request to https://sandbox.espago.com/api/dcc/rates.

curl -i https://sandbox.espago.com/api/dcc/rates \
-H "Accept: application/vnd.espago.v3+json" \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new(user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD')
response = client.send "api/dcc/rates", method: :get

puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/dcc/rates');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');

curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);
{
  "timestamp":"2017-12-01T04:48:00.000+01:00",
  "mark_up_percentage":"300",
  "currency_name":"PLN",
  "currency_code":"985",
  "rates":{
    "USD":"0.285413",
    "ARS":"2.546572",
    "RON":"1.136708",
    "CZK":"6.997923",
    "EUR":"0.255955",
    "KWD":"0.085902",
    "MYR":"1.025983",
    "MXN":"4.372453",
    "GBP":"0.183134",
    ...
  }
}

link Possible payment states

Only state “executed” means that payment is done and money was taken from the customer’s account.

Status Description
new New payment, client’s account has not been charged
executed Payment executed, client’s account was successfuly charged.
Notice: It’s possible to return the whole amount or part of the transaction amount for all executed transactions.
rejected Payment was rejected.
Notice: In response of the rejected transaction, you receive reject_reason and issuer_response_code parameters.
failed Payment ended with a failure
preauthorized [Status available only when using the parameter complete=false] Money are reserved (holded) on the customer’s account but not yet charged.
tds2_challenge [State available only when using 3D-Secure v2]. Customer was redirected to 3-D Secure website or have displayed iFrame, waiting for commin back.
tds_redirected [State available only when using 3D-Secure]. Klient został przekierowany na stronę 3D-Secure (stronę banku), oczekiwanie na jego powrót.
dcc_decision [State available only if 3D-Secure is enabled]. Customer is redirected to 3D-Secure page (bank/issuer site), Espago gateway is waiting for returning customer.
resigned Customer resigned from the autorization of payment or left payment [state available if enabled is 3D-Secure, DCC and/or MasterPass]. In case of leaving transaction with state “new”, “tds_redirected” or “dcc_decision” (no customer action during 1,5 hour) transactions will change state to “resigned”.
reversed Payment was reversed before settlement.
refunded Payment is refunded fully or partially.
blik_redirected [State available only for BLIK payments]. Customer was redirected to the payment page to enter the BLIK code.
transfer_redirected [State available only for BLIK transfers]. Customer was redirected to the payment page to make a transfer.

link Possible rejection reasons

Parameter “reject_reason” can be used as additional information (parameter “issuer_response_code” is more usefull and complete).

Message Meaning Reason Comments
declined transaction rejected Unactivated type of service (MOTO, ecommerce), also lack of funds
card expired Card is not valid Card expiration date was exceeded
insert card soft decline Strong Customer Authentication (SCA) required for this client profile If the payment was made with client profile, it needs to be proceeded again with SCA - to do this, retry with cof=storing parameter in the API request.
invalid amount Invalid amount It refers to the transactions amount limit or number of transactions limit.
invalid card invalid card number, card doesn’t exist
invalid profile invalid MID account Rejected by Elavon due to inactive MID Occurs with issuer_response_code=00
please retry System failure, please re-attempt. Temporary acquirer or issuer system malfunction. Occurs with issuer_response_code=00
referral A / pick up card Card should be taken Card marked as stolen/lost/blocked. IMPORTANT NOTICE: It is forbidden to retry transactions that ended with this reason. It may be recogenized as fraud attempt!
referral B Transaction needs confirmation It requires contact with issuing bank to confirm transaction
serv not allowed Merchant does not support this particular type of a card For instance: American Express, Diners Club, in the case of no BRAM registration - also MasterCard
3ds_not_authorized rejected during 3D-Secure Rejection due to wrong client authentication in 3D-Secure or another error during 3D-Secure check.

The current table (MySQL dump) with the issuer_response_code and descriptions can be found in the “Download” section.

Codes issuer_response_code, after witch you sholud not try to charge again due to possible fraud or the lack of chance of success: 04, 07, 12, 14, 15, 41, 43, 46, 57, R0, R1, R3 B14, B15, B41, B43, B54

Decline response codes that indicate the account never existed or has been permanently blocked including lost or stolen account numbers. This category also includes decline codes that indicate the account is valid however the transaction is not permitted due to permanent product/regulatory restrictions or transaction error conditions that prevent approval.

Response code Meaning Proposed message
04,07 Pickup card (special condition, other than lost/stolen card) REJECTED - Pickup card. Please contact your card issuer and try again later. IMPORTANT NOTICE: It is forbidden to retry transactions that ended with this code. It may be recogenized as fraud attempt!
12 Invalid transaction REJECTED - no privileges to execute this transaction for your card. Please contact your card issuer to get more details and try again later.
14 Invalid account number (no such number) Payment rejected by the issuer - invalid account number. Please use a different card or contact the issuer for clarification.
15 No such issuer Payment rejected - no such issuer. Please use a different card or contact the issuer for clarification.
41 Pickup card (lost) REJECTED – Please contact your card issuer to get more details and try again later. IMPORTANT NOTICE: It is forbidden to retry transactions that ended with this code. It may be recogenized as fraud attempt!
43 Pickup card (stolen) REJECTED – Please contact your card issuer to get more details and try again later. IMPORTANT NOTICE: It is forbidden to retry transactions that ended with this code. It may be recogenized as fraud attempt!
46 Closed account Please use a different card or contact the issuer for clarification.
57 Function not permitted to cardholder REJECTED – Bank/Issuer has declined the transaction as this credit card cannot be used for this type of transaction (eccommerce, MOTO or recurring). Please check your card settings or use another card.
R0 Stop Payment Order Payment rejected by the issuer - Stop Payment Order. Please contact the issuer for clarification.
R1 Revocation of authorization order Payment rejected by the issuer - Revocation of authorization order. Please contact the issuer for clarification.
R3 Revocation of all authorizations order Payment rejected by the issuer - Revocation of all authorizations order. Please contact the issuer for clarification.

Decline response codes that indicate the Issuer may approve, but cannot do so now, perhaps due to temporary decline condition such as credit risk, Issuer velocity controls or other account restrictions. This cluster covers temporary decline decisions made by Issuers that may change over time and the Issuer would welcome a future authorisation attempt. In some cases, cardholder action is required to remove the restriction before an approval can be obtained.

Response code Meaning Proposed message
03 Invalid merchant or service provider REJECTED - Authorization’s Error. Please contact your card issuer and try again later.
19 Re-enter transaction Payment rejected by the issuer. Please use a different card or contact the issuer for clarification.
51 Insufficient funds REJECTED - Insufficient funds. Please check funds on your account and try again later.
59 Suspected fraud REJECTED – Please contact your card issuer to get more details and try again later.
61 Exceeds approval amount limit REJECTED – Please check settings of your account and configurations of limits. Please contact your card issuer and try again later.
62 Restricted card, country exclusion. REJECTED – Your card can be not supported, e.g. due to country issuer exclusion or imposition an embargo. Please contact your card issuer.
65 VIsa: Activity count limit exceeded Visa: REJECTED – Activity count limit exceeded. Change your limits settings or try again later.
75 Allowable number of PIN-entry tries exceeded. REJECTED – Invalid activity count limit exceeded. Please check your CVV/CVC/PIN code on your card.
78 Transaction from a new cardholder, card has not been unblocked. REJECTED – Inactive card. Please activate your card and try again later.
86 Cannot verify PIN Payment rejected by the issuer - cannot verify PIN. Please try again or contact the issuer for clarification.
91,92,94,98 Please retry REJECTED - Refused by Issuer because Issuer is temporarily inoperative. Try again later.
93 Transaction cannot be completed - violation of law Please use a different card or contact the issuer for clarification.
E4 3D-Secure failure in bank. REJECTED - 3D-Secure failure in bank.

Decline codes that indicate data quality issues where invalid payment or authentication data has been provided and the Issuer may approve if valid information is provided.

Response code Meaning Proposed message
54 Expired card REJECTED - Expired card. Please check your card or try another.
55 Incorrect PIN or PIN missing Płatność odrzucona - niepoprawny lub brakujący PIN.
65 Mastercard: soft decline Mastercard: Soft decline - an authentication required.(SCA)
82, N7 Negative CVV results REJECTED - Negative CVV results. Check entered data and try again. IMPORTANT NOTICE: It is forbidden to retry transactions that ended with this code. It may be fraud attempt!
1A Visa: soft decline Visa: Soft decline - an authentication required.(SCA)

This category includes all other decline response codes, many of which are caused by technical problems and provide little to no value to Merchants in determining their reattempt strategy.

Response code Meaning Proposed message
01,02 Voice authorisation required REJECTED - Authorisation Error. Please contact your card issuer.
05 MOTO/eCommerce/recurring inactive or not honoured REJECTED – The bank has declined the transaction due to security check (used card doesn’t support payment without CVV code / recurring payment), or the funds have been frozen, or card doesn’t support MOTO/internet transactions. Please check your card settings or use another card.
13 Invalid amount or currency conversion field overflow Payment rejected by the issuer - invalid amount or currency conversion field overflow. Please use a different card or contact the issuer to check the ecommerce payment settings.
30 Invalid data format REJECTED – Please contact your card issuer to get more details and try again later.
E3 Incorrect 3D-Secure verification REJECTED - Incorrect 3D-Secure verification or another error. Please try again later.
E5 3D-Secure error REJECTED - Temporary 3D-Secure error. Please try again later.

Additional category, containing response codes unrelated to rejections by card issuers. Contains codes related to payment aproval and rejections by Acquirer/Espago.

Response code Meaning Proposed message
00 Successful approval/completion Transaction approved, thank You!
00 Rejected transaction on acquier/Elavon level (We suggest contacting Espago/Elavon) REJECTED - An error occured. Transaction rejected by Elavon due to no response from issuer/bank, inactive Merchant account, used not supported card or incorrect card data. Please try again later or contact with the Espago Support Team.
85 Successful approval/completion Transaction approved, thank You!
B04, B14, B15, B41, B43, B54 Abort The payment has been blocked by Espago, due to an inactive or stolen card. Please update the customer profile with a altered card.
B1A, B65 Abort The payment has been blocked by Espago, due to a missing SCA identificator - Strong Customer Authentication (SCA) required.
E1 Refusal limit exceeded The payment has been blocked by Espago due to exceeding the limit of rejected retries and the risk of additional fees from the operator. Please use a different card or contact the Merchant.
Q1 Transaction blocked on acquirer level due to suspected fraud. The rejection code assigned by the acquirer is returned in the reject_reason parameter. The payment has been blocked by acquirer due to suspected fraud.
Q2 An error occurred while communicating with the acquirer’s system. Additional error information may be returned in the reject_reason parameter. Try again later.

link Response for an incorrect request

When parameters in request are incorrect (ie. cc token already was used before) Espago gateway may reject a response with an HTTP code 422 or others. Such a situation should occur only in a test environment. Rejection of HTTP code 422 is a rejection of the incorrect request on API level, there is no payment attempt.

Response for an incorrect payment description

{
    "errors": [
        {
            "code": "description:invalid_length",
            "message": "Description should be between 5 and 255 characters, was: 0",
            "param": "description",
            "type": "invalid_request_error"
        }
    ]
}

Response when the token has already been used

{
  "errors": [
    {
      "code": "card:token_not_found",
      "message": "Card token not found",
      "param": "card",
      "type": "card_error"
    }
  ]
}

Response when the client profile does not exist or is used with the incorrect account or the profile has no card data

{
    "errors": [
        {
            "code": "card:blank",
            "message": "Card can't be blank",
            "param": "card",
            "type": "card_error"
        }
    ]
}

link Charge preauthorization

This is the function that allows you to hold certain amount of money on customer’s card and charge it later. To preauthorize a charge please send POST request to the following address: https://sandbox.espago.com/api/charges

Parameters, you have to send inside this request are almost the same as they are in a single charge. You can check them above (in the new charge section). The additional parameter you have to include is complete. The default value of this parameter is true - in this case the request is interpreted as the request of a normal charge. If the value is changed to false, then the request is interpreted as preauthorization and the set funds on customer’s card are blocked, but without further completion they will be released after few days.

Preauthorisation can be finished later, by completing the payment (“complete” request, which changes the payment’s status to “executed”) or cancelling (a “DELETE” request, which changes the payment’s status to “reversed”).

The maximum time of blocking funds is defined by institusion which issued the card. Usually, it is no longer than a week.

curl -i https://sandbox.espago.com/api/charges \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
-d "card=cc_7724fuzWy0SYasoLV" \
-d "amount=49.99" \
-d "currency=pln" \
-d "description=Description" \
-d "complete=false"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new(user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD')
response = client.send(
  'api/charges',
  method: :post,
  body: {
    card: 'cc_7724fuzWy0SYasoLV',
    amount: 49.99,
    currency: 'pln',
    description: 'Opis transakcji',
    complete: false
  }
)

puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/charges');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "card=cc_7724fuzWy0SYasoLV&amount=49.99&currency=pln&description=Opis transakcji&complete=false");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);
{
  "id":"pay_772Zm0D5saC0pEA9",
  "description":"Description",
  "channel":"elavon",
  "amount":"49.99",
  "currency":"pln",
  "state":"preauthorized",
  "client":"cli_772yY9NvH2Hyt2DM",
  "created_at":1561559076,
  "card":{ ... },
  "issuer_response_code":"00",
  "completed":false,
  "reversable":true,
  "transaction_id":"tr_772_88A0S"
}

link Preauthorized charge capture

To capture preauthorized charge please send POST request to the following address https://sandbox.espago.com/api/charges/(:id)/complete

(:id) - id of the preauthorized charge, which has to be captured


Notice
The request you send could contain an amount of the capture. If you do not set the amount of capture, it will capture the amount you set on preauthorization. You could capture the customer’s card on amount that is from 1% to 115% of amount you set on preauthorization.

curl -i https://sandbox.espago.com/api/charges/pay_772Zm0D5saC0pEA9/complete \
-X POST \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
-d "amount=35"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new(user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD')
payment_id = 'pay_8a1Wx0ggKxvxxmv1'
response = client.send(
  "api/charges/#{payment_id}/complete",
  method: :post,
  body: {
    amount: 35
  }
)

puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/charges/pay_772Zm0D5saC0pEA9/complete');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "amount=35");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);
{
  "id":"pay_772Zm0D5saC0pEA9",
  "description":"Description",
  "channel":"elavon",
  "amount":"35.00",
  "currency":"pln",
  "state":"executed",
  "client":"cli_772yY9NvH2Hyt2DM",
  "created_at":1561559076,
  "issuer_response_code":"00",
  "reversable":true,
  "transaction_id":"tr_772JlqSER"
}

link Reversal of a pending charge

Payment could be reversed only if it has not been settled yet and it’s possible only for the full amount of the transaction. In the sandbox environment settling is executed once per hour. In production environment payment becomes executed every 24 hours (between 10:30PM and 12:00AM CEST). Only a refund is possible after this time.

Payment reversing is also way to cancel preauthorization. Preauthorizations could be reversed during 1-2 weeks, according to Bank (card’s issuer) politics.


When the payment is already settled in Elavon (a bank) the reversal attempt will fail.

To reverse a pending charge please send a DELETE request to the following address https://sandbox.espago.com/api/charges/(:id)

(:id) - Id of the transaction you want to reverse

curl -i https://sandbox.espago.com/api/charges/pay_772Zm0D5saC0pEA9 \
-X DELETE \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
payment_id = 'pay_8a1Wx0ggKxvxxmv1'
response = client.send "api/charges/#{payment_id}", method: :delete

puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/charges/pay_772Zm0D5saC0pEA9');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');

curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);
{
  "id":"pay_772Zm0D5saC0pEA9",
  "description":"Description",
  "channel":"elavon",
  "amount":"35.00",
  "currency":"pln",
  "state":"reversed",
  "client":"cli_772yY9NvH2Hyt2DM",
  "created_at":1561559076,
  "issuer_response_code":"00",
  "transaction_id":"tr_772JlqSER"
}

link Displaying charges

To fetch the data of a single charge send a GET request to https://sandbox.espago.com/api/charges/(:id)

(:id) - Id of the charge you want to fetch

curl -i https://sandbox.espago.com/api/charges/pay_771MKFI-15SIK1Pm \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
payment_id = 'pay_8a1Wx0ggKxvxxmv1'
response = client.send "api/charges/#{payment_id}", method: :get

puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/charges/pay_771MKFI-15SIK1Pm');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');

curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);

{
  "id": "pay_771MKFI-15SIK1Pm",
  "description": "Espago docs",
  "channel": "elavon",
  "amount": "10.00",
  "currency": "PLN",
  "state": "executed",
  "client": "cli_771Xsyr9GkpN8iTp",
  "created_at": 1559130872,
  "card": {
    "company": "VI",
    "last4": "4242",
    "year": 2024,
    "month": 9,
    "first_name": "Adam",
    "last_name": "Nowak",
    "authorized": null,
    "created_at": 1612977801
  },
  "issuer_response_code": "00",
  "reversable": true,
  "transaction_id": "tr_771EQhf18",
  "reference_number": "Test_doc"
}

You could display a group of charges with a specified number of charges per page. To display a specified group of charges send a GET request to the following address: https://sandbox.espago.com/api/charges?page=1&per=10&client=client_id

Available HTTP parameters

Parameter Description Default value
page Numebr of the page you want to fetch 1 (first page)
per Number of charges per page 25 (25 charges)
client ID of the client whose charges you want to fetch all clients
curl -i https://sandbox.espago.com/api/charges \
-X GET \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
-d "page=1" \
-d "per=5" \
-d "client=cli_772YYE_98HM1DmAD"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
response = client.send(
  'api/charges',
  method: :get,
  body: {
    client: 'cli_772YYE_98HM1DmAD',
    page: 1,
    per: 5,
  }
)

puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/charges');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "page=1&per=5&client=cli_772YYE_98HM1DmAD");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');

curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);
{
  "count":4,
  "charges":[
    {
      "id":"pay_772xZV-3uSUTIxPz",
      "description":"Payment #88",
      "channel":"elavon",
      "amount":"79.00",
      "currency":"pln",
      "state":"executed",
      "client":"cli_772YYE_98HM1DmAD",
      "created_at":1561645210,
      "card":{ ... },
      "issuer_response_code":"00",
      "reversable":true,
      "transaction_id":"tr_772bk-yP2"
    },
    {
      "id":"pay_772X3bE9o9JHdpZt",
      "description":"Payment #23",
      "channel":"elavon",
      "amount":"19.99",
      "currency":"pln",
      "state":"executed",
      "client":"cli_772YYE_98HM1DmAD",
      "created_at":1561645191,
      "card":{ ... },
      "issuer_response_code":"00",
      "reversable":true,
      "transaction_id":"tr_772ZZm3Zt"
    },
    . . .
  ]
}

Recurring Payments autorenew

link Possible scenarios

The main goal of recurring payments is saving the client’s credit card data in the Espago gateway (in the Client profile) and using them for recurring payments (e.g. subscriptions) or payments on client’s demand (e.g. faster payments for clients registerd in the shop). It is possible to carry out charges in a few different ways. The two scenarios below are most notable:

Recurring payments handled by the merchant Recurring payments handled by Espago
  • When the amount and frequency of charges is fickle.
  • When apart from recurring payments clients are also capable of using singular payments.
  • When the Merchant already has the mechanisms necessary to manage payment dates.
  • When the Merchant wants to offer quick (one-click) payments to regular customers.
  • When the amount and frequency of charges is constant. (e.g. monthly subscription)

This chapter describes payments handled by the Merchant. More on Espago subscriptions can be found: here.

link How recurring payments work

  1. The merchant initiates a payments with cof=storing, (which creates a new client profile with the credit card data) and optional authentication_ind, and receives the client ID and confirmation of payment’s execution or a redirection URL (SCA: 3D-Secure). Amount of this initial transaction should be the same as later recurring amount, or (ex. in case of free trial):
    (a) 0 amount - with acquirer Elavon
    (b) 5 EUR (this can be refunded or rversed) in SIX Payment Services;
  2. Optionally, It is a good idea to right after receiving the client’s ID initiate a client profile authorisation, in order to check if the card is suited for recurring payments (look: The problem of cards not suited for recurring payments).
  3. Then the Merchant may make charge requests (/api/charges with client ID and more) adding the information that the payment is recurring (cof=recurring parameter).

The cof=recurring parameter is required for proper marking of repeting/recurring payments (The CVV/CVC code is not required and 3D-Secure is not used) (More on client profile creation: Client profile). The cof=recurring parameter was introduced by Visa and MasterCard in 2019 and replaced the previous recurring=true parameter.

Notice: When this scenarios is used as a oneclick payment/recurring payment on demand of the client, then in charge requests (/api/charges) the cof=recurring parameter should be omitted, which will enable the client to be redirected to complete 3D-Secure. It would also be a good idea to use CVV sending, which makes it more secure and likely to end successfully.

link Requirements and good practises for recurring payments

Action Description
Before subscription customer should have at least one payment with SCA/3D-Secure. Since 01.01.2021 each subscription or storing card for delayed/recurring payments need start with a payment with SCA.
This first payment should be with the amount of later recurring payments or “0” - this is the authorization without charging customer.
You should not reverse/refund payment with SCA/3D-Secure which initialised recurring payment. If you need to do trial-free period, you should consider payment on “0” USD/EUR. Reversing first/SCA payment may be seen by Bank as resignation of customer, and may occur in rejection of subsequent recurring payments.
You should minimize the repetition of failed payments, especially if the customer has several outstanding payments. Visa recommends (in the future this may be a requirement) to avoid a situation where several outstanding payments result in multiple repetitions of multiple payments.
There should not be more than 1 attempt to charge the outstanding payment for the day, Visa recommends one try of payments per 4 days, and after few tries one per 16 days. In practice, if the customer has several outstanding payments, then if the attempt of one (eg with the lowest amount) is rejected, then usually others are also rejected.
Use preauthorisation if you expect the amount to be returned or the actual charge will only encompass a part of the preauthorisation.
Avoid preauthorisation if it’s not needed.
Preauthorisation enables you to reserve funds on a card without charging it.
Depending upon the contract with Elavon, Visa/MasterCard can charge a constant, small amount for every preauthorisation.

link The problem of cards not suitable for recurring payments

Most of cards suitable for one-time Internet/e-commerce payments and recurring payments (if cardholder turns on this type of payments in his bank and sets the appropriate limits). There are, however, some cards, which can make one-time payments online, but which are not suitable for recurring payments, eg. Maestro or a few card types from Polish banks: PEKAO and PKO S.A.

It would be inconvenient for both the Seller and the Customer to successfully add a card and make the first payment (with SCA) and after a month it turns out that no further payments with this card are possible.

To avoid such a situation, it is worth to do immediately after adding the card (payment withcof = storing and strong authentication 3D-Secure) preauthorization with the parameter cof = recurring . After successful preauthorization (state = preauthorized), it can be withdrawn and the customer’s card is considered suitable for recurring payments.

It is also important to ensure that recurring/cyclic transactions (where is no longer used CVV/CVC code) were marked with the parameter cof=recurring. Many banks/issuers will reject normal internet payment if there is no CVV/CVC ando 3D-Secure, but will accept recurring/cyclic payment. Since 1 January 2021 this behavior will apply to all European banks.


Step Function Description
1 Initial payment with saving of customer profile The Merchant triggers a payment with the parameter cof = storing, for the amount that will later be a recurring charge or or amount of 0 USD/EUR/etc (in Elavon). It is expected that the customer will have to pass 3D-Secure verification.
** PAYMENT SUCCESSFUL: ** card supports internet payments, you can go to step 2. This payment should not be deleted / refunded. After successful payment, the customer profile cli_xxxxxxxxxx remains for later use.
** PAYMENT FAILURE: ** the card does not support online payments, so another charge attempt will certainly not be successful ^ 1,3
2 Creation of subscription

First charge

Second authorization or preauthorization
Create a subscription (with automatical charge) or making of the first payment (if recurring is handled by the Merchant) or requesting another preauthorization on demand (if Merchant wants to only check if the card supports recurring transactions.
SUCCESS: customer’s card supports internet and recurring payments. Subsequent payments will most likely also be successful2.
FAIL:
customer’s card doesn’t support recurring payments, so next payment attempts will most certainly also fail1.

1 - If the reason for the rejection is “card does not supported online/MOTO payment” or too low limits for this types of transactions, then after turning on these options/setting up this limits in the credit card options, next payments may be made successfully.

2 - In the case that the customer will not have sufficient money on account (issuer_response_code=51) or card validity will expire, execution of payments will be no longer possible.

3 - If authorization (first transaction) was rejected due to invalid CVV/CVC (error codes 75, 82, N7) you shold not try more payments using this card! This situation could be fraud/using stolen card. Next payment may be accepted by bank because (invalid) CVV code is no more used, but it will be on Merchant responsibility.

link Recurring and repeating (one-click, extending) payments

What is card on file?

Card on file is a service that enables you to save credit card data in Espago - in order to charge the client without having the cardholder to enter his data again. Card on file as a term and the cof parameter function in the Espago gateway since July 2019.

To make use of card on file in Espago you should:

  • carry out a payment with strong SCA authentication (3D-Secure) and the cof=storing parameter (saving the card through card on file) in the API request. Data is saved in the Client Profile. The ID of this newly created profile will be returned with the gateway response. Carrying out a payment in the aforementioned way is necessary to be able to use this client profile for further charges.
  • Initiating more payments through the Client Profile in the*card on file* model. In the acquirer’s and bank’s point of view, these payments will be associated with the initiating payment.

Functionality

Data in the Client Profile can be updated, and the profile itself - if it’s needed - can be deleted through an API request. Card on file in Espago lets you make use of all the features devised by credit card companies, which is described in this chapter.
Charges using a saved card are divided into:

  • Merchant Initiated Transactions according to the contract (e.g. recurring payments, postponed, balance compensation)
  • Cardholder Initiated Transactions (e.g. one-click)

Merchant Initiated Transactions

After successfully processing the initiating payment with strong authentication (SCA), more charges can be made through a process initiated by the Merchant - according to the deal made with the cardholder. Example of such a charge:

  • monthly subscription for a service or a gym membership;
  • charge for a service initiated by the customer (e.g. taxi or car sharing)

Payments initiated by the cardholder

Payments initiated by the cardholder (e.g. one-click) have to be marked as cof=unscheduled. These are payments, carried out because of the cardholder’s actions:

  • confirming an online purchase by clicking the “Buy” or “Pay” button;
  • buying a service in a mobile app.

link CoF parameter - values

Value of the cof parameter is a string.

Initiating payment

storing - saves credit card data and returns the client profile, which can be used for subsequent payments.

Payments initiated by the merchant (MIT) - standing instructions

recurring - recurring payments with a constant interval (less than a year), within the period of providing the service;
unscheduled - payments using the saved credit card, with a constant or changing amount, which are not carried out according to any schedule (e.g. charge after a service on demand);

Payments initiated by the Merchant (MIT) - industry-specific

delayed_charge - a delayed charge after finishing the service.
Useful in - hotels, vehicle rental.

no-show - a payment carried out according to the deal between the merchant and the cardholder, enabling the former to charge the latter when, because of the cardholder, the service could not be completed.
Useful when - a guest has not shown up.

reauthorisation - payment for a purchase made after initial authorisation, may reflect different scenarios (e.g. extending the service past the original authorisation amount)
Example:
* eCommerce - in split shipping or its delay
* when extending vehicle rental or a hotel stay;

resubmission - payment for a service, initiated once again due to unsuccessful authorisation in the first attempt of charging the card;

Espago subscriptions poll

link Espago subscriptions

Recurring payments are a way of charging the client automatically loads the specified frequency. In the Espago system recurring payments consist of two main components, these are: plans oraz subscriptions. To use recurring payments you must also create a Espago client object with assigned credit card data - based on the customer ID he is assigned to a specific subscription.

This system is very simple. You first define a plan, which encompasses the details of how frequently should the charges take place and the amount of these charges. To start these repeated payments, you need to create a new subscription with the use of client ID and plan ID.

Merchant defines Plan (or Plans), i.e. scheme indicating the amount and period. Next, for each client Merchant creates client profile with card data (using single payment with token and parameter “cof=storing”), and create subscription (using client ID and plan ID). When subscription is created, first payment is started. If first payment is successful, subscription is active, and next payment will be performed in time defined in the plan. Each payment’s attempt generates back-request with information about payment status.

Bank statements concerning recurring payments (states, charging attempts etc) are gathered in invoices. They’re available only through recurring payments handled by Espago.

link Configuration

After gaining access to the merchant panel you need to undertake the following actions:

  1. Access this subpage
  2. Click “Edit” to see the details
  3. Set up the back request URL (more on this under “Back request”)
  4. Fill in the field with time between charge attempts (after an unsuccessful one) and determine the state in case of exceeding the limits for additional charging attempts. In the production environment the possible values are: 1, 2, 3, 4 days, while in the test environment in minutes.



Possible states after exceeding the charging attempt limits:

State Description
Stop subscription Turns the subscription off preventing it from generating new charges. The subsciption status changes to “inactive”.
Do nothing The charges will be generated anyway.

link Plans

Plans define scheme of recurring payments, including information obout the amount and frequency of payment. Next, based on the defined plans, you can launch subscriptions for customers.


While creating a plan you define data like: type of charging frequency unit (day, month, etc), number of frequency units (in case of a period=7 and period_unit=day, we get a charge every 7 days) and the amount charged.

To create a plan send a POST request to https://sandbox.espago.com/api/plans with correct parameters.

Available HTTP methods

Parameter Description Notes
period_unit Period unit It defines the period unit, for example: day or month.
period amount of periods Integer number. It decides about the amount of periods beetwen charges i.e. if period_unit=month, period=2 will create charge every 2 months
amount Transaction amount Decimal number, i.e. 123.45
currency currency Currency symbol
description plan description It should contain at least 5 characters.

It is important to set the parameters “period” and “period_unit” in the right way. Their summary values are responsible for the frequency of charges.

Value of the 'period_unit' parameter Acceptable 'period' values Result
day 1-366 Plan, that charges client’s card every specified number of days
month 1-12 Plan that charges client’s card every specified number of months

Example of a plan creation request:

curl -i https://sandbox.espago.com/api/plans -H \
'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
-d "description=description" \
-d "period_unit=month" \
-d "period=1" \
-d "amount=50" \
-d "currency=pln"


require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
response = client.send(
  'api/plans',
  method: :post,
  body: {
    description: 'plan description',
    period_unit: 'month',
    period: 1,
    amount: 50,
    currency: 'pln'
  }
)

puts response.code
puts response.body


$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/plans');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "description=description&period_unit=month&period=1&amount=50&currency=pln");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);

{
  "id":"pl_77299uAqqIu4a6eQB",
  "description":"description",
  "period":1,
  "period_unit":"month",
  "amount":"50.0",
  "currency":"pln",
  "created_at":1559739533
}


To fetch a current plan send a GET request to https://sandbox.espago.com/api/plans/(:id)
(:id) - Id of the plan you want to fetch

curl -i https://sandbox.espago.com/api/plans/ID \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD


require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
plan_id = 'pl_8a1W3P6xTXOZ4epTp'
response = client.send "api/plans/#{plan_id}", method: :get

puts response.code
puts response.body


$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/plans/ID');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');

curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);

{
  "id":"pl_77299uAqqIu4a6eQB",
  "description":"description",
  "period":1,
  "period_unit":"month",
  "amount":50.0,
  "currency":"pln",
  "created_at":1559739533
}


To delete a plan send a DELETE request to https://sandbox.espago.com/api/plans/(:id)
(:id) - Id of the plan you want to delete

curl -i https://sandbox.espago.com/api/plans/ID \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
-X DELETE 

require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
plan_id = 'pl_8a1FInbtEadoX0PER'
response = client.send "api/plans/#{plan_id}", method: :delete

puts response.code
puts response.body


$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/plans/ID');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');

curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);

In response: Status: 204 NoContent

By dokonać zmiany ustawień planu należy wysłać żądanie metodą PUT na adres: https://sandbox.espago.com/api/plans/(:id)
(:id) - Id of the plan you want to update

The rest of parameters and headers are identical to those sent when creating a new plan

Notice
Plan updates do not change any existing subscriptions - the changes apply only to newly created subscriptions (created after the change). As such we recommend creating new plans instead of updating old ones.

curl -i https://sandbox.espago.com/api/plans/ID \
-X PUT -u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
-d "description=Plan update" \
-d "period_unit=month" \
-d "period=1" \
-d "amount=75" \
-d "currency=pln"


require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
plan_id = 'pl_8a1FInbtEadoX0PER'
response = client.send(
  "api/plans/#{plan_id}",
  method: :put,
  body: {
    description: 'updated plan description',
    period_unit: 'month',
    period: 1,
    amount: 75,
    currency: 'pln'
  }
)

puts response.code
puts response.body


$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/plans/ID');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "description=Plan update&period_unit=month&period=1&amount=75&currency=pln");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');

curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);

The response: Status: 204 No Content

Fetch a list of plans by sending a GET request to: https://sandbox.espago.com/api/plans

curl -i https://sandbox.espago.com/api/plans \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD 


require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
response = client.send 'api/plans', method: :get

puts response.code
puts response.body


$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/plans');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');

curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);

{
  "count":3,
  "plans":[
  {
    "id":"pl_772F0N8AqpLJ8tUhK",
    "description":"Karnet EXCLUSIVE PRO",
    "period":1,
    "period_unit":"month",
    "amount":119.0,
    "currency":"pln",
    "created_at":1559745412
  },
  {
    "id":"pl_772eAqoP50JRfV3Fo",
    "description":"Karnet PRO",
    "period":1,
    "period_unit":"month",
    "amount":79.0,
    "currency":"pln",
    "created_at":1559745395
  },
  {
    "id":"pl_772tYQqPm5QaD9ye9",
    "description":"Karnet NORMAL",
    "period":1,
    "period_unit":"month",
    "amount":50.0,
    "currency":"pln",
    "created_at":1559745382
  }]
}


link Subscriptions

Subscriptions are objects which connect clients to plans.

By default, subscription is running since it is launched (it generates the first payment) and next payment are done after period defined in Pan. Time (hour) of execution of the next payment is similar to hour of creation of subscription (payment can be called max 4 hours later).
Subcription is stopped when:

  • the first payment (made during creation of subscription) is rejected. In this case subscription is not activated.
  • Merchant sends request to stop subscription,
  • one of next payments are failured (repeated three times or not repeated and if the stopping subscription in such a situation has been configured in the web panel).

There is also possibility for launching a subscription with the delayed start (ie. with a defined date of the first payment). In such a situation there is no automatic mechanism for deactivating the subscription in case of rejection of the first payment.

Create a new subscription by sending a POST request to https://sandbox.espago.com/api/subscriptions and choose the appriopriate client and plan.

Available HTTP parameters

Parameter Description Notice
client Client ID required
plan Plan ID required
channel Payment channel Optional - by default is set to the service payment channel Available values: elavon_cc, worldline_cc.
start_time Time of starting the subscription Optional parameter. Format: unix time. By default (without this parameter) subscription is started in moment of sending request. Parameter require unix time: later than 12 hour after request and earlier than time of next period defined in plan. Details about delayed start in the next chapter.
curl -i https://sandbox.espago.com/api/subscriptions \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
-d "client=client_id" \
-d "plan=plan_id"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
response = client.send(
  'api/subscriptions',
  method: :post,
  body: {
    client: 'cli_772YYE_98HM1DmAD',
    plan: 'pl_8a1trIGa-EMTQN1VI'
  }
)

puts response.code
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/subscriptions');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "client=client_id&plan=plan_id");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);
In the response, aside from subscription details, we also send the data of the first charge(last_invoice).
{
  "id": "sub_i3CoQEnqX5IKve",
  "state": "active",
  "client": "cli_buoBpPrw6rU7iC",
  "plan": "pl_vGTGxa_Kf521Sdv",
  "created_at": 1373461486,
  "last_invoice": {
    "id": "in_MVt4vwsp7VvOTqa",
    "date": 1373461485,
    "client": "cli_buoBpPrw6rU7iC",
    "subscription": "sub_i3CoQEnqX5IKve",
    "amount": "7.00",
    "currency": "PLN",
    "paid": true,
    "issuer_response_code": "00",
    "attempts": 1,
    "next_payment_attempt": "null",
    "created_at": 1373461485
  }
}

Notice!
If during creation of the subscription first payment fails this subscription expires - this is security element against the creation of a subscription using the card, which for example does not support inernet transactions or MOTO transaction.
In this case, in response to a request for creating a subscription (/api/subscriptions) parameter "state" will have value "inactive".

Further responses

Aside from the subscription, the first subscription with the information about the transcation status will be created. Further informations regarding future charges will be sent as asynchronous back requests to the back request URL (more on that in the chapter: Back request) and are generated when a subscription is created or a charge is attempted. Example of a back request (more in Invoices):

{
  "id": "in_hS-KiS3N6YCzOhG",
  "date": 1371631155,
  "client": "cli_OU7k00vEMGi53C",
  "subscription": "sub_QyJzN4KdzNzvmZ",
  "amount": "7.00",
  "currency": "PLN",
  "paid": true,
  "attempts": 1,
  "next_payment_attempt": "null",
  "created_at": 1371500155
}

Back The response is sent for up to 24 hours of descending interval until a response 200 ‘OK’ from the client application.

There is a possibility to create subscription, which start time (first charge) will be declared by the Seller. To start a subscription with a delayed start, you need to use “start_time” parameter of the corresponding value in the request for creating a subscription (description above).

  • This option is usefull eg. when first period should be free.
  • After starting subscription with delayed start, it work as normal subscription.
  • You can stop the subscription before the first charge.

Subscription with the delayed start has some limitations:

  • During creation of subscription there is no first attempt of payment, so there is no mechanism for deactivating the subscription in case of rejection of the first payment. Thus it is possible to run a subscription for the card, which can not be charged, because, for example, it does not support online payments and/or recurring payments.
  • To avoid this problem, the Seller shall ensure that sooner or card supports recurring billing (described earlier).
  • Date and time of launch subscription defined in the parameter “start_time” must be later than 12 hours after the request, and earlier than the time period defined as a period of plan/subscription.

To fetch the data of a subscription send a GET request to https://sandbox.espago.com/api/subscriptions/(:id)
(:id) - Id of the subscription you want to fetch

curl -i https://sandbox.espago.com/api/subscriptions/ID \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
subscription_id = 'sub_8a1xsjIpXYYlKFzF'
response = client.send "api/subscriptions/#{subscription_id}", method: :get

puts response.code
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/subscriptions/ID');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');

curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);
{
  "id": "sub_i3CoQEnqX5IKve",
  "state": "active",
  "client": "cli_buoBpPrw6rU7iC",
  "plan": "pl_vGTGxa_Kf521Sdv",
  "created_at": 1373461486,
  "last_invoice": {
    "id": "in_MVt4vwsp7VvOTqa",
    "date": 1373461485,
    "client": "cli_buoBpPrw6rU7iC",
    "subscription": "sub_i3CoQEnqX5IKve",
    "amount": "7.00",
    "currency": "PLN",
    "paid": true,
    "issuer_response_code": "00",
    "attempts": 1,
    "next_payment_attempt": "null",
    "created_at": 1373461485
  }
}

To stop a subscription send a DELETE request to https://sandbox.espago.com/api/subscriptions/(:id)
(:id) - Id of the subscription you want to delete

curl -i https://sandbox.espago.com/api/subscriptions/ID \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
-X DELETE 
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
subscription_id = 'sub_8a1FXEDVNMINvTOS'
response = client.send "api/subscriptions/#{subscription_id}", method: :delete

puts response.code
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/subscriptions/ID');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');

curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);
Response: status: 204 No Content

To fetch the list of active subcriptions send a GET request to: https://sandbox.espago.com/api/subscriptions. It is possible to send additional parameters, but it is not required.

Parameter Description Default value
page Page number 1 (first page)
per Subscriptions per page 25 (25 subscriptions)
curl -i https://sandbox.espago.com/api/subscriptions \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
-d "page=2" \
-d "per=5"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
response = client.send(
  'api/subscriptions',
  method: :get,
  body: {
    page: 1,
    per: 5
  }
)

puts response.code
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/subscriptions');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "page=2&per=5");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);

{
  "count": 1,
  "subscriptions": [
    {
      "id": "sub_i3CoQEnqX5IKve",
      "state": "active",
      "client": "cli_buoBpPrw6rU7iC",
      "plan": "pl_vGTGxa_Kf521Sdv",
      "created_at": 1373461486,
      "last_invoice": {
        "id": "in_9d7xIbhzLMkxTFm",
        "date": 1373463196,
        "client": "cli_buoBpPrw6rU7iC",
        "subscription": "sub_i3CoQEnqX5IKve",
        "amount": "7.00",
        "currency": "PLN",
        "paid": true,
        "issuer_response_code": "00",
        "attempts": 1,
        "next_payment_attempt": "null",
        "created_at": 1373463196,
      }
    }
  ]
}

To fetch the list of active subscriptions of a client send a GET request to: https://sandbox.espago.com/api/clients/(:client_id)/subscriptions
(:client_id) - Id of the client whose subscriptions you want to fetch. It is possible to send additional parameters, but it is not mandatory.

Parameter Description Default value
page Page number 1 (first page)
per Number of subscriptions per page 25 (25 subscriptions)
curl -i https://sandbox.espago.com/api/clients/CLIENT_ID/subscriptions \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
-d "page=2" \
-d "per=5"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
client_id = 'cli_772YYE_98HM1DmAD'
response = client.send(
  "api/clients/#{client_id}/subscriptions",
  method: :get,
  body: {
    page: 1,
    per: 5
  }
)

puts response.code
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/clients/CLIENT_ID/subscriptions');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "page=2&per=5");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);

{
  "count": 2,
  "subscriptions": [
    {
      "id": "sub_WbAUbaC_7KB79V",
      "state": "active",
      "client": "cli_buoBpPrw6rU7iC",
      "plan": "pl_vGTGxa_Kf521Sdv",
      "created_at": 1373463500,
      "last_invoice": {
        "id": "in_I3iEPUZFxUsLUR-",
        "date": 1373463498,
        "client": "cli_buoBpPrw6rU7iC",
        "subscription": "sub_WbAUbaC_7KB79V",
        "amount": "7.00",
        "currency": "PLN",
        "paid": true,
        "issuer_response_code": "00",
        "attempts": 1,
        "next_payment_attempt": "null",
        "created_at": 1373463498
      }
    },
    {
      "id": "sub_FMw5DlPzK0dW9V",
      "state": "active",
      "client": "cli_buoBpPrw6rU7iC",
      "plan": "pl_vGTGxa_Kf521Sdv",
      "created_at": 1373463506,
      "last_invoice": {
        "id": "in_WtlQMDFdUDpIdSq",
        "date": 1373463504,
        "client": "cli_buoBpPrw6rU7iC",
        "subscription": "sub_FMw5DlPzK0dW9V",
        "amount": "7.00",
        "currency": "PLN",
        "paid": true,
        "issuer_response_code": "00",
        "attempts": 1,
        "next_payment_attempt": "null",
        "created_at": 1373463504,
      }
    }
  ]
}

link Invoices

Invoice is a kind of object which is used to store informations about recurring transaction state, number of attempts and date of next payment attempt if last was rejected/failed.

To display all invoices of a client send a GET request to: https://sandbox.espago.com/api/clients/(:client_id)/invoices
(:client_id) - Id of the client

curl -i https://sandbox.espago.com/api/clients/CLIENT_ID/invoices/ \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
client_id = 'cli_772YYE_98HM1DmAD'
response = client.send "api/clients/#{client_id}/invoices", method: :get

puts response.code
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/clients/CLIENT_ID/invoices/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');

curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);

{
  "count":1,
  "invoices":[
    {
      "id":"in_7728vjvj-BdSK0B64",
      "date":1559903458,
      "client":"cli_772YYE_98HM1DmAD",
      "subscription":"sub_772pHbFAL2vs-z8g",
      "amount":"119.00",
      "currency":"pln",
      "paid":true,
      "issuer_response_code":"00",
      "attempts":1,
      "next_payment_attempt":null,
      "created_at":1559903458,
      "last_payment":"pay_772Nkgo8MS-25osp"
    }
  ]
}

Meaning of fields in the response:

Field name Meaning Available values
Date Planned date of charge attempt Time in Unix Format
Paid Was invoice paid? True or False
Attempts Number of executed attempts Integer
Next payment attempt Data of execution next payment attempt Time in Unix format or null

If you want to enforce more retries of invoice charge you can send a special POST request to the following address: https://sandbox.espago.com/api/invoices/(:invoice_id)/pay
(:invoice_id) - Id of the invoice

Notice
Using this request when not all retry attempts were made will decrease number of attempts made by gateway automatically!

curl -i https://sandbox.espago.com/api/invoices/(:invoice_id)/pay \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
invoice_id = 'in_7728vjvj-BdSK0B64'
response = client.send "api/invoices/#{invoice_id}/pay", method: :post

puts response.code
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/invoices/(:invoice_id)/pay');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);
{
  "id": "in_MUL7PeIUTDwOHx8",
  "date": 1371805245,
  "client": "cli_N7hldWZqSoBLva",
  "subscription": "sub_occMPm6-_284b3",
  "amount": "7.00",
  "currency": "PLN",
  "paid": true,
  "attempts": 2,
  "next_payment_attempt": "null",
  "created_at": 1371805245,
    "last_payment":"pay_772Nkgo8MS-25osp"
}

When the invoice has already been paid for, we send: 422 "Unprocessable Entity.

Display a single invoice by sending a GET request to: https://sandbox.espago.com/api/invoices/(:id)
(:id) - Id of the invoice

curl -i https://sandbox.espago.com/api/invoices/ID_FAKTURY \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
invoice_id = 'in_7728vjvj-BdSK0B64'
response = client.send "api/invoices/#{invoice_id}", method: :get

puts response.code
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/invoices/ID_FAKTURY');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');

curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);
{
  "id":"in_7728vjvj-BdSK0B64",
  "date":1559903458,
  "client":"cli_772YYE_98HM1DmAD",
  "subscription":"sub_772pHbFAL2vs-z8g",
  "amount":"119.00",
  "currency":"pln",
  "paid":true,
  "issuer_response_code":"00",
  "attempts":1,
  "next_payment_attempt":null,
  "created_at":1559903458,
  "last_payment":"pay_772Nkgo8MS-25osp"
}

link Invoice Items

Invoice Items serve the purpose of providing information concerning a single payment, which is a part of a subscription cycle. It covers the details of an attempt to charge the client (to pay off an invoice). If it fails, another invoice item is created and the system attempts to charge the client once again. This proccess can be configured (to make a certain amount of charge attempts with certain intervals). More on configuring Espago subscriptions: Espago Subscriptions - Configuration

To create a new invoice item, send a POST request to: https://sandbox.espago.com/api/invoice_items

Parameters

Parameter Description Value Obligatory
amount Transaction amount A decimal number, eg. 123,45 Required
currency Currency The currency symbol compatible with your MID Required
date Date of charge A future date of charge in unix time Required
client client ID ID used to link this transaction to a created client Required
description Description Should consist of at least 5 characters. Optional
curl -i https://sandbox.espago.com/api/invoice_items \
-H 'Accept: application/vnd.espago.v3+json' \
-u app_id:password \
-d "currency=currency" \
-d "date=unix_time" \
-d "amount=100" \
-d "client=client_id" \
-d "description=Description"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
response = client.send(
  "api/invoice_items",
  method: :post,
  body: {
    currency: 'pln',
    date: 1764363614,
    amount: 100,
    client: 'cli_772YYE_98HM1DmAD',
    description: 'Opis transakcji'
  }
)

puts response.code
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/invoice_items');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "currency=currency&date=unix_time&amount=100&client=client_id&description=Description");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'app_id' . ':' . 'password');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);
{
  "id": "ii_1sbC2i-UHMWJXZH",
  "client": "cli_xNKNXh-_kWu6Qi",
  "description": "Description",
  "amount": "100.00",
  "currency": "PLN",
  "created_at": 1381755981
}

To fetch information about the items encompassed by a particular invoice send a GET request to: https://sandbox.espago.com/api/invoices/(:invoice_id)/line_items
(:invoice_id) - ID of the invoice

curl -i https://sandbox.espago.com/api/invoices/(:invoice_id)/line_items \
-H 'Accept: application/vnd.espago.v3+json' \
-u app_id:password
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
invoice_id = 'in_7728vjvj-BdSK0B64'
response = client.send "api/invoices/#{invoice_id}/line_items", method: :get

puts response.code
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/invoices/:invoice_id/line_items');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');

curl_setopt($ch, CURLOPT_USERPWD, 'app_id' . ':' . 'password');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);

{
  "count": 1,
  "invoice_items": [
    {
    "id": "ii_1KZ0VBahlukLI2X",
    "client": "cli_OU7k00vEMGi53C",
    "description": "Position 1",
    "amount": "7.00",
    "currency": "PLN",
    "created_at": 1371631057
    }
  ]
}

To delete an existing invoice item send a DELETE request to: https://sandbox.espago.com/api/invoice_items/(:id)
(:id) - ID of the invoice item

curl -i https://sandbox.espago.com/api/invoice_items/(:id) \
-X DELETE \
-H 'Accept: application/vnd.espago.v3+json' \
-u app_id:password
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
invoice_id = 'in_7728vjvj-BdSK0B63'
response = client.send "api/invoices/#{invoice_id}", method: :delete

puts response.code
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/invoice_items/(:id)');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');

curl_setopt($ch, CURLOPT_USERPWD, 'app_id' . ':' . 'password');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);
The status returned with a response is: 204 "No content"

Back requests receipt

link Configuration

The Espago gateway sends asynchronous back requests to the merchant site in a few situations:

  • payment state info - after carrying out a payment in APIv3.0 (in a payment with 3D-Secure, the request is sent after the verification process and the bank’s response),
  • payment state info - after carrying out a subscription payment,
  • subscription state info - when the subscription state changes (e.g. when it gets deactivated),
  • created token info - disabled by default, used by certain Merchants.

Responses about transaction state changes are sent asynchronously to the URL specified in your configuration.
Back requests should make use of the HTTPS (port 443) protocol, but HTTP (port 80) is also possible.
In the Sandbox test environment, the server additionally may send back requests to ports 8002 and 8003.

Notice
In case of the lack of the “HTTP 200” response from the Merchant’s site, the action will be retried for 24h with an increasing interval.

After gaining access to the merchant panel, you should take the following steps:
1. Navigate to:
2. Click on “Edit”.
3. Fill in “Back request URL (application/json v. 3.0.)” - back requests will be sent to this address.
4. Fill in “Basic login (for Back request URL)” oraz “Basic password (for Back request URL)”. Espago back requests will be authorised through these values.

Notice
Login and password validation for back requests is not mandatory, however implementing it is highly recommended for security reasons.

link Back requests in payments

If the merchant uses APIv3.0, every initiated payment generates a back request.

If 3D-Secure is not used, receiving this request is not obligatory, since it has the same information as the ones returned with a gateway response. If 3D-Secure is turned on, the back request is sent after the client authorisation, and they are the main source of information for the Merchant about the payment’s state. If the client discards the payment on the 3DS verification step, after 1,5h the payment’s state will be changed to “resigned” and a back request confirming that will be sent.

Example (back request):

{
  "id": "pay_772sMqGEogv63CSk",
  "description": "order_263",
  "channel": "elavon",
  "amount": "56.94",
  "currency": "PLN",
  "state": "executed",
  "client": "cli_7725o4SHuhgnHAVe",
  "created_at": 1560160387,
  "card": {
    "company": "VI",
    "last4": "4242",
    "year": 2030,
    "month": 1,
    "first_name": "John",
    "last_name": "Smith",
    "authorized": null,
    "created_at": 1560160386
  },
  "issuer_response_code": "00",
  "reversable": true,
  "transaction_id": "tr_772b9YYzb"
}
Parameter Notes Description
id Payment ID. Enables one to find this payment later, check its status. Has the form of pay_xxxxxxxxxxxxxxxx and a length between 18 and 20 characters.
description Payment description sent to /api/charges.
channel Payment channel.
amount Transaction amount.
currency Transaction currency.
state Transaction state. Described in detail in “Possible payment states”
client Client ID used for this payment. In one time payments (requests with the “card” parameter) it’s just a temporary client’s ID, which can be ignored
created_at Payment creation date in unix.
card object Card parameters.
issuer_response_code Response code from banks. If the payment is on the 3D-Secure step, this parameter gains the 00 or NULL value, until it is finished.
tds_status_reason Code which siginfies the reason behind the status of the 3D-Secure 2 authorization. More detailed descriptions of these codes can be found in the Downloads section as 3D-Secure status codes.
transaction_id Transaction ID. Useful when searching for the payment in the Elavon panel, since only this value is visible in Elavon reports (There are no client ID or payment ID). Transaction is an “operation”. By default only payments have only one transaction, after returning a part all the enitre payment, the ID of the reversing transaction will be here.
redirect_url optional URL to which the user should be redirected to for 3D-Secure.
reversable optional The “reversable=true” parameter informs that the payment can be reversed before it’s settled. After the settlement this parameter has the value “false” and is no longer visible in payment’s properties.
tds_redirect_form optional/object Parameters letting you redirect the client directly to the bank (instead of Espago through the use of redirect_url). In this case the user should be redirected through a form with the POST method, with PaReq, MD i TermUrl parameters. This option is not recommended, please contact Espago before implementing it.
liability_shift Available only for the worldline_cc payment channel Boolean. The liability_shift=true parameter indicates the liability shift to the card issuer in the case of fraud-related chargebacks.
trace_id Available only for the worldline_cc payment channel ID of an SCA transaction, which serves as evidence of its completion. This ID is sent to the bank as part of the authorization data for MIT payments (payments without cardholder’s involvement).

link Back requests in subscriptions

Example of a back request with info regarding a successful payment (paid=true).

{
  "id": "in_hS-KiS3N6YCzOhG",
  "date": 1371631155,
  "client": "cli_OU7k00vEMGi53C",
  "subscription": "sub_QyJzN4KdzNzvmZ",
  "amount": "7.00",
  "currency": "PLN",
  "paid": true,
  "issuer_response_code": "00",
  "attempts": 1,
  "next_payment_attempt": "null",
  "created_at": 1371500155,
  "last_payment": "pay_iq1yCYmgieM_ct"
}

If the subscription state gets changed - if the option to cancel the subscription after unsuccessful charge attempts has been turned on - a back request communicating that will be sent.

{
  "id": "sub_WQO0vEpk0-SrqM",
  "state": "inactive",
  "client": "cli_MNXfMFpu8_j3ax",
  "plan": "pl_dxT6xBEo__fbb7y",
  "created_at": 1457559667,
  "last_invoice": {
    "id": "in_CjUBitNf9UpWdoQ",
    "date": 1460461811,
    "client": "cli_MNXfMFpu8_j3ax",
    "subscription": "sub_WQO0vEpk0-SrqM",
    "amount": "55.00",
    "currency": "pln",
    "paid": false,
    "issuer_response_code": "00",
    "attempts": 1,
    "next_payment_attempt": "null",
    "created_at": 1460461811,
    "last_payment": "pay_iq1yCYmgieM_ct"
  }
}

link Back requests in token creation

There is an option to turn on sending back requests with information about newly generated tokens. Using this option the merchant’s server could gather the information about a new token directly form Espago, and not from the client’s web browser

In order to turn on this option, you need to contact the Espago Support (through email).
To make Espago send the back request, the “card[description]” parameter (this should be unique for the merchant’s server) with a length of 5-60 characters should be added to the token creation request (POST /api/tokens).

Creating a token with back requests turned on:

  1. From the client’s web browser (using Espago JS) or a mobile app, a token creation request i sent to Espago. This request contains credit card data and the “card[description]” field.
  2. The client receives a response form the Espago gateway confirming that a new token has been generated. The response contains the token’s ID, which by default would be sent to the Merchant’s server by the client.
  3. The Espago gateway sends an asynchronous back request to the Merchant’s server, containing token’s ID, and (in the section about the credit card) the “description” field, enabling the Merchant to link the token to a certain client.
  4. Through the use of the token received from Espago (or from the client), the Merchant’s service can carry out a payment.
{
  "subject": "card",
    "id": "cc_7762MqOeLF1iVw7fD",
  "created_at": 1571170086,
  "used": false,
  "card": {
    "company": "VI",
    "last4": "4242",
    "year": 2020,
    "month": 2,
    "first_name": "Jan",
    "last_name": "Kowalski",
    "authorized": null,
    "description": "Client_1234567890",
    "created_at": 1571170086
  },
  "description": "Client_1234567890"
}

Refunds undo

link Refund of a settled Charge

In current chapter described is only the refund of a settled charge. If you want to reverse a pending charge, you can read more about it here.

To refund settled charge please send POST request to the following address https://sandbox.espago.com/api/charges/(:id)/refund where the (:id) is ID of selected Charge (“pay_xxxxxxxxxxxx”).

You can return the entire amount of the transaction or part of it. There is no possibility to undo/stop return.

Payment can be refunded in 12 months after it’s creation.

In the case of partial refund, payment can be repeatedly refunded payment until you pay the entire amount of the original payment. Parameter refunded_amount has value already refunded amount. If you need to return full amount of payment which is partial refunded you can calculate the rest of amount (rest of money = amount - refunded_amount) or make refund request without amount.

HTTP Parameters

Parameters Description Required? Comments
amount amount, that will be refunded No This parameter has to be less than or equal the amount of transaction. If you do not set this value, the entire transaction amount will be refunded.

Important parameters from response

Parameter Descriptions Comments
id id of payment Value unchanged
state status of payment After correct refund (partial or full) became “refunded”
refunded_amount amount already refunded After full refund, refunded_amount=amount. After partial refund, refunded_amount is sum of all returns already done on this payment.
transaction_id ID of refund transaction ID of transaction (operation) which is refunding payment. This ID is different than ID transaction made payment.

Example request

curl -i https://sandbox.espago.com/api/charges/(:id)/refund \
 -X POST \
 -H 'Accept: application/vnd.espago.v3+json' \
 -u app_id:password \
 -d "amount=n"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
payment_id = 'pay_315gfsdf234'
response = client.send(
  "api/charges/#{payment_id}/refund",
  method: :post,
  body: {
    amount: 100
  }
)

puts response.code
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/charges/(:id)/refund');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "amount=n");
curl_setopt($ch, CURLOPT_USERPWD, 'app_id' . ':' . 'password');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);
{
  "id": "pay_COy6zH9fLj1d7K",
  "description": "Opis transakcji",
  "channel": "elavon",
  "amount": "49.99",
  "refunded_amount": "15.00",
  "currency": "pln",
  "state": "refunded",
  "client": "cli_xNKNXh-_kWu6Qi",
  "created_at": 1381823580,
  "card": {
    "company": "VI",
    "last4": "4242",
    "year": 2017,
    "month": 2,
    "first_name": "Jan",
    "last_name": "Kowalski",
    "authorized": true,
    "created_at": 1381755890
  },
  "issuer_response_code": "00",
  "transaction_id": "tn_AKZ71ysMF"
}

link Refund without a previous ecommerce payment

The following chapter describes refunds without prior ecommerce payment. If you want to learn about refunds of existing payments, go here.

A refund without a prior ecommerce transaction occurs by sending a POST request to the address https://sandbox.espago.com/api/refunds.

The preferred method of refund is to refer to a previous transaction. Refunds without an ecommerce transaction may be applicable in situations where the original transaction was made on a physical payment terminal and the Espago gateway does not have its data.

Request body

Parameter Description Required
amount Amount to be refunded Required
currency Three-letter currency code in the ISO 4217 standard. Required
description The description of the refund (5 to 255 characters). Required
channel The channel that will be used to process the refund. Supported values: elavon_cc, elavon_eisop Required
custom_order_id An identifier that will appear in the settlement file. Optional
eisop_token An eisop_token object that contains the data of the EISOP token that will be used to process the refund. Conditional
card ID of an existing card token in Espago, with which the refund will be processed. Mandatory if client or eisop_token is not provided. Conditional
client ID of an existing client profile in Espago, with which the refund will be processed. Mandatory if card or eisop_token is not provided. Conditional

The eisop_token object

Parameter Description Required
token EISOP token number Required
card_year Expiration year of the customer’s card in the numerical format YYYY. Required
card_month Expiration month of the customer’s card in the numerical format MM Required

Important response parameters

Parameter Description Notes
id The identifier of the refund.
state The state of the refund After a successful refund, the value should be "refunded" or "refund_executed". Other values include "refund_rejected" and "failed"
refunded_amount The refunded amount.
issuer_response_code Rejection code Code indicating the reason for rejecting the refund attempt.

Example request

curl -i https://sandbox.espago.com/api/refunds \
 -X POST \
 -H 'Content-Type: application/json' \
 -H 'Accept: application/vnd.espago.v3+json' \
 -u  ms_771eUTliRiZ:SeCreT_P@ssw0rD \
 -d '{ "amount": 10, "currency": "PLN", "channel": "elavon_eisop", "description": "docs test refund",  "eisop_token": { "token": "BEYOVBGIVPBX0006", "card_year": "2025", "card_month": "12" } }'
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
payment_id = 'pay_315gfsdf234'
response = client.send(
  "api/charges/#{payment_id}/refund",
  method: :post,
  body: {
    amount: 10,
        currency: "PLN",
        description: "docs test refund",
        eisop_token: {
          token:  "BEYOVBGIVPBX0006",
            card_year: "2025", 
        card_month: "12"
      }
  }
)

puts response.code
puts response.body
{
  "id": "pay_COy6zH9fLj1d7K",
  "channel": "elavon_eisop",
  "refunded_amount": "10.0",
  "currency": "GBP",
  "state": "refunded",
  "created_at": 1381823580,
  "eisop_token": {
    "token": "xxx",
    "token_type": "xxx",
    "last4": "xxxx",
    "year": "YYYY",
    "month": "MM",
    "company": "CC"
  },
  "issuer_response_code": "XX",
  "transaction_id": "xxx"
}

Client Profile accessibility_new

link Cient Object

Client data can be stored in the client object (especially card data). A client profile with all attributes can be used in multiple charges.

It is possible to create a client profile without card data (only description and email), in order to add the details later

In our web panel there you can enable/disable automatic authorisation during client profile creation. If it is enabled, after a request to /api/client test authorization is done (charge and reversal of 1 PLN to check if the card supports Internet transactions), and in the “authorized” response parameter in client profile contain authorisation status (for detail see the chapter belowClient profile and card attributes.

link Customer profile and card attributes

The customer profile is an object with certain parameters. They are usually returned directly after creating a client. They’re also available later when sending requests about a customer or his payments.

Description and possible card parameter values in customer’s profile:

Parameter Value Description
company VI, MC, MD Card Provider info: VI - Visa, MC - MasterCard, MD - Maestro, AX - American Express, DC - Diners Club, JC - JCB, SW - Switch, SO - Solo, LA - Laser. WARNING: more often than not a contract with Elavon encompasses only Visa and Mastercard cards. For this reason, in most scenarios, distinguishing between VI, MC, MD will be enough.
authorized null, true, false The value of last authorisation of the card, it’s a boolean value.
null - has not been authorised yet
true - card authorisation was successful and is active
false - unsuccessful card authorisation
authorized_cvv_cvc null, true, false This parameter is available while using the double authorisation feature. Returns information about the first card authorisation using CVV/CVC. It’s of boolean type, like “authorized”.
issuer_response_code Issuer response code If authorized=false, then this parameter will contain the rejection code (issuer_response_code)
created_at (number) Time in unix format
sca_payment object Array of information about initial transaction which starts recurring (first or lattest payment with cof=storing on this client profile). This payment details will be sent to Bank in as reference in recurring payments. Example: "sca_payment": { "id": "pay_aaaaaaaaaaaa", "amount": "19.00", "updated_at": 1605775020, "client": "cli_xxxxxxxxxxxxxxx" }

link New customer profile

New customer creation is carried out by sending a POST request to https://sandbox.espago.com/api/clients/

Available HTTP parameters

Parameter Function Description Mandatory
description Should consist of at lest 5 characters. Optional
email Customer’s e-mail address Not required but necessary if Espago has to inform the customer about changes of payment’s state via email. Optional.
We check the email’s format after receiving it.
card Parameter with the ID of card token The ID of a previously created card token. Required
curl -i https://sandbox.espago.com/api/clients \
-H "Accept: application/vnd.espago.v3+json" \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
-d "description=John Smith" \
-d "card=token_id"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
response = client.send(
  "api/clients",
  method: :post,
  body: {
    description: 'Jan Kowalski',
    card: 'token_id'
  }
)

puts response.code
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/clients');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "description=John Smith&card=token_id");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);
{
  "email": "john@smith.com",
  "id": "cli_Yzij0t46pV88oR",
  "created_at": 1381825758,
  "description": "John Smith",
  "card": {
    "company": "VI",
    "last4": "4242",
    "year": 2017,
    "month": 2,
    "first_name": "John",
    "last_name": "Smith",
    "authorized": true,
    "created_at": 1381825758,
  },
  "deleted": false
}


Instead of sending card tokens, you can send card data directly, but for security’s sake using tokens is the preffered method. Sending complete data in parameters can be used for testing and certain appliances in the production environment (please contact Espago).

Card data can be sent according to the following draught (all fields are required):

Parameter Function Description
card[first_name] Card owner’s first name
card[last_name] Card owner’s last name
card[number] Credit card number
card[verification_value] CVV
card[year] Year of expiry In YYYY format
card[month] Month of expiry In MM format; values between 01-12

link Card token creation

In order to create a card token send a POST request to https://sandbox.espago.com/api/tokens

curl -i https://sandbox.espago.com/api/tokens \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
-d "card[first_name]=John" \
-d "card[last_name]=Smith" \
-d "card[number]=4242424242424242" \
-d "card[verification_value]=123" \
-d "card[year]=2018" \
-d "card[month]=02"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
response = client.send(
  "api/tokens",
  method: :post,
  body: {
    card: {
      first_name: "Jan",
      last_name: "Kowalski",
      month: "02",
      number: "4242424242424242",
      verification_value: "123",
      year: "2030"
    }
  }
)

puts response.code
puts response.body
// Generated by curl-to-PHP: http://incarnate.github.io/curl-to-php/
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/tokens');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "card[first_name]=John&card[last_name]=Smith&card[number]=4242424242424242&card[verification_value]=123&card[year]=2018&card[month]=02");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);
{
  "id": "cc_J_wDRKH6jmIEb_8",
  "created_at": 1550871516,
  "used": false,
  "card": {
    "company": "VI",
    "last4": "4242",
    "year": 2018,
    "month": 2,
    "first_name": "John",
    "last_name": "Smith",
    "authorized": "null",
    "created_at": 1550871586
  }
}

used parameter is of boolean type (true or false). If it’s value is set to false, the token has not been used yet.

link Checking the token details

You can get the following details of the tokenized payment card:

  • issuer country code
  • bank name (but only Polish banks)
  • currency code
  • card type

In order to turn on this feature, please contact the Espago support.
In some cases, checking the card details takes over 1 s.

To check the tokenized card details send a POST request to https://sandbox.espago.com/api/tokens/(:id)/check_type

(:id) - id of the card token you want to check

curl -i https://sandbox.espago.com/api/tokens/cc_776Hzu24ArvnooVvq/check_type \
-X POST \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
token_id = 'cc_8a1IcKzD4NzD7httF'
response = client.send "api/tokens/#{token_id}/check_type", method: :post

puts response.code
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/tokens/cc_776Hzu24ArvnooVvq/check_type');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);
{
  "email":"test@example.com",
  "id":"cli_772IYA6M52V4njJR",
  "created_at":1561373467,
  "description":"John Smith id:321",
  "card":{
    "company":"VI",
    "last4":"4242",
    "year":2026,
    "month":2,
    "first_name":"John",
    "last_name":"Smith",
    "authorized":true,
    "card_type":"D",
    "country":"HKG",
        "currency":"HKD",
    "bank":"U",
    "created_at":1561373520
  },
  "deleted":false
}

Parameter Function Description
card_type Type of card C - credit card
D - debet card
U - no info
country Card issuer country 3-letter country code defined in ISO 3166-1 alpha-3.
U - no info
currency Card currency 3-letter country code defined in ISO 4217.
U - no info
bank Bank’s name Bank’s name
U - no info

link Profile editing

Delete any existing customer profiles by sending a DELETE request to the following URL: https://sandbox.espago.com/api/clients/(:id)

(:id) - Id of the customer you want to delete

curl -i https://sandbox.espago.com/api/clients/CLIENT_ID \
-X DELETE \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
client_id = 'cli_8a1IcKzD4NzD7httF'
response = client.send "api/clients/#{client_id}", method: :delete

puts response.code
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/clients/CLIENT_ID');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');

curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);

We send a response of: Status 204: no content

Update an exisitng customer by sending a PUT request to
https://sandbox.espago.com/api/clients/(:id)
where (:id) is the Id of the client that you want to udpate (example path: /api/clients/cli_xxxxxxx)

Send the same parameters as when creating a customer profile, at least one needs to be different:
* email [optional]
* description [optional]
* card=token_id when card is updated


WARNING
Just like in customer profile creation, submitting a card’s token id is the required method (created before sending an update request) If (in case of a Merchant with PCI certification) any of the card’s details are updated, you need to send a complete set of the card’s data (Even if only a single parameter is changed).
After updating card data there is no way to get back to revert this process. If you want to make it possible to submit a new card, only if it functions properly and deleting the old one thereafter, you may want to consider creating a new customer profile and deleting the old one.

curl -i https://sandbox.espago.com/api/clients/ID_KLIENTA \
-X PUT \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
-d "description=John Smith" \
-d "email=client@example.com" \
-d "card[first_name]=John" \
-d "card[last_name]=Smith" \
-d "card[number]=4242424242424242" \
-d "card[verification_value]=123" \
-d "card[year]=2025" \
-d "card[month]=02"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
client_id = 'cli_772YYE_98HM1DmAD'
response = client.send(
  "api/clients/#{client_id}",
  method: :put,
  body: {
    description: 'Jan Kowalski',
    email: 'client@example.com',
    card: {
      first_name: 'Jan',
      last_name: 'Kowalski',
      number: 4242424242424242,
      verification_value: 123,
      year: 2025,
      month: 02
    }
  }
)

puts response.code
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/clients/ID_KLIENTA');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "description=John Smith&email=client@example.com&card[first_name]=John&card[last_name]=Smith&card[number]=4242424242424242&card[verification_value]=123&card[year]=2025&card[month]=02");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');

curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);
{
  "email":"client@example.com",
  "id":"cli_772q8GcejiQfRl4z",
  "created_at":1560960175,
  "description":"John Smith",
  "card":{
    "company":"VI",
    "last4":"4242",
    "year":2025,
    "month":2,
    "first_name":"John",
    "last_name":"Smith",
    "authorized":null,
    "created_at":1561125908
  },
  "deleted":false
}

link Fetching profiles

Fetch the data of a formerly created customer by sending a GET request to https://sandbox.espago.com/api/clients/(:id)

(:id) - Id of the customer whose data you want to acquire

curl -i https://sandbox.espago.com/api/clients/CLIENT_ID \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
client_id = 'cli_772YYE_98HM1DmAD'
response = client.send "api/clients/#{client_id}", method: :get

puts response.code
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/clients/CLIENT_ID');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');

curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);

{
  "email":"client@example.com",
  "id":"cli_772q8GcejiQfRl4z",
  "created_at":1560960175,
  "description":"John Smith",
  "card":{
    "company":"VI",
    "last4":"4242",
    "year":2022,
    "month":2,
    "first_name":"John",
    "last_name":"Smith",
    "authorized":true,
    "created_at":1561126879
    },
  "deleted":false",
  "sca_payment": {
    "payment_id": "pay_772bLKUDa1sdfsd",
    "amount": "0.00",
    "channel": "elavon",
    "updated_at": 1561126879,
    "client_id": "cli_772q8GcejiQfRl4z"
    }
}

Display a number of customers by sending a GET request to https://sandbox.espago.com/api/clients?page=1&per=10

Available HTTP methods

Parameter Description Mandatory Default value
page Page number Optional 1 (first page)
per Number of customers on a single page Optional 25 (25 klientów)
curl -i https://sandbox.espago.com/api/clients \
-X GET \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
-d "page=2" \
-d "per=15"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
response = client.send(
  "api/clients",
  method: :get,
  body: {
    page: 1,
    per: 5
  }
)

puts response.code
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/clients');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "page=2&per=15");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');

curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);
{
  "count":19,
  "clients":[
    {
      "email":"client@example.com",
      "id":"cli_772q8GcejiQfRl4z",
      "created_at":1560960175,
      "description":"John Smith",
      "card":{
        "company":"VI",
        "last4":"4242",
        "year":2022,
        "month":2,
        "first_name":"John",
        "last_name":"Smith",
        "authorized":true,
        "authorized_cvv_cvc":true,
        "issuer_response_code":"00",
        "created_at":1561126879
      },
      "deleted":false
    },
    {
      "email":"test@example.com",
      "id":"cli_772psATGSdMbS8NS",
      "created_at":1560960154,
      "description":"John Smith id:321",
      "card":{
        "company":null,
        "last4":null,
        "year":null,
        "month":null,
        "first_name":null,
        "last_name":null,
        "authorized":null,
        "created_at":null
      },
      "deleted":false
    },
    (. . .)
  ]
}

link Authorising customers' cards on demand

Cards are authorised by reserving and immediately returning 1 PLN (or 1 EUR, etc). This process ensures that the card is suited for payments.

  • If authentication is successful, it means that the card supports online payments, is not expired and that the bank account has funds.
  • If authentication fails, it means that it is almost certain that the next payments will also fail (except for a rejection due to a temporary lack of funds or reached transaction limit of the day).

In Espago’s web panel you can set automatic authorisation on client profile creation. In that case, you will get authorisation information already in response to client creation (and update).

WARNING
If authorisation is the first process carried out on a card/customer, CVV has to be used. Any further transactions will be completed without CVV. Some cards may not support payments without CVV (and therefore do not support recurring payments) which may cause situations in which a card passes authorisation, but every other transaction fails. In order to avoid this, you could follow authorisation with a second one or a payment


Authorise clients’ card by sending a POST request to https://sandbox.espago.com/api/clients/(:id)/authorize

(:id) - Id of the client who will be authorised

curl -i https://sandbox.espago.com/api/clients/CLIENT_ID/authorize \
-X POST \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
client_id = 'cli_772YYE_98HM1DmAD'
response = client.send "api/clients/#{client_id}/authorize", method: :post

puts response.code
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/clients/CLIENT_ID/authorize');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);

{
  "email":"client@example.com",
  "id":"cli_772q8GcejiQfRl4z",
  "created_at":1560960175,
  "description":"John Smith",
  "card":{
    "company":"VI",
    "last4":"2239",
    "year":2025,
    "month":2,
    "first_name":"John",
    "last_name":"Smith",
    "authorized":true,
    "issuer_response_code":"00",
    "created_at":1561369769
  },
  "deleted":false
}

link Secure web page for creating and updating client's card data

This is page where customer can be redirected for creating client profile with card data or updating card information in his profile. This way, Customer puts his credit card data on the Espago Website, not on the seller’s site (when using Espago JS or iFrame solution).

Additionaly by using ‘check’ and ‘store’ parameters you can declare the conditions under which an update shall take place. This is to prevent clients from replacing their working credit cards, with new ones, not suited for recurring payments.

In order to create the “client_card_page” - a secure page, to which the user can be redirected to securely enter his credit card data - send a POST request to:
https://sandbox.espago.com/api/clients/card_page
and redirect the customer to the received URL.

HTTP parameters

Parameter Required Function Description
client client/customer ID If used, this parameter should contain ID of customer/client created earlier.
client[description] check Short customer description Should have at least 5 characters.
card[email] Customer e-mail address Not required but necessary if Espago has to inform customer about changes of payments state via email.
store Information when save card data: all
check Information how to test client’s credit card - nothing
positive_url URL the customer should be redirected to after saving his credit card details.
negative_url URL the customer should be redirected to when customers resign or an error occurs.
title Short description for what this card will be used for - it’ll be displayed on the page. At least 5 characters


If the merchant has the ‘Automatic client authorization’ option checked then ‘check’ is by default set to ‘recurring. Otherwise it’s set to 'nothing’.


curl -i https://sandbox.espago.com/api/clients/card_page \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
-d "client[description]=John Smith id:321" \
-d "client[email]=test@example.com" \
-d "check=recurring" \
-d "store=recurring" \
-d "title=Card for future subscription for the radio ABC"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
response = client.send(
  "api/clients/card_page",
  method: :post,
  body: {
    client: {
      description: "Jan Kowalski id:321",
      email: "test@example.com"
    },
    check: "recurring",
    store: "recurring",
    title: "Card for future subscription for the radio ABC"
  }
)

puts response.code
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/clients/card_page');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "client[description]=John Smith id:321&client[email]=test@example.com&check=recurring&store=recurring&title=Card for future subscription for the radio ABC");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);
{
  "id":"cpl_772AUdz2l2DMHCvz",
  "url":"https://sandbox.espago.com/client_card_page/cpl_772AUdz2l2DMHCvz",
  "client":"cli_772IYA6M52V4njJR",
  "store":"recurring",
  "check":"recurring",
  "title":"Card for future subscription for the radio ABC",
  "valid_to":1561459867,
  "created_at":1561373467,
  "used":false,
  "positive_url":null,
  "negative_url":null
}

Now the (cli_772IYA6M52V4njJR) profile can be used as normal. They ‘URL’ parameter encapsulates the client_card_page URL for this client. Such a link is valid for one hour and expires after saving the card.
After saving the card, finish-true parameter is displayed on the last screen. It can trace this URL in WebView (in the mobile app) and close the window after credit card creation.

link Checking client card information

You can get the following details of the payment card assigned to the client’s profile:

  • issuer country code
  • bank name (but only Polish banks)
  • currency code
  • card type

In order to turn on this feature, please contact the Espago support.
In some cases, checking the card details takes over 1 s.

To check the card details, send a POST request to https://sandbox.espago.com/api/clients/(:id)/check_type

(:id) - id of the requested client’s profile.

curl -i https://sandbox.espago.com/api/clients/cli_772IYA6M52V4njJR/check_type \
-X POST \
-H 'Accept: application/vnd.espago.v3+json' \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
client_id = 'cli_772YYE_98HM1DmAD'
response = client.send "api/clients/#{client_id}/check_type", method: :post

puts response.code
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/clients/cli_772IYA6M52V4njJR/check_type');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);
{
  "email":"test@example.com",
  "id":"cli_772IYA6M52V4njJR",
  "created_at":1561373467,
  "description":"John Smith id:321",
  "card":{
    "company":"VI",
    "last4":"4242",
    "year":2026,
    "month":2,
    "first_name":"John",
    "last_name":"Smith",
    "card_type":"D",
    "country":"HKG",
    "currency":"HKD",
    "bank":"U",
    "created_at":1561373520
  },
  "deleted":false
}

Parameter Function Description
card_type Type of card C - credit card
D - debet card
U - no info
country Card issuer country 3-letter country code defined in ISO 3166-1 alpha-3.
U - no info
currency Card currency 3-letter country code defined in ISO 4217.
U - no info
bank Bank’s name Issuer bank name.
U - no info

Submitting CVV Numbers vpn_key

link Why should I send CVVs?

CVV can only be used once and after a successful first authorisation or payment, it is deleted from the Espago gateway. In order to make another payment with the use of a client profile and CVV, you need to fetch the CVV (through EspagoFrame or Espago JS and create a token for it) and send it as a payment parameter.


The feature of adding CVV is specially useful as an additional authentication method in multiple payments initiated by the customer. Sending CVV also increases the probability of the payment succeding, because it makes it possible to charge cards, which do not work without CVV (look: The problem of cards not suitable for recurring payments)

CVV token can be used in 24h after creating, there is no option to store CVV for later multiple payments.

link Creating CVV tokens

You can use EspagoIFrame (which enables the user to securely enter their credit card data, or in this instance, just CVV) to create CVV tokens. Then this data will be sent to Espago and a script will return the token ID back to the site. This token can be used later to securely send the CVV.

1. Calling the IFrame

The client calls our IFrame suited for gathering CVVs, enters his code and sends it to Espago

<script src="https://js.espago.com/espago-1.3.js"></script>
 <script 
   async=""
   data-id="EspagoFrameScript"
   data-key="VrYVaA1CjmRooKh63YYv"
   data-live="false"
     data-cvv-only="true"
   data-button="Pay"
   src="https://js.espago.com/iframe.js">
 </script>

 <a id="pay_btn">Pay</a>
$('#pay_btn').click( () => {
  showEspagoFrame()
})

Receiving the token

After the user filled in the form with his card details, the script sends this data directly to Espago Servers. In case of creating a token, the script (by default) returns it form of an input to a form named `espago_form` (this form has to be present on your site, for the script to work!).

You can change this behaviour in these parameters: data-target or data-success in IFrame.

<form id="espago_form">
  <input type="hidden" id="cvv_token" name="cvv_token" value="cvv_xxxxxx">
</form>

Creating a charge

Creating a charge with an additional parameter: cvv=cvv_token_id.

curl -i https://sandbox.espago.com/api/charges \
-H "Accept: application/vnd.espago.v3+json" \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
-d "amount=10" \
-d "currency=pln" \
-d "client=cli_772IYA6M52V4njJR" \
-d "description=Espago docs" \
-d "cvv=cv_772oAPNIwkEZlEIPo"

link Parameters

Parameter Required Default values Description
async done “” Can not have a value different than default
data-id done EspagoFrameScript Can not have a value different than default
src done source of the script Can not have a value different than default
data-key done String, Merchant public key
data-cvv-only done String, if ‘true’, EspagoFrame is set in CVV mode - only CVV field will be displayed.
data-live true String, If ‘true’, then requests are sent to production environment. If set to ‘false’, requests are sent to test environment.
data-company String, indicates saved card company, this company logo will be displayed as card info next to CVV field. Available: AX, DC, DI, JC, MC, MD, UP, VI.
data-last4 String, indicates saved card number last 4 digits , will be displayed as card info next to CVV field.
data-valid-to String, format: MMYYYY, indicates saved card validation date, will be displayed as card info next to CVV field.
data-lang pl String, Form language (for default labels, placeholders) in ISO 639-1 standard. Available: da, de, en, et, fr, it, lt, lv, pl, ru, sv.
data-success function(data) {} A success callback. Action inside this function will be executed when token is received. Note: If given, default script action is disabled - field ‘card_token’ will not be added to form.
data - string; Espago token value.
data-error function(data) {} An error callback. Action inside this function will be executed when error occurred.
data - string; error code with description.
data-onclose function() {} An “on close” callback. This function is executed when user closes modal (using “x” button or “Esc” key).
data-target espago_form Form name, where ‘card_token’ hidden field will be added.
Note - if the ‘data-success’ parameter is specified, above action will not perform.
data-title Add your card (en) Form title.
Note - The default value depends on the language value of ‘data-lang’.
data-subtitle The text displayed below the form title and store name (store name is taken automatically from the API Espago)
data-button Save (en) The label of the submit button.
Note - The default value depends upon the ‘data-lang’ parameter

link Payments with CVV tokens

A CVV payment is executed just like a regular one, but posesses an aditional cvv parameter, with the id of the CVV token.

Request example

curl -i https://sandbox.espago.com/api/charges \
-H "Accept: application/vnd.espago.v3+json" \
-u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
-d "amount=10" \
-d "currency=pln" \
-d "client=cli_772IYA6M52V4njJR" \
-d "description=Espago docs" \
-d "cvv=cv_772oAPNIwkEZlEIPo"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD'
response = client.send(
  "api/charges",
  method: :post,
  body: {
    amount: 10,
    currency: 'pln',
    client: 'cli_772YYE_98HM1DmAD',
    description: 'Espago docs',
    cvv: 'cv_772oAPNIwkEZlEIPo'
  }
)

puts response.code
puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/charges');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "amount=10&currency=pln&client=cli_772IYA6M52V4njJR&description=Espago docs&cvv=cv_772oAPNIwkEZlEIPo");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);

link Using Espago.js to create CVV tokens

To accept the CVV code and create a token CVV, please use the form using JS script espago-1.3. This script sends the CVV code directly from the form (client browser) into the gateway Espago, next recieve CVV token and sends its ID (as parameter “cvv_token” with the value like “cv_xxxxxxxx”) with the form to the merchant website.

URL of the actual script: https://js.espago.com/espago-1.3.js
Demo: https://github.com/espago/espago-1.3.js-demo

In the script there should be used “Public Key”, the same as in the Espago JS used to create normal credit card script.

<script src='https://js.espago.com/espago-1.3.js' type='text/javascript'></script>

<form action='cv_token.html' id='espago_new_cvv_form' method='POST'>
  <input id='espago_new_verification_value' type='text' value='712'>
  <span id='espago_new_verification_value_error'></span>
  <input type='submit' value='Create CVV token'>
</form>
var espago = new Espago({public_key: 'PfcMBQnqWjNF2ihkv9xs', custom: true, live: false})

$("#espago_new_cvv_form").submit(function(event){
  event.preventDefault()

  if (espago.validate_new_cvc()){
    $("#espago_new_verification_value_error").text("")
  } else {
    $("#espago_new_verification_value_error").text("Błędne dane!")
  }
  espago.create_new_cvv()
})

Espago Terminals payment

link What is Espago Terminals

Espago Terminals allows integration of physical payment terminals with a sales system accessible through browser. The integration involves sending payments to the terminal via API request and the sales system receiving information about the status of the transaction. It also allows for executing a refund initialized by sales system.

Standard integration can be extended with functionality that allows the transaction ID received from the terminal to be linked with the client in the merchant’s system, and based on that, the client card can be re-charged without its physical presence (as long as the merchant’s terms and conditions allow for it).

The usage of the Espago Terminals is consistent with Espago API (used in e-commerce, e-invoicing and recurring services), since after payment is made on the terminal and Espago Terminals obtains client profile, all future proceedings are being made in the same way on Espago gateway based on that profile.

For implementation purposes Espago prepared simulation of a physical terminal, due to this feature integration partner does not need access to actual test physical terminal as well as test payment cards.

link Application scope of Espago Terminals

Due to nature of payment terminals operations, Espago Terminals has several technical limitations:
1. The computer (later referred to as POS) from which payment will be sent must be directly connected to the same LAN network as the terminal.
2. POS must have one of the following operating system: Android (phone or tablet), or Windows.
3. POS must have a dedicated Espago Terminals application installed (Download).
4. Espago Terminals only work with certain acquirers. For more information, please contact sales@espago.com.

Espago Terminals application

Our application was created with transaction security purposes in mind, and without it our solution will not work properly. It is used for direct communication between our API and the payment terminal.

No additional software or special configuration is needed besides installing said application. The extension was created in such a way that it does work in background - with other app in focus and is booting up with OS.

The extension is available in the Download section. Link

link Integration

After getting access to the account from support staff, log in at https://terminals-beta.espago.com/users/sign_in. After that, it is recommended to change your password. This can be done in your account panel - it is located under the “account” tab in the bottom left corner.

In the next step, go to “Service” tab. There you will be able to find your test service.
In Espago Terminals, each user can have multiple services; service can have multiple terminals, but each service has its own separate API access, and they cannot share any information nor share any terminals each other.

After selection your service, click “Edit Service” button and set API access password - it must not be shared to any third party. Also, you should specify back_request_url - parameter that specifies an address to which a back request will be sent with transaction information after it has been executed, as well as basic auth login and password used for authorizing back requests.

The final step is terminals configuration. To do this, from service view, you should select “View Terminal” on the terminal you want to configure. Choose name to your liking - convenient for integrator. Key parameters for basic configuration are LAN IP address and port on which terminal will listen. At the stage of integration into the test environment, these parameters are not relevant for making payments work properly.

After this configuration, you can start sending requests to Espago Terminals gateway according to the instructions in following sections. Espago also provides a tool to preview requests that are being sent to the gateway. These are located in Api Requests tab.

Virtual Terminal

Keeping in mind that access to Espago Terminals and integration may occur well before a physical terminal is available, we have created a virtual test terminal built into our extension. All payments sent to the test environment (https://terminals-sandbox.espago.com) will be handled by it.
Once the payment is correctly queried and the Espago Terminals extension goes to the browser link, it will launch a new window with the virtual terminal, which shows the key information for the developer sent to the terminal. At the bottom of the window, there will be an option to select the response sent to the terminal.

After proper integration and passing some tests, Espago team will launch a production environment with which payments can be sent to physical terminals.

link Espago Terminals apps

In order to use the services we offer, it is necessary to install one of the dedicated applications for this purpose. They will serve as an intermediary in the communication of the payment terminal with our API. These applications are available for computers running Windows and Android phones. Application of our choice can be downloaded in the Download section. Link

The installer guides us through the entire installation process, which includes only two steps:
1. Choosing for whom to install the application (current user / all users)
2. Path under which the application will be installed

After installation, the application will be added to the system autostart, so that, when the computer is restarted, we do not have to start it manually. It also works completely in the background, so we will not see its window at startup. If we want to display the application’s window, expand tray (system tray) in the taskbar, then left-click on the white Espago Terminals icon. To avoid accidentally closing the application with the X button, its behavior has been changed, so that trying to close the application this way will only minimize it to the tray.

Right-clicking on the icon will display additional actions.
* Force reload - forces a restart of the application’s connection to the Espago cloud and payment terminal.
* Disable Virtual Terminal - disables / enables the capture of sent payments by the virtual terminal.
* Quit - forces a complete shutdown of the application.

Before the application is ready to work, we need to enter the settings panel by clicking on the gear located in the upper right corner of the window, and then enter the following information to the application:
* TID - ID of the terminal we want to connect.
* API login - login to API for your service.
* API password - password to API for your service.

The above data are needed to connect to the Espago cloud and the terminal. Without them, the application will not work properly!

We can access the above information in our service panel. Note that if we don’t have the API password set, it should be done by going to Service → Edit Service → Edit Passwords.

Currently, this mode is only available on Windows applications.
It should only be used for development purposes, when trying to connect to our API.

For integration purposes, an option has been added that switches the application to Sandbox mode. This mode changes the environment with which the application and the terminal communicate. To enable said mode, set the switch described as “Run in sandbox mode ” in the application settings, so it turns yellow. In order to avoid confusion as to what mode the application is running in, a special message will appear in the main view of the application indicating that Sandbox mode is enabled.

You need to remember to check the data of the service and the terminal you are trying to communicate with, as these can vary from environment to environment.

More multiple user accounts at one device

If your setup include more than one user account, you need to change Login settings for all users (Microsoft documentation) . To do this, you need to Settings, find position Sign-in options, and under Privacy ensure that “Use my sign-in info to automatically finish setting up my device and reopen my apps after an update or restart.” option is disabled. Without this Espago Terminals app will not be working properly.

link Espago Terminals in action

1. Request with data to perform the transaction

Sending a request to Espago Terminals API with terminal data and transaction information to terminals.espago.com/api/charges.

{
  "amount": 12.00,
  "currency": "EUR",
  "description": "Payment #5656",
  "terminal": "1234567",
  "kind": "mobile"
}

2. Response

After submitting the correct data, Espago Terminals will send payment on terminal, and respond with information about the created payment.

{
  "payment_guid": "tp_4455rgT6Ve",
    "state": "sent"
}

When the terminal is not connected or wrong params are provided, then the error message will be given.

3. Sending payment to the payment terminal

After successful API request the transaction will be sent immediately. At this moment client can pay on device, according to terminal payment instructions.

4. Response with transaction status

Once the transaction is completed, the status of transaction will be displayed on the terminal. Transaction information will be sent to the address provided as a back request.

{
  "payment": {
    "id": "tp_7d7z-noWFPW",
    "description": "Payment #5656",
    "state": "success",
    "amount": "12.00",
    "currency": "EUR"
  }
}

link Charge parameters

A new payment on the terminal is made by sending a POST request to https://terminals.espago.com/api/charges. Just like in the standard Espago API, the request must be authorized using the Authorization header with the value Basic app_id:password.

The following parameters are available:

Parameter Description Mandatory Comment
terminal TID Yes Tid of the terminal to which the payment is to be sent.
description Transaction description Yes Must be 3 to 255 characters. It should be used to associate the payment with the customer of the service.
amount Transaction amount Yes Positive decimal number, e.g. 123.45.
currency Currency Yes A three-letter abbreviation according to the currency accepted by the terminal.
kind Transaction type Yes Has to be "mobile" string, otherwise payment will not be sent on terminal
fetch_client Customer object No A value of true will result in the passing of the customer object in the back request.

In response, Espago Terminals will send a link to redirect the POS computer or, in the case of an invalid request, its reason.

link Back requests params

After the payment is completed, Espago Terminals sends information about its status.
Sample response:

{
  "payment": {
    "id": "tp_7d7z-noWFPW",
    "description": "Order #55665",
    "state": "success",
    "amount": "12.99",
    "currency": "PLN"
  },
  "client": {
    "id": "cli_7d7Cm9pP61YyvOKZ",
    "card": {
      "full_name": "Myrna Cummings",
      "company": "VI",
      "last4": "0002",
      "year": "2024",
      "month": "12",
      "country_code": "en"
    }
  }
}
Parameter Description Notes
payment Payment data
payment id Payment ID As assigned by Espago Terminals
payment description Description of the payment Provided by the merchant at the time of payment creation
payment state Payment status A value other than success means failure
payment amount Payment amount
payment currency Payment currency
client Client data Returned only if fetch_client=true
client id Id of client profile in Espago
client card Data of the card assigned to the profile
reject_reason Reason for rejecting payment This parameter is only sent if the transaction fails

link Payment rejected - reject_reason parameter

The reject_reason parameter contains a general infromation about payment rejection or refusal from the payment terminal. It is included in the response only when the payment status is failed. Returned together with payments via back requests and API request. It contains information about: name, message and description of the error. It is strictly informative to help locate a possible error.

{
    "payment": { 
        ...,
        "state": "failed"
        },
    "reject_reason": {
        "name": "declinedWrongPin",
        "message": "Authorization declined - Wrong PIN",
        "description": "Authorization failed, cardholder entered wrong PIN."
    }
}

link Payment status

Espago Terminals logs all communication with the terminal and all necessary information about the payment, including its status. You can view this information in the panel at https://espago.terminals.com/manage, but in case of ambiguity, the information on the terminal screen is always the superior source of information.

Possible payment states on the terminal:

State Description
new Payment created on Espago Terminals service, but the link assigned to it has not been used.
sent Payment sent to the terminal, awaiting completion.
success Payment completed, customer account was charged.
failed Payment failed.

link Recuring payments on terminal

Recuring payments based on the first transaction made on the terminal are very simple to implement, especially if the merchant already has integration with Espago’s standard payment gateway.

In order to get the transaction reference after the payment when it is created via a request on endpoint /api/charges, the fetch_client parameter should be added and given the value true. Then, when the payment is successful in the back request, we will get the client object with the id parameter.

{
  "payment": { ... },
  "client": {
    "id": "cli_7d7Cm9pP61YyvOKZ",
    "card": {
      "full_name": "Myrna Cummings",
      "company": "VI",
      "last4": "0002",
      "year": "2024",
      "month": "12",
      "country_code": "en"
    }
  }
}

After a successful payment, Espago Terminals creates a client profile for the standard Espago gateway. ID means the ID of the profile, which can be specified instead of the token (client: ...) in the payment creation parameters and can be used in the same way as a regular client profile created by a regular request to the Espago gateway.
You can read more about the client profile in client profile.

link Fetching client profile after payment was made

It is possible to get a client after making a payment with a status of success, even if the fetch_client parameter has not been set to true. This request can be especially useful for a payment that was made on the terminal, but for some reason the card data could not be extracted, and the client profile could not be created, although we would like to get it.
To do this, send a standard POST request to endpoint /api/payment/fetch_client with the parameter

Example request.

{
    "payment": "tp_3452342"
}

Example response.

{
    "client": {
        "id": "cli_83cSYFUwtQQ4Nd72",
        "card": {
            "full_name": "Gayle Erdman",
            "company": "VI",
            "last4": "0002",
            "year": "2025",
            "month": "12",
            "country_code": "en"
        }
    },
    "status": "ok"
}

link Terminal status

It is possible to get terminal data and its current status from API.
To do this, send a standard POST request to endpoint /api/terminal with the terminal parameter indicating the terminal’s TID.

The connection parameter indicates the status of the terminal’s connection to the cloud via the native application. If integrating via a browser extension, ignore this.

Example request.

{
    "terminal": "238409245"
}

Example response.

{
    "tid": "238409245",
    "ip": "192.168.0.2",
    "port": "7784",
    "name": "reception-2",
    "updated_at": "1628548083",
    "connection": {
        "connected": true,
        "busy": false
    }
}

link Getting transaction data

It is possible to pull the payment data and its current status through the API.
To do this, send a standard POST request to endpoint /api/payment with parameter payment indicating the payment id (tp_....).

Example request.

{
    "payment": "tp_83cePB345fg"
}

Example response.

{
    "guid": "tp_83cePNfN04b",
    "description": "order #345323",
    "state": "success",
    "amount": "15.99",
    "currency": "EUR"
}
~~~

link Refund payment executed on terminal

To execute refund on successfully charged payment, you need to send a POST request on https://terminals.espago.com/api/charges/(payment id)/refunds, and provide amount in JSON body.
Note: For complete emulation in sandbox environment, odd number of decimal points will result as failed transaction.

Example request:

/api/charges/tp_456xyz/refunds

{
  "amount": 5.99
}

Response:

{
  "id": "tp_456xyz",
  "refunded_amount": "5.99",
  "state": "refunded"
}

Espago.js web

link The functioning of Espago.js

NOTE: The use of Espago JS described here is an accepted, but older solution than Espago iFrame. For new integrations, we strongly suggest using the iFrame solution that gives more opportunities and is constantly being developed.

In order to facilitate the integration process, we’ve prepared a script which generates a created token and returns its value in the ‘card_token’ parameter.
The URL where you can find this script: https://js.espago.com/espago-1.3.js

If the payment form will be located on your website (directly, not through an Iframe) the use of this script (https://js.espago.com/espago-1.3.js) is mandatory. The script has to be downloaded directly form the Espago server.

The availability of the js.espago.com script (SLA) is the same as the Espage gateway’s, therefore there is no need to copy the script to your server. On the download page you can download the latest example of the form using JS script with jQuery.

The sample form uses the JQuery library, which is not required for Espago.js to work correctly. It is possible to implement Espago Payment Form in pure JavaScript.

When using the script https://js.espago.com/espago-1.3.js, form fields with card data (card number, expiration date, the owner) must not have the “name” parameter. The Espago script needs just ‘id’. To obtain this data, you can make a request to get token information or (the easiest way) to read them from the response from Espago gateway during creation of a customer profile (query /api/clients) or payments (query /api/charges).

1. Filling in the form

The client fills in the form with their data and calls the token creation action by clicking on a designated button

<script src='https://js.espago.com/espago-1.3.js' type='text/javascript'></script>
<form action='/charge' id='espago_form' method='POST'>
  <input id='espago_card_number' type='text'>
  <input id='espago_first_name' type='text'>
  <input id='espago_last_name' type='text'>
  <input id='espago_month' type='text'>
  <input id='espago_year' type='text'>
  <input id='espago_verification_value' type='text'>
  <input type='submit' value='Pay'>
</form>

2. Receiving

The ‘create_token()’ function is the main action which communicates with our Gateway. The merchant is identified based upon a previously specified public key and any sent card data are bound with a token. By default the espago.create_token() function calls a submit action.

var espago = new Espago({public_key: 'PfcMBQnqWjNF2ihkv9xs', custom: true, live: false})

$("#espago_form").submit(function(event){
  event.preventDefault()
  if (!espago.validate_card_number()){
    alert("Błędne dane!")
  }

  if (!espago.validate_first_name()){
    alert("Błędne dane!")
  }

  if (!espago.validate_last_name()){
    alert("Błędne dane!")
  }

  if (!espago.validate_card_date()){
    alert("Błędne dane!")
  }

  if (!espago.validate_card_cvc()){
    alert("Błędne dane!")
  }

  espago.create_token()
})

3. Calling the payment

Calling a normal payment with a token - read more about payments

link Espago constructor parameters

The form will function properly only if the action is called on a previously defined espago object. Any methods responsible for communication and validation of sent data must be called on this object. The created obejct has to contain the merchant’s public key. You can see an example of this implementation below:

var espago = new Espago({public_key: 'klucz_publiczny:'});

Parametry

Parameter Required Default values Description
public_key done Merchant’s public key
live true If value of this parameter is true, then requests from espago.js library are sent to production environment.
In the case of ‘false’ value of this parameter, requests are sent to test environment.
form #espago_form Name of the form
card_number #espago_card_number ID of the field with client’s card number
first_name #espago_first_name ID of the field with the customer’s name
last_name #espago_last_name ID of the field with the customer’s surname
month #espago_month ID of the field with the month of card expiration date
year #espago_year ID of the field with the year of card expiration date
cvc #espago_verification_value ID of the field with Card Verification number
custom false The ‘true’ value enables the option of defining custom success and error parameters.
success function(data) {} A callback function. Actions within will be executed only in case of a postive response.
error function(data) {} A callback function. Action within will be executed when errors occur.
submit true Form confirmation and submitting.

link Token creation

The main action of the script which communicates with the gateway. The merchant is identified by a previously specified public key and any sent credit card data are bound with a token.

espago.create_token()

By default the espago.create_token() executes the submit action. It is possible to disable it by appending a few additional parameters which can be seen below (disabling the submit action and the actions after an error occurs respectively):

espago.create_token({
  submit: false,
  success: (data) => { 
    alert("success")
  },
  error: (data) => { 
    alert("error");
  }
})

link Form fields

Default field ID Field type Description
espago_card_number text Client’s card number
espago_first_name text Client’s name
espago_last_name text Client’s surname
espago_month text The month of card expiration date
espago_year text The year of card expiration date
espago_verification_value text Verification code

All available validation functions are presented below. In the sample code of every function we introduced data subjected to validation. In the case of their absence, the default value is adequate form field value.

validate_card_number()

This method validates card number. If card number is typed with additional non-numeric characters, these characters will be ignored.

espago.validate_card_number('4242424242424242') //true
espago.validate_card_number('42 42 42 42 42 42 42 42') //true
espago.validate_card_number('42 42 42') //false
espago.validate_card_number() //the default value of this method is form field 'espago_card_number' value

validate_first_name()

This method validates card owner’s first name.

espago.validate_first_name('Jan') //true
espago.validate_first_name('') //false
espago.validate_first_name() //default value of this method is form field 'espago_first_name' value

validate_last_name()

This method validates card owner last name.

espago.validate_last_name('Kowalski') //true
espago.validate_last_name('') //false
espago.validate_last_name() //default value of this method is form field 'espago_last_name' value

validate_card_date()

This method validates card expiration date.

espago.validate_card_date('02', '2017') //true
espago.validate_card_date(02, 2017) //true
espago.validate_card_date(2, 17) //false
espago.validate_card_date() //default values of this method are form field  'espago_month' and 'espago_year' values

validate_card_cvc()

This method validates card cvc code.

espago.validate_card_cvc('123') //true
espago.validate_card_cvc('12') //false
espago.validate_card_cvc('xyx') //false
espago.validate_card_cvc() //default value of this method is form field 'espago_verification_value' value

Compatibility compare_arrows

link Constraints

The purpose of the API is to not limit in any way the technology used by merchant’s services, in which payments are to be integrated, as well as devices from which customers will make payments. Nevertheless, there are some requirements during communication with Espago gateway, and it results in some limitations of compatibility with older technologies:

Espago gateway requires connections using TLSv1.1 or TLSv1.2 with strong ssl ciphers. Every requirement and configuration about SSL/TLS is first implemented on our test gateway https://sandbox.espago.com. If your app works fine in the test environment, it will also work in the production environment (and connect with the production gateway)


Some olders systems, libraries or browsers doesn’t support this connections, and need to by upgraded - This requirement applies to connections to API, 3D-Secure redirections and access to WWW panel.

List of software that supports TLS 1.2 and TLSv1.1

System/ application/ library The minimum compatible version Additional notes
Windows 7 and later In Windows XP and Vista customer need to use alternative web browser (ie. Chrome, Firefox, Opera)
Windows Server 2008 R2 and later Windows 2008 R2 requires enabling TLSv1.2 in systems registry and enabling additional ssl ciphers
Android 4.4.4 and later Android API level 20. Partial support available also in 4.2
OpenSSL 1.0.1 and later Note: OpenSSL 0.9.8 (all subversion) does not support TLSv1.2
Apache 2.2.23 and later
Java 8 and later Note: Java 6 and Java 7 does not support TLSv1.2
.NET Framework 4.5.1 and later enabling in preferences may be needed, and it requires Windows that supports TLSv1.2

List of protocols and ssl ciphers allowing secure connection to the Espago gateway

It is recommended to configure the application to permit connections using the safest available protocols and ciphers, and to have the opportunity to connect with several sets of codes (ie. not forcing one specific one cipher).

Protocol Ciphers
TLSv1.3 TLS_AES_128_GCM_SHA256
TLS_AES_256_GCM_SHA384
TLS_CHACHA20_POLY1305_SHA256
TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256
ECDHE-RSA-AES128-GCM-SHA256
ECDHE-ECDSA-AES256-GCM-SHA384
ECDHE-RSA-AES256-GCM-SHA384
ECDHE-ECDSA-CHACHA20-POLY1305
ECDHE-RSA-CHACHA20-POLY1305

link Migration from APIv2

Please see Polish version for details.
Differences between API v.2.0 and v.3.0:
1. Every request to Espago gateway need to have a header with invormation about used API (more). If service has already APIv2.0 and API v3.0 enabled, when no header is defined default API version is 2.0.
2. 3D-Secure option may requir client redirection to the url address, which is sent in the response for the request /api/charges.
3. The Back requests are also sent for ordinary charges (in APIv2.0 back request are sent only in subscription’s payments).
4. New version 1.3 Espago JS script used in form to create tokens (more) and possibility to use Espago iFrame.
5. The new format of back requests: ‘Content-Type’ => ‘application / json; charset = utf-8 ’.
* During of migrating from version 2 to 3, you need to specify - in Merchant panel (more) - the format of “back request” for cyclic payment
* Back request format for ordinary charges is dependent on the version of the API which transactions are created. Accordingly application/x-www-form-urlencoded and application/json for API v. 2.0 and API v. 3.0.

link The payment form does not work in IE9 and older versions

For correct payment form functioning, you need Internet Explorer in version 10 or newer, or any other web browser (Google Chrome, Mozilla Firefox, Opera, Safari, etc). The payment form does not work with Internet Explorer in version IE9 and older. In some configurations there are also problems with token creation in Microsoft Edge ( due to limitation of CORS support in this browser).

The indicated IE browser incompatibility applies to any version of IE in Windows XP, so it is recommended for Windows XP users to make payments using any other browser. The indicated incompatibility is important for example for a program written in .NET on Windows XP, using the built-in system of IE or imitating it in an version earlier than or equal to IE9.

Explanation: https://js.espago.com/espago-1.3.js script that must be implemented in the payment form uses XMLHttpRequest addressed to a domain other than the seller (request to the Espago gateway forming a token), this is a Cross-Origin Resource Sharing, in short CORS. Older versions of IE do not allow such requests.

link Availability of functions at individual Acquirers

Function Elavon SIX
GENERAL
creating plans and subscriptions running by Espago yes no
default payment’s channel when parameter channel is not sent in charge request yes no
PAYMENTS
payment/authentication 3D-Secure on amount of 0 currency yes no
payment with flag cof=unscheduled yes no

Manage a service polymer

link Back requests settings

Ask a support (support@espago.com) for an english translation.

Google Pay™ payment

link Description

Google Pay allows buyers to make a fast and simple checkout without having to enter credit card data.
Card data is stored securely by Google.

There are two ways of implementing Google Pay support:
1. Using our Hosted Checkout solution – Espago Secure Web Page
2. Using Google Pay API on the Merchant’s domain and sending the received token to the Espago API with a POST request to /api/charges



All Merchants must adhere to the Google Pay APIs Acceptable Use Policy and accept the terms defined in the Google Pay API Terms of Service.

link Hosted Checkout

Google Pay can be handled entirely by Espago if you redirect the cardholder to Espago Secure Web Page.

In order to enable this feature one should contact the Espago support team.

Test payments

In the Sandbox environment the decimal value of transaction can be used to define the Secure Webpage simulated payment scenario.

Decimal value Payment scenario
n.00 successful with cryptogram, no 3D Secure
n.01 successful PAN_ONLY, 3D Secure Challenge
n.02 successful PAN_ONLY, 3D Secure Frictionless
n.10 rejected with cryptogram
n.11 rejected PAN_ONLY, 3D Secure Challenge
n.12 rejected PAN_ONLY, 3D Secure Frictionless
n.66 incorrect gatewayMerchantId

Where n is a natural number.

link Google Pay API integration


The integration itself is relatively simple:
1. Merchants integrates with the Google Pay API.
2. Buyer selects the Google Pay button on the Merchant’s website or mobile application.
3. Buyer finalizes the transaction and Google Pay returns the payment token to Merchant.
4. Merchant encodes the received token using base64 and sends it to the Espago API as a part of a POST request to /api/charges.


Google Pay API Web integration

In order to integrate your website with the Google Pay API, follow the instructions in the Google Pay API documentation for web applications, familiarize yourself with Google Pay web application brand guidelines and refer to Google Pay web application integration checklist.



Google Pay API Android integration

In order to integrate your Android application with the Google Pay API, follow the instructions in the Google Pay documentation for Android developers, familiarize yourself with GooglePay Android App Brand Guidelines and refer to Google Pay Android Integration Checklist.



Integration setup

In the code invoking the script, Merchant has to indicate the payment gateway and the Merchant ID. For the Espago gateway, the parameters take the following values:
gateway: 'espago',
gatewayMerchantId: '[merchant service app_id]'

For example:

const tokenizationSpecification = {
   type: 'PAYMENT_GATEWAY',
   parameters: {
     'gateway': 'espago',
     'gatewayMerchantId': 'ms_771eUTliRiZ'
   }
};

Supported card networks

Amongst the card networks supported by Google Pay, Espago supports all Visa, Mastercard and JCB cards, which implies the following Google Pay API configuration:

const allowedCardNetworks = ["JCB", "MASTERCARD","VISA"];

link Transfer of encrypted payment data to Espago and a charge request

After recieving encrypted payment data from Google Pay, Merchant has to encode it using base64, then send them to the Espago gateway as the value of the googlepay parameter.

A new charge is created after a POST request is sent to https://sandbox.espago.com/api/charges

The payment is initiated using the same parameters as in the case of charge parameters described in the chapter One-time payment. The exception is the new parameter googlepay and the value of the channel parameter, which must be equal to elavon_google_pay.

Currently Google Pay is available only for Elavon integrations




For PAN_ONLY payments, 3D Secure authentication is initiated automatically, similarly to card payments.
As a part of the API response, Merchant will receive a url address to redirect the customer (value of the redirect_url parameter).

link Google Pay payload generator

There is a form that generates Google Pay payloads for use in the sandbox.espago.com environment.

link Charge example

{
  "amount": 10,
  "currency": "pln",
  "channel": "elavon_google_pay",
  "description": "Espago docs Google Pay",
  "google_pay": "eyJwcm90b2NvbFZlcnNpb24iOiJFQ3YyIiwic2lnbmVkTWVzc2FnZSI6IntcImVuY3J5cHRlZE1lc3NhZ2VcIjpcInY4bmhGYVJVWmYveERJakhFcnAvOEc2WmdyK2xCcCt2N2cyL0MveXl4UmNhbGcwTElKUmF1NUljblVpYnZMMUh1UkdETTV2dVNYQUNxUG0yaSt3cFBBL0lrSzZvWko4WlNVdFFEcXc1K0RPY002a2ZJYy9jeUVtdmpXTWhVTkdDZkJ2dUF5RU0xeGk3dzU4MjNoVmhQemVUSk12K2YyYjZwQTAvZGZRZkpSWURjRVp1bjFWWGFFalRDdWFRcUVlV0x6RW81MDlBd25nOFJjYmFRelNzQXcwd0U4dUZsVDliRlY3cVc5N2svS3RuYTluYUdHR29UdmVaS3lKdDF4SmQ0NkhTRlkyNkN4WmxLRkppaGFLN2d4OW94RGVqVEE2VGtHL2tDd05keUZUQk4wSGY3ZEZUaUpEVkRiUklZOUtlalpkRXJwWnlQbHFES1luMWJSRytPSldWNGszWVhldmp6QWZoTmpzMWZyQ0dpTE5GeUtWa1RMRFl1enhOQWZobkQvZHpINVkyYkZUSnRqYmhOUFpNL3VmdmJMWjNTN1dKOVpuWFkxS2dyRlpNRFBzQkRjb3hjZE1nVmtMcVptQjVSNFZhUndDdm96M2JtcDhUd2tiVG5Vb2lndE5hQ29pclJ2TT1cIixcImVwaGVtZXJhbFB1YmxpY0tleVwiOlwiQk9IcXNPME55Z3NNQThFcHpyaGIyWTV5SjR0V3hjeU8wUmhJdTMyMmIvc1B0VE5uU3Q4RGlNUlVEZWx1WU5rbUZMcFJoeTg3blVPTTlNbk5KcVBhS3JzPVwiLFwidGFnXCI6XCJySU5Nay9DVjFjQUQzYVgwc2JOOSt2UEdjb1g4RGdzTHE0R0hld2NEMEw4PVwifSIsInNpZ25hdHVyZSI6Ik1FVUNJUUQ4ZkhSWG5kWFVjd2FpczltTW9Hd0QwSm90MlYvby9vOU41cG9JemRTS0V3SWdjdWw5RGhoSVppVGN3N2RrWisxUGtQbDlJZjBwNG1qamg5OVQvVXZZQ0NBPSIsImludGVybWVkaWF0ZVNpZ25pbmdLZXkiOnsic2lnbmVkS2V5Ijoie1wia2V5RXhwaXJhdGlvblwiOlwiMTc0MjgxMDMxNzAwMFwiLFwia2V5VmFsdWVcIjpcIk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRWhtUzhlbWExdEFhQWtHWkVmMERKVllHM0d5T3FNenpxL2lZR3JLZHZGbWlOK2s2cGdOQWNoTzFXRlo1NUFtYzZwL1o4RU5CdlZ3MnRhai9EaDNDNGNnPT1cIn0iLCJzaWduYXR1cmVzIjpbIk1FUUNJQ012Vm9mUVpzVDFQSmZORHR4aHZwS1c4SHRWbFRKYXBwdkVFQjJMbURsdkFpQTBLZElCNVVjNmFsdTlXSmJpSHBGbWRyclFkaHZwZHV2YnlsN1JybGhSQXc9PSJdfX0="
}
curl -i https://sandbox.espago.com/api/charges \
 -H "Accept: application/vnd.espago.v3+json" \
 -u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
 -d "amount=10" \
 -d "currency=pln" \
 -d "channel=elavon_google_pay"\
 -d "description=Espago docs Google Pay"\
  -d "google_pay=eyJwcm90b2NvbFZlcnNpb24iOiJFQ3YyIiwic2lnbmVkTWVzc2FnZSI6IntcImVuY3J5cHRlZE1lc3NhZ2VcIjpcInY4bmhGYVJVWmYveERJakhFcnAvOEc2WmdyK2xCcCt2N2cyL0MveXl4UmNhbGcwTElKUmF1NUljblVpYnZMMUh1UkdETTV2dVNYQUNxUG0yaSt3cFBBL0lrSzZvWko4WlNVdFFEcXc1K0RPY002a2ZJYy9jeUVtdmpXTWhVTkdDZkJ2dUF5RU0xeGk3dzU4MjNoVmhQemVUSk12K2YyYjZwQTAvZGZRZkpSWURjRVp1bjFWWGFFalRDdWFRcUVlV0x6RW81MDlBd25nOFJjYmFRelNzQXcwd0U4dUZsVDliRlY3cVc5N2svS3RuYTluYUdHR29UdmVaS3lKdDF4SmQ0NkhTRlkyNkN4WmxLRkppaGFLN2d4OW94RGVqVEE2VGtHL2tDd05keUZUQk4wSGY3ZEZUaUpEVkRiUklZOUtlalpkRXJwWnlQbHFES1luMWJSRytPSldWNGszWVhldmp6QWZoTmpzMWZyQ0dpTE5GeUtWa1RMRFl1enhOQWZobkQvZHpINVkyYkZUSnRqYmhOUFpNL3VmdmJMWjNTN1dKOVpuWFkxS2dyRlpNRFBzQkRjb3hjZE1nVmtMcVptQjVSNFZhUndDdm96M2JtcDhUd2tiVG5Vb2lndE5hQ29pclJ2TT1cIixcImVwaGVtZXJhbFB1YmxpY0tleVwiOlwiQk9IcXNPME55Z3NNQThFcHpyaGIyWTV5SjR0V3hjeU8wUmhJdTMyMmIvc1B0VE5uU3Q4RGlNUlVEZWx1WU5rbUZMcFJoeTg3blVPTTlNbk5KcVBhS3JzPVwiLFwidGFnXCI6XCJySU5Nay9DVjFjQUQzYVgwc2JOOSt2UEdjb1g4RGdzTHE0R0hld2NEMEw4PVwifSIsInNpZ25hdHVyZSI6Ik1FVUNJUUQ4ZkhSWG5kWFVjd2FpczltTW9Hd0QwSm90MlYvby9vOU41cG9JemRTS0V3SWdjdWw5RGhoSVppVGN3N2RrWisxUGtQbDlJZjBwNG1qamg5OVQvVXZZQ0NBPSIsImludGVybWVkaWF0ZVNpZ25pbmdLZXkiOnsic2lnbmVkS2V5Ijoie1wia2V5RXhwaXJhdGlvblwiOlwiMTc0MjgxMDMxNzAwMFwiLFwia2V5VmFsdWVcIjpcIk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRWhtUzhlbWExdEFhQWtHWkVmMERKVllHM0d5T3FNenpxL2lZR3JLZHZGbWlOK2s2cGdOQWNoTzFXRlo1NUFtYzZwL1o4RU5CdlZ3MnRhai9EaDNDNGNnPT1cIn0iLCJzaWduYXR1cmVzIjpbIk1FUUNJQ012Vm9mUVpzVDFQSmZORHR4aHZwS1c4SHRWbFRKYXBwdkVFQjJMbURsdkFpQTBLZElCNVVjNmFsdTlXSmJpSHBGbWRyclFkaHZwZHV2YnlsN1JybGhSQXc9PSJdfX0="
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new(user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD')
response = client.send(
  'api/charges',
  method: :post,
  body: {
    amount: 10,
    currency: 'pln',
    channel: 'elavon_google_pay',
    description: 'Espago docs Google Pay',
        google_pay: 'eyJwcm90b2NvbFZlcnNpb24iOiJFQ3YyIiwic2lnbmVkTWVzc2FnZSI6IntcImVuY3J5cHRlZE1lc3NhZ2VcIjpcInY4bmhGYVJVWmYveERJakhFcnAvOEc2WmdyK2xCcCt2N2cyL0MveXl4UmNhbGcwTElKUmF1NUljblVpYnZMMUh1UkdETTV2dVNYQUNxUG0yaSt3cFBBL0lrSzZvWko4WlNVdFFEcXc1K0RPY002a2ZJYy9jeUVtdmpXTWhVTkdDZkJ2dUF5RU0xeGk3dzU4MjNoVmhQemVUSk12K2YyYjZwQTAvZGZRZkpSWURjRVp1bjFWWGFFalRDdWFRcUVlV0x6RW81MDlBd25nOFJjYmFRelNzQXcwd0U4dUZsVDliRlY3cVc5N2svS3RuYTluYUdHR29UdmVaS3lKdDF4SmQ0NkhTRlkyNkN4WmxLRkppaGFLN2d4OW94RGVqVEE2VGtHL2tDd05keUZUQk4wSGY3ZEZUaUpEVkRiUklZOUtlalpkRXJwWnlQbHFES1luMWJSRytPSldWNGszWVhldmp6QWZoTmpzMWZyQ0dpTE5GeUtWa1RMRFl1enhOQWZobkQvZHpINVkyYkZUSnRqYmhOUFpNL3VmdmJMWjNTN1dKOVpuWFkxS2dyRlpNRFBzQkRjb3hjZE1nVmtMcVptQjVSNFZhUndDdm96M2JtcDhUd2tiVG5Vb2lndE5hQ29pclJ2TT1cIixcImVwaGVtZXJhbFB1YmxpY0tleVwiOlwiQk9IcXNPME55Z3NNQThFcHpyaGIyWTV5SjR0V3hjeU8wUmhJdTMyMmIvc1B0VE5uU3Q4RGlNUlVEZWx1WU5rbUZMcFJoeTg3blVPTTlNbk5KcVBhS3JzPVwiLFwidGFnXCI6XCJySU5Nay9DVjFjQUQzYVgwc2JOOSt2UEdjb1g4RGdzTHE0R0hld2NEMEw4PVwifSIsInNpZ25hdHVyZSI6Ik1FVUNJUUQ4ZkhSWG5kWFVjd2FpczltTW9Hd0QwSm90MlYvby9vOU41cG9JemRTS0V3SWdjdWw5RGhoSVppVGN3N2RrWisxUGtQbDlJZjBwNG1qamg5OVQvVXZZQ0NBPSIsImludGVybWVkaWF0ZVNpZ25pbmdLZXkiOnsic2lnbmVkS2V5Ijoie1wia2V5RXhwaXJhdGlvblwiOlwiMTc0MjgxMDMxNzAwMFwiLFwia2V5VmFsdWVcIjpcIk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRWhtUzhlbWExdEFhQWtHWkVmMERKVllHM0d5T3FNenpxL2lZR3JLZHZGbWlOK2s2cGdOQWNoTzFXRlo1NUFtYzZwL1o4RU5CdlZ3MnRhai9EaDNDNGNnPT1cIn0iLCJzaWduYXR1cmVzIjpbIk1FUUNJQ012Vm9mUVpzVDFQSmZORHR4aHZwS1c4SHRWbFRKYXBwdkVFQjJMbURsdkFpQTBLZElCNVVjNmFsdTlXSmJpSHBGbWRyclFkaHZwZHV2YnlsN1JybGhSQXc9PSJdfX0='
  }
)

puts response.body
{
  "id": "pay_8ffCLdBYBSzMk6HJ",
  "description": "Espago docs Google Pay",
  "channel": "elavon_google_pay",
  "amount": "10.00",
  "currency": "pln",
  "state": "executed",
  "client": "cli_8ffe5FGyhZceHb6q",
  "created_at": 1679651962,
  "card": {
    "company": "VI",
    "last4": "0006",
    "year": 2030,
    "month": 1,
    "created_at": 1679651962
  },
  "issuer_response_code": "00",
  "reversable": true,
  "transaction_id": "tr_8ffi3se3t"
}

More info about responses can be found here.

{
  "id": "pay_8ffaeAEaCyzUY-D-",
  "description": "Espago docs Google Pay",
  "channel": "elavon_google_pay",
  "amount": "10.00",
  "currency": "pln",
  "state": "new",
  "client": "cli_8ffEpSsgrShInvKc",
  "created_at": 1679651893,
  "card": {
    "company": "VI",
    "last4": "0006",
    "year": 2030,
    "month": 1,
    "created_at": 1679651893
  },
  "issuer_response_code": "",
  "transaction_id": "tr_8fftqyPct",
  "redirect_url": "https://sandbox.espago.com/secure_web_page/pay_8ffaeAEaCyzUY-D-"
}

BLIK phonelink_ring

link Introduction

BLIK is a Polish mobile payment platform that enables convenient and fast payments in both stationary and online stores using a 6-digit code. To use BLIK, your customers need a mobile application from a bank that supports BLIK payments.

BLIK payments are only available for the PLN currency


There are three ways to initiate a BLIK transaction:
1. Payment by sending a BLIK code to the Espago gateway.
2. Payment through the eblik.pl website.
3. BLIK one-click payment, after registering a BLIK one-click alias.

link BLIK charge by code

The seller must create a form within their application to obtain the BLIK number from the payer and then submit it to the Espago gateway via a POST request to the /api/charges address.
After the request is sent, the payer is prompted to confirm the BLIK transaction in their banking application, and the payment enters the blik_decision state.
The response with the final payment status is sent via a Back Request.


A new charge is created after a POST request is send to https://sandbox.espago.com/api/charges. The transaction needs to be executed with the use of the p24_blik payment channel.

For BLIK charge by code payments, it is necessary to send the parameter p24_regulation_accepted with a value of true. Because in this case, the payer will be directly redirected to the bank.

Parameter Description Format Mandatory
channel The value p24_blik must be passed. String Mandatory
blik_code The BLIK code (T6) generated in the payer’s banking application. String (6 characters) Mandatory if the alias_type parameter is not provided.
alias_type Provided when creating a one-click alias. Allowed values: one_click. String Optional
client The Client Profile ID (the created BLIK alias will be assigned to the Client Profile). String Optional
email Email address of the payer. String Mandatory (unless the client parameter is provided with the Client ID that has an assigned email address).
return_url URL to which the client will be forwarded after the transaction processing String Optional, if parameter blik_code is provided. Mandatory for eblik.pl payments.
locale Transaction language String, Language code in ISO 639-1 standard. Available values: bg, cs, de, en, es, fr, hr, hu, it, nl, pl, pt, se, sk. Optional
p24_regulation_accepted Acceptance of the Przelewy24 terms and conditions. Specifies whether the payer will be shown the consent after redirection to the P24 page. The default value is false - do show. Boolean Optional

When providing the value true, for the the p24_regulation_accepted parameter - partner’s website must include the consent statement: “I hereby state that I have read the regulations and information obligation of Przelewy24”.
The words "regulations” and “information obligation” must contain links to the respective documents. The checkbox cannot be pre-selected.

{
  "channel": "p24_blik",
  "blik_code": "777100",
  "amount": 10,
  "currency": "PLN",
  "description": "Espago docs P24 BLIK",
  "email": "example@example.com"
}
curl -i https://sandbox.espago.com/api/charges \
 -H "Accept: application/vnd.espago.v3+json" \
 -u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
 -d "channel=p24_blik" \
 -d "blik_code=777100" \
 -d "amount=10" \
 -d "currency=PLN" \
 -d "description=Espago docs P24 BLIK" \
 -d "email=example@example.com"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param method_name [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new(user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD')
response = client.send(
  "api/charges",
  method: :post,
  body: {
    channel: 'p24_blik',
    blik_code: '777100',
    amount: 10,
    currency: 'PLN',
    description: 'Espago docs P24 BLIK',
    email: 'example@example.com'
  }
)

puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/charges');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "channel=p24_blik&blik_code=7771000&amount=10&currency=PLN&description=Espago docs P24 Blik&email=example@example.com");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);
{
  "id":"pay_901X97fmqW7-ZQqo",
  "description":"Espago docs P24 Blik",
  "channel":"p24_blik",
  "amount":"10.00",
  "currency":"PLN",
  "state":"blik_decision",
  "email":"example@example.com",
  "created_at":1684166626,
  "transaction_id":"p24_901E5Jsu2IlhzNE2"
}

link eblik.pl Payment

In case the blik_code parameter is not provided, the payment status will be returned as new along with a link to redirect the payer to the eblik page where they can enter the BLIK code. This option is not available when creating a one_click alias. After successful redirection, the payment status changes to blik_redirected.

The final payment status response is sent through a Back Request.

{
  "channel": "p24_blik",
  "amount": 10,
  "currency": "PLN",
  "description": "Espago docs P24 BLIK",
  "return_url": "https://espago.com",
  "email": "example@example.com"
}
curl -i https://sandbox.espago.com/api/charges \
 -H "Accept: application/vnd.espago.v3+json" \
 -u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
 -d "channel=p24_blik" \
 -d "amount=10" \
 -d "currency=PLN" \
 -d "description=Espago docs P24 BLIK" \
 -d "return_url=https://espago.com" \
 -d "email=example@example.com"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param method_name [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new(user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD')
response = client.send(
  "api/charges",
  method: :post,
  body: {
    channel: 'p24_blik',
    amount: 10,
    currency: 'PLN',
    description: 'Espago docs P24 BLIK',
    return_url: 'https://espago.com',
    email: 'example@example.com'
  }
)

puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/charges');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "channel=p24_blik&amount=10&currency=PLN&description=Espago docs P24 Blik&return_url=https://espago.com&email=example@example.com");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);
{
  "id":"pay_901oh54m1sFgJfHj",
  "description":"Espago docs P24 Blik",
  "channel":"p24_blik",
  "amount":"10.00",
  "currency":"PLN",
  "state":"new",
  "email":"example@example.com",
  "created_at": 1684166942,
  "transaction_id": "p24_901GMO87ibiWf8KZ",
  "redirect_url":"https://sandbox.espago.com/p24_eblik/pay_901oh54m1sFgJfHj"
}

link BLIK one-click

BLIK one-click payments allow for making purchases without the need to enter the BLIK code, only by confirming the payment in the mobile application.


Registration of a BLIK one-click alias occurs after initiating a charge request for the p24_blik channel, using the alias_type=one_click parameter.

The alias registration request will be forwarded to the BLIK system, and the customer will receive an invitation in their banking application for payment without a BLIK code at the Merchant’s store.
If the customer’s decision is positive, the alias will be registered in the BLIK system, and the customer will not be asked for a BLIK code during future payments.

Depending on the use of the Client Profile in the API request, there are 3 scenarios for registering a one-click alias.

Client Profile Result
No One-time payment and creating a Client Profile with a one-click alias, if the customer approves.
Yes (without active alias) One-time payment and adding the alias to the Client Profile, if the customer approves.
Yes (with active alias) One-time payment and registering another bank application for the alias.


{
  "channel": "p24_blik",
  "blik_code": "777101",
  "amount": 21.04,
  "currency": "PLN",
  "description": "Espago docs P24 BLIK",
  "email": "example@example.com",
  "alias_type": "one_click"
}
curl -i https://sandbox.espago.com/api/charges \
 -H "Accept: application/vnd.espago.v3+json" \
 -u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
 -d "channel=p24_blik" \
 -d "blik_code=777101" \
 -d "amount=21.04" \
 -d "currency=PLN" \
 -d "description=Espago docs P24 BLIK" \
 -d "email=example@example.com"
 -d "alias_type=one_click"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param method_name [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new(user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD')
response = client.send(
  "api/charges",
  method: :post,
  body: {
    channel: 'p24_blik',
    blik_code: '777101',
    amount: 21.04,
    currency: 'PLN',
    description: 'Espago docs P24 BLIK',
    email: 'example@example.com',
    alias_type: 'one_click'
  }
)

puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/charges');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "channel=p24_blik&blik_code=777101&amount=21.04&currency=PLN&description=Espago docs P24 Blik&email=example@example.com&alias_type=one_click");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);
{
  "id":"pay_901D3j3SglzRigHQ",
  "description":"Espago docs P24 Blik",
  "channel":"p24_blik",
  "amount":"21.04",
  "currency":"PLN",
  "state":"blik_decision",
  "email":"example@example.com",
  "created_at":1684166626,
  "transaction_id":"p24_901E5maO86lhzNE2",
  "client":"cli_9015q7ioPP2EllAO"
}

Starting a new charge for a one-click alias is done by sending a POST request to the address https://sandbox.espago.com/api/charges. One-click transactions must be processed through the p24_blik_alias payment channel.


For BLIK one-click alias payments, it is necessary to send the parameter p24_regulation_accepted with a value of true. Because in this case, the payer will be directly redirected to the bank.

Parameter Description Format Mandatory
channel The value should be p24_blik_alias String Mandatory
alias_type Indicates which type of alias to use String, allowed values: one_click Mandatory
client The ID of the client profile String Mandatory
email Email address of the payer. String Mandatory (unless the client parameter is provided with a client ID that has an associated email address)
locale Transaction language String, Language code in ISO 639-1 standard. Available values: bg, cs, de, en, es, fr, hr, hu, it, nl, pl, pt, se, sk. Optional
p24_regulation_accepted Acceptance of the Przelewy24 terms and conditions. Specifies whether the payer will be shown the consent after redirection to the P24 page. The default value is false - do show. Boolean Mandatory

When providing the value true, for the the p24_regulation_accepted parameter - partner’s website must include the consent statement: “I hereby state that I have read the regulations and information obligation of Przelewy24”.
The words "regulations” and “information obligation” must contain links to the respective documents. The checkbox cannot be pre-selected.

{
  "channel": "p24_blik_alias",
  "alias_type": "one_click",
  "amount": 10,
  "currency": "PLN",
  "description": "Espago docs P24 BLIK",
  "client": "cli_8a2lAMfJiJRblhYR"
}
curl -i https://sandbox.espago.com/api/charges \
 -H "Accept: application/vnd.espago.v3+json" \
 -u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
 -d "channel=p24_blik_alias" \
 -d "alias_type=one_click" \
 -d "amount=10" \
 -d "currency=PLN" \
 -d "description=Espago docs P24 BLIK" \
 -d "client=cli_8a2lAMfJiJRblhYR"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param method_name [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new(user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD')
response = client.send(
  "api/charges",
  method: :post,
  body: {
    channel: 'p24_blik_alias',
    alias_type: 'one_click',
    amount: 10,
    currency: 'PLN',
    description: 'Espago docs P24 BLIK',
    client: 'cli_8a2lAMfJiJRblhYR'
  }
)

puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/charges');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "channel=p24_blik_alias&alias_type=one_click&amount=10&currency=PLN&description=Espago docs P24 Blik&client=cli_8a2lAMfJiJRblhYR");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);
{
  "id":"pay_9011PZTylAm-JEsM",
  "description":"Espago docs P24 Blik",
  "channel":"p24_blik_alias",
  "amount":"10.00",
  "currency":"PLN",
  "state":"blik_decision",
  "email":"example@example.com",
  "created_at":1684166626,
  "transaction_id":"p24_901E1z-JffNa-F4098",
  "client":"cli_8a2lAMfJiJRblhYR"
}


A customer profile can have one active one-click alias registered. Multiple bank applications of the payer can be registered to a single one-click alias. After registering a second bank application, the Espago API will return a payment with the new status and a list of available applications to choose from in response to the api/charges request on the p24_blik_alias channel (for a given customer profile):

"alternative_keys": [
    {
        "label": "TEST APP 032",
        "alias": "617987"
    },
    {
        "label": "TEST APP 028",
        "alias": "617986"
    }
]

To complete the payment, send a POST request to the api/charges/(:id)/blik_app_decision endpoint, sending the alias parameter in the request body. For example:

POST /api/charges/pay_8a1UC6bjMbhsBbYH/blik_app_decision

{
    "alias": "617987"
}

These aliases are variable and there is no need to save them for later use.

{
  "alias": "617987"
}
curl -i https://sandbox.espago.com/api/charges/pay_8a1UC6bjMbhsBbYH/blik_app_decision \
 -H "Accept: application/vnd.espago.v3+json" \
 -u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
 -d "alias=617987"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param method_name [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new(user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD')
response = client.send(
  "api/charges/pay_8a1UC6bjMbhsBbYH/blik_app_decision",
  method: :post,
  body: {
    alias: '617987'
  }
)

puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/charges/pay_8a1UC6bjMbhsBbYH/blik_app_decision');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "alias=617987");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);
{
  "id":"pay_9011PZTylAm-JEsM",
  "description":"Espago docs P24 Blik",
  "channel":"p24_blik_alias",
  "amount":"10.00",
  "currency":"PLN",
  "state":"blik_decision",
  "email":"example@example.com",
  "created_at":1684166626,
  "transaction_id":"p24_901E1z-JffNa-F4098",
  "client":"cli_8a2lAMfJiJRblhYR"
}

To see the assigned BLIK aliases for a client profile, you need to use the Client Profile data fetching method.
The BLIK one-click alias is visible as the p24_blik_alias_one_click parameter.

Example of Client Profile’s data with a registered one-click alias.

{
    "email": "example@example.com",
    "id": "cli_8a2lAMfJiJRblhYR",
    "created_at": 1665433136,
    "description":"Client with a BLIK alias",
    "card": {
        "company":"VI",
        "last4":"4242",
        "year":2022,
        "month":2,
        "first_name":"Jan",
        "last_name":"Kowalski",
        "authorized":true,
        "created_at":1561126879
    },
    "p24_blik_alias_one_click": {
        "kind": "one_click",
        "state": "registered",
        "email": "example@example.com",
        "expiration_date": 1728476779,
        "value": "27c798a90f9fbbb546c5c5cda71bacb87c8ee5a644c2f9ab384c5336ad50"
    },
    "deleted": false
}

If the payer does not accept the registration of the one-click alias, an inactive alias (“state”: “unregistered”) will be assigned to their customer profile.

link Test payments

BLIK payments in the Sandbox environment are automatically confirmed. The response with the final payment status is sent via Back Request, just like in the production environment.

To correctly process BLIK payments, codes should be created according to the pattern 777xxx, where x represents any digit. BLIK codes are one-time-use, and should be changed for each subsequent test charge attempt.

The sandbox environment will return a specific error code when a BLIK transaction is made with the appropriate amount:
- 288.00 — ALIAS_DECLINED
- 192.00 — TAS_DECLINED
- 144.00 — USER_DECLINED
- 216.00 — SEC_DECLINED
- 264.00 — SYSTEM_ERROR
- 360.00 — GENERAL_ERROR
- 120.00 — INSUFFICIENT_FUNDS
- 312.00 — TIMEOUT
- 96.00 — LIMIT_EXCEEDED
- 336.00 — USER_TIMEOUT
- 168.00 — ISSUER_DECLINED

In the sandbox environment, the BLIK one-click alias can be confirmed (status REGISTERED) by making a BLIK transaction for an amount with the “04” decimal value, e.g. 21.04 PLN.

Changing the status of the BLIK one-click alias to UNREGISTERED requires making a BLIK transaction with a payment amount with the “33” decimal value, for example 37.33 PLN.

Fast Bank Transfer account_balance

link How to order a bank transfer

It is possible to make a payment via bank transfer using the “Przelewy24” platform. To initiate the transaction, you need to send a POST request to the /api/charges path. In response, you will receive a redirect_url parameter, which contains the URL to redirect the client to the “Przelewy24” payment page. After the redirection, the payment will enter the transfer_redirected state. The final payment status will be sent asynchronously through a back request.

To initiate a new charge, send a POST request to the address https://sandbox.espago.com/api/charges. Bank transfer transactions must be made through the p24_transfer payment channel.

{
  "channel": "p24_transfer",
  "amount": 10,
  "currency": "PLN",
  "description": "Espago docs P24 Transfer",
  "email": "example@example.com",
  "return_url": "https://espago.com",
  "p24_regulation_accepted": true
}
curl -i https://sandbox.espago.com/api/charges \
 -H "Accept: application/vnd.espago.v3+json" \
 -u ms_771eUTliRiZ:SeCreT_P@ssw0rD \
 -d "channel=p24_transfer" \
 -d "amount=10" \
 -d "currency=PLN" \
 -d "description=Espago docs P24 Transfer" \
 -d "email=example@example.com" \
 -d "return_url=https://espago.com" \
 -d "p24_regulation_accepted=true"
require 'net/http'
require 'uri'
require 'json'

class EspagoClient
  # @param user [String]
  # @param password [String]
  def initialize(user:, password:)
    @user = user
    @password = password
  end

  # @param path [String]
  # @param body [Hash, nil]
  # @param method [Symbol]
  # @return [Net::HTTPResponse]
  def send(path, body: nil, method: :get)
    uri = URI.join('https://sandbox.espago.com', path)
    request = request_class(method).new(uri)
    request.basic_auth(@user, @password)
    request['Accept'] = 'application/vnd.espago.v3+json'
    request['Content-Type'] = 'application/json'
    request.body = body.to_json if body

    Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
      http.request(request)
    end
  end

  private

  # @param method_name [Symbol]
  # @return [Class<Net::HTTPRequest>]
  def request_class(method_name)
    Net::HTTP.const_get(method_name.to_s.capitalize)
  end
end

client = EspagoClient.new(user: 'ms_771eUTliRiZ', password: 'SeCreT_P@ssw0rD')
response = client.send(
  "api/charges",
  method: :post,
  body: {
    channel: 'p24_transfer',
    amount: 10,
    currency: 'PLN',
    description: 'Espago docs P24 Transfer',
    email: 'example@example.com',
    return_url: 'https://espago.com',
    p24_regulation_accepted: true
  }
)

puts response.body
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://sandbox.espago.com/api/charges');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "channel=p24_transfer&amount=10&currency=PLN&description=Espago docs P24 Transfer&return_url=https://espago.com&email=example@example.com");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_USERPWD, 'ms_771eUTliRiZ' . ':' . 'SeCreT_P@ssw0rD');

$headers = array();
$headers[] = 'Accept: application/vnd.espago.v3+json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);
{
  "id":"pay_901oh54m1sFgJfHj",
  "description":"Espago docs P24 Transfer",
  "channel":"p24_transfer",
  "amount":"10.00",
  "currency":"PLN",
  "state":"new",
  "email":"example@example.com",
  "created_at": 1684166942,
  "transaction_id": "p24_902rCZV7MGssIo61",
  "redirect_url":"https://sandbox.espago.com/payment_p24/pay_901oh54m1sFgJfHj"
}

Parameter Description Format Mandatory
channel Value p24_transfer must be passed. String Mandatory
amount Transaction amount Decimal number, up to 2 decimal places. For example: 123.45. Mandatory
description Transaction description String, from 5 to 99 characters. Mandatory
email Email address of the payer. String Mandatory (unless the client parameter is provided with a client ID that has an associated email address)
return_url URL to which the client will be forwarded after the transaction processing String Mandatory
locale Transaction language String, Language code in ISO 639-1 standard. Available values: bg, cs, de, en, es, fr, hr, hu, it, nl, pl, pt, se, sk. Optional
p24_regulation_accepted Acceptance of the Przelewy24 terms and conditions. Specifies whether the payer will be shown the consent after redirection to the P24 page. The default value is false - do show. Boolean Optional

When providing the value true, for the the p24_regulation_accepted parameter - partner’s website must include the consent statement: “I hereby state that I have read the regulations and information obligation of Przelewy24”.
The words "regulations” and “information obligation” must contain links to the respective documents. The checkbox cannot be pre-selected.

Apple Pay credit_card

link Hosted Checkout

Apple Pay can be handled entirely by Espago if you redirect the cardholder to Espago Secure Web Page.

In order to enable this feature one should contact the Espago support team.

Test payments

In the Sandbox environment the decimal value of transaction can be used to define the Secure Webpage simulated payment scenario.

Decimal value Payment scenario
n.00 successful
n.10 rejected
n.20 rejected ECI=7

Where n is a natural number.

link Apple Pay payload generator

There is a form that generates Apple Pay payloads for use in the sandbox.espago.com environment.

Welcome to the Espago docs!

We use cookies to enhance your experience. By continuing to visit this site you agree to our use of cookies. Enjoy Espago docs!

Espago Team