We implemented the OAuth 2.0 standard so you can communicate with our APIs with a single Bearer token.
Once you receive the access token, you must include it as an authorization header every time you communicate with our APIs.
Example in Curl:
curl https://api.pomelo.la -H 'Authorization: Bearer eyJhbGciOiJSUzI1Ni'
Each API validates the access token and verifies that the scope matches the required permissions.
For the requests to be valid, communicate with our APIs only via HTTPS and include the authorization header indicating that it is a Bearer type.
The endpoint /oauth/v1/token is used to obtain an access token. When performing a successful authentication, be sure to save it as you will need it to communicate with our APIs.
Each token is a JWT that contains an expiration time. Request a new token only when the token you have has expired.
The Users API contains all the endpoints needed to manage the user bases. You can use it to create, update or even search for users within certain parameters.
The /users/v1/ endpoint allows you to create a new user in our database.
The number of parameters required to create a user varies depending on the product you have signed up for, but we will always ask you for email and operation_country.
Cada usuario debe tener un email único, También debe ser única la combinación de tipo de documento de identidad y valor.
The types of identity documents accepted are the following:
In the case of the DNI, we will validate that its extension is 7 or 8 characters.
The type of fiscal document accepted is the CUIL.
The types of identity documents accepted are the following:
The type of fiscal document accepted is the CPF. We will validate that its extension is 11 characters.
The types of identity documents accepted are the following:
The type of tax document accepted is the RFC, but it will not be mandatory to include it.
If you operate in Argentina, the user’s legal address must be from one of these provinces:
Si operas en Brasil, deberás completar el campo zipcode
con un dato válido, ya que lo usaremos para determinar la dirección legal del usuario.
If you operate in Mexico, there are no special requirements regarding the user's legal address fields.
The /users/v1/ endpoint allows you to search for a group of users and receive a list sorted according to the parameters specified.
Filters must be specified as parameters following this pattern: filter[campo]=valor
. For example: /users/v1/?filter[status]=ACTIVE
To filter an attribute for several possible values, separate the values with commas.
Let's look at an example: filter[status]=ACTIVE,BLOCKED
The results are paginated and you can specify the amount of data per page and also which page to view using: page[number]=value and page[size]=value
You can specify the order of the results with certain parameters that you must send as list of strings in the sort filter type. For example: ?filter[status]=ACTIVE&sort=status,gender
The default sorting will be ascending. To specify a descending sorting, you must send the character '-' as a prefix of the attribute. For example: /users/v1/?filter[status]=ACTIVE&sort=status,-gender
The possible sorting attributes are:
id
gender
identification_type
identification_value
status
If a parameter is incorrect or misspelled, it will return an error.
The /users/v1/{id} endpoint allows you to query a user’s information through their user_id.
The endpoint /users/v1/{id} allows you to update a user’s information with their ID.
To block a user you must send the status
with the value BLOCKED
and the value CLIENT_INTERNAL_REASON
in the status_reason
field.
To reactivate a user you have blocked, you will need to send status
with value ACTIVE
.
Cada usuario debe tener un email único. También debe ser única la combinación de tipo de documento de identidad y valor.
The types of identity documents accepted are the following:
In the case of the DNI, we will validate that its extension is 7 or 8 characters.
The type of fiscal document accepted is the CUIL.
The types of identity documents accepted are the following:
The type of fiscal document accepted is the CPF. We will validate that its extension is 11 characters.
The types of identity documents accepted are the following:
The type of tax document accepted is the RFC, but it will not be mandatory to include it.
If you operate in Argentina, the user’s legal address must be from one of these provinces:
Si operas en Brasil, deberás completar el campo zipcode
con un dato válido, ya que lo usaremos para determinar la dirección legal del usuario.
If you operate in Mexico, there are no special requirements regarding the user's legal address fields.
The Cards API contains all the endpoints needed to create nominate and innominate cards, activate them, run queries, retrieve information on a particular card, and more.
The endpoint /cards/v1/{id}
enables retrieving information about a particular card.
The parameter extend
is used to retrieve additional data on a card.
The endpoint /cards/v1/{id}
enables updating a card’s status, affinity group, and PIN.
You will need to specify a reason from the list below in order to update a card status:
New status | Valid reason |
---|---|
BLOCKED / DISABLED | CLIENT_INTERNAL_REASON |
BLOCKED / DISABLED | USER_INTERNAL_REASON |
DISABLED | FRAUDULENT |
DISABLED | LOST |
DISABLED | STOLEN |
DISABLED | BROKEN |
DISABLED | UPGRADE |
The endpoint /cards/v1/{id}/shipment
enables updating the shipping address of a card.
The card must be physical, nominate and have a CREATED
status.
The endpoint /cards/v1/
enables searching for a group of cards based on the attributes specified.
You will need to specify your filters as parameters following this pattern: filter[campo]=valor
. For example: filter[status]=CREATED
.
To filter an attribute for several possible values, separate the values with commas.
Let's look at an example: filter[status]=CREATED,ACTIVE
The results are paginated and you can specify the amount of data per page and also which page to view using: page[number]=value and page[size]=value
You can specify the order of the results with certain parameters that you must send as list of strings in the sort filter type. For example: /cards/v1/?sort=status,card_type
.
The default sorting will be ascending. To specify a descending sorting, you must send the character '-' as a prefix of the attribute. For example: /cards/v1/?sort=status,-card_type
.
The possible sorting attributes are:
card_type
user_id
status
affinity_group_id
status_detail
shipment_id
innominate
.If a parameter is incorrect or misspelled, it will return an error.
The endpoint /cards/v1/
enables you to create a new physical or virtual card.
To create a new physical card, you will need to specify the shipping address.
You can use the previous_card_id
parameter to specify that a card is a replacement for a previous card.
To make sure that a request is not run more than once, please send the header: x-idempotency-key with a unique ID to use our idempotency schema. If two requests have the header with the same ID, we only create one card and the two requests have the same positive response
The endpoint /cards/v1/batches
enables you to create a batch of innominate cards.
A batch can have a maximum of 1000 cards.
The shipping address is mandatory when distribution type is CLIENT
.
We will process the call asynchronously, i.e. the cards may not be available immediately.
The endpoint /cards/v1/batches/shipments/{shipmentId}
enables updating the shipping address of a batch of cards.
The card batch must be physical, innominate and have a CREATED
status.
The endpoint /cards/v1/activation
enables you to activate a physical card and also set up a PIN.
The user must be active and the card must have a EMBOSSED
status.
The PIN to set up:
You can use the previous_card_id
parameter to specify that a card is a replacement for a previous card.
The Shipping API contains all the endpoints and webhooks needed to create a shipment, get information about a shipment and stay up-to-date on events that affect a shipment.
You need a public endpoint so we can communicate about what’s new in shipments in real time.
Your endpoint should end in /shipping/updates
We will notify you there if there are updates about a shipment. You are responsible for searching for the resource to get the updated status.
POST https://api.current-customer.com/whatever/shipping/updates
{
'shipment_id': 'shi-20VphpUWbbGm0Nwo8DMqsFBJgYv',
'meta': {
'resource_url': 'http://localhost:8080/v1/{shipment_id}'
}
}
curl --request POST \
--url https://api.current-customer.com/whatever/shipping/updates \
--header 'Content-Type: application/json' \
--data '{
'shipment_id' : 'shi-20VphpUWbbGm0Nwo8DMqsFBJgYv',
'meta' : {
'resource_url' : 'http://localhost:8080/v1/shi-20VphpUWbbGm0Nwo8DMqsFBJgYv'
}
}'
As a security measure, all update notifications will include a hmac-sha256 signature, but the reply does not need to be signed by customers.
To ensure that the only participants in the communication are our backends (Pomelo and the Client), we provide you with an api-key and api-secret during onboarding to digitally sign the content of the communication.
Below we explain the key-exchange and order- signing processes in more depth.
During the onboarding process, we create an api-key and api-secret specific to you.
It is also possible to use gpg or an email plugin (such as https://flowcrypt.com/).
Let’s look at an example using openssl on the command line.
$ echo -e 'api-key=$(openssl rand -base64 32)\napi-secret=$(openssl rand -base64 32)' > api-credentials.txt
$ cat api-credentials.txt
api-key=tgeAkX0795jKTxrVR0cJbb//D8UlhHn0KZwTcDG3gyg=
api-secret=un/OHwD+fMN1TTSaEhs0vupQEDQS7DVaUdlNOu7Fpyw=
$ openssl genrsa -out private.pem 2048
$ openssl rsa -in private.pem -pubout -out public.pem
Send us your public.pem public key by email or Slack.
We encrypt the credential file with the public key you gave us:
$ openssl rsautl -encrypt -in api-credentials.txt -out api-credentials.txt.enc -inkey public.pem -pubin
We send the api-credentials.txt.enc file by email or Slack
Decrypt the api-credentials.txt.enc file with your private.pem private key:
$ openssl rsautl -decrypt -in api-credentials.txt.enc -inkey private.pem
api-key=tgeAkX0795jKTxrVR0cJbb//D8UlhHn0KZwTcDG3gyg=
api-secret=un/OHwD+fMN1TTSaEhs0vupQEDQS7DVaUdlNOu7Fpyw=
Along with the authorization or adjustment request we’ll send you HTTP headers with the signature, timestamp and the api-key so that you can verify the signature is correct.
The HTTP headers we send are:
x-api-key
: this header allows you to identify which api-secret you have to use in the event that multiple api-key and api-secret pairs have been configured.
x-signature
: this header contains the digital signature (body + timestamp + endpoint) that you must verify to ensure request integrity. If the signature does not match, the order must be rejected.
x-timestamp
: this header contains the moment the order was signed in unix-epoch format so that you can verify that the signature has not expired.
x-endpoint
: the endpoint to which the request is made and used to generate the signature. Use this header to regenerate the signature to be validated, compare it with the endpoint of your service and verify that they match.
Let’s look at a sample curl indicating how this information is sent within the request:
curl --location --request POST 'localhost:9090/shipping/updates' \
--header 'x-api-key: h3Ws4Cv09JcCdw7732ig+1Eq3I2b+IWOI1anUu1A4dE=' \
--header 'x-signature: hmac-sha256 kLV3Jeyn7qbKfGHLDQKKuy5xzG/kbPrYEg8RvD8jb8A=' \
--header 'x-timestamp: 1637117179' \
--header 'x-endpoint: {clientPath}/shipping/updates'
--header 'Content-Type: application/json' \
--data-raw '{
'shipment_id' : 'shi-20VphpUWbbGm0Nwo8DMqsFBJgYv',
'meta' : {
'resource_url' : 'http://localhost:8080/v1/shi-20VphpUWbbGm0Nwo8DMqsFBJgYv'
}
}'
To set up a signature you can use the following code snippet (in python 3) such as:
import hmac, hashlib, base64, time
############# Pomelo's side ################
############################################
# pomelo's secret key
pomelo_secret_key = base64.b64decode('kLV3Jeyn7qbKfGHLDQKKuy5xzG/kbPrYEg8RvD8jb8A=')
# the update data pomelo is gonna use to make the signature
pomelo_update_body = '{
'shipment_id' : 'shi-20VphpUWbbGm0Nwo8DMqsFBJgYv',
'meta' : {
'resource_url' : 'http://localhost:8080/v1/shi-20VphpUWbbGm0Nwo8DMqsFBJgYv'
}
}'
client_req_endpoint = '/shipping/updates'
pomelo_timestamp = str(int(time.time()))
# the request data signed out by pomelo
pomelo_signature = hmac.new(pomelo_secret_key, bytes(pomelo_timestamp + client_req_endpoint + pomelo_update_body, 'utf-8'), hashlib.sha256).digest()
############# Client's side ################
############################################
# client's secret key
client_secret_key = base64.b64decode('kLV3Jeyn7qbKfGHLDQKKuy5xzG/kbPrYEg8RvD8jb8A=')
# client's api endpoint
client_api_endpoint = '/transactions/authorizations'
# signature expiration offset
signature_expiration_offset = 60 #A minute of expiration
# the authorizacion data the client needs to use to recreate the signature
client_request_data = bytes(pomelo_timestamp + client_req_endpoint + pomelo_update_body, 'utf-8')
# the signature the client has recreated
signature = hmac.new(client_secret_key, client_request_data, hashlib.sha256).digest()
# if signature is not expired and they match you can trust the request, otherwise reject it
now = int(time.time()) - signature_expiration_offset
signatureExpired = int(pomelo_timestamp) < now
signaturesMatch = hmac.compare_digest(signature, pomelo_signature)
endpointsMatch = client_api_endpoint in client_req_endpoint
requestIsValid = not signatureExpired and signaturesMatch
################ Results ###################
############################################
print('pomelo' signature = {0}'.format(base64.b64encode(pomelo_signature)))
print('client's signature = {0}'.format(base64.b64encode(signature)))
print('signature expired = {0}'.format(signatureExpired))
print('signatures match = {0}'.format(signaturesMatch))
print('endpoints match = {0}'.format(endpointsMatch))
print('request is valid = {0}'.format(requestIsValid))
The /shipments/v1/
endpoint is used to create a new shipment.
Si operas en Brasil, deberás completar el campo region
con el código UF de dos carácteres. Ejemplo: 'SP' para São Paulo Ver códigos UF
Para Brasil el taxIdentificationNumber
es obligatorio.
The /shippining/v1/
endpoint allows you to search for a group of shipments based on attributes you specify.
Filters must be specified as parameters following this pattern: filter[campo]=valor
. For example: filter[shipment_type]=BOX
.
To filter an attribute for several possible values, separate the values with commas. Let's look at an example: filter[shipment_type]=BOX,WAREHOUSE
The results are paginated and you can specify the amount of data per page and also which page to view using: page[1]=value and page[2]=value
You can specify the order of the results with certain parameters that you must send as list of strings in the sort filter type. For example: /shipping/v1/?sort=status,shipment_type
.
The default sorting will be ascending. To specify a descending sorting, you must send the character '-' as a prefix of the attribute. For example: /shipping/v1/?sort=status,-shipment_type
.
The possible sorting attributes are:
shipment_type
status
status_detail
If a parameter is incorrect or misspelled, it will return an error.
The /shipping/v1/{shipment_id}
endpoint allows you to get information about a particular shipment.
You will need to specify the shipment_id to perform the query.
Para los envíos hacia un warehouse y también para los que se realizan en México, no devolveremos un ID externo de seguimiento, ¡pero descuida! Te mantendremos informado sobre el estado del envío desde el Dashboard y también vía webhooks.
You must implement and expose the “Authorization” and “ Adjustments” endpoints on your backend so that we can communicate.
Every time a user uses their card in any online or physical store.
When the network (Mastercard, Visa, etc.) requests reconciliation of all payments presented by merchants.
If there is a discrepancy in the reconciliation, we will request a correction to your API. We expect a quick response to ensure a good experience. If the response is delayed, reject the transaction.
Since an HTTP request can time out, make sure that it is processed only once when retrying. We’ll send you an x-idempotency-key header with a unique ID with each request for that purpose. Process with a cache in memory (for example: redis).
At the beginning of each transaction, check if the idempotency key we sent you is already in the in-memory cache and do the following:
Cache in memory the idempotency key → request with a in-transit status with a TTL of 3 minutes.
When you approve or reject the transaction, you’ll need to cache the result and update the idempotency key status to ‘finished’.
In case of a duplicate request, you will need to check the transaction status in the cache.
finished
status, respond with an HTTP code 200 with the expected body for the endpoint and complete it with the cache result.in-transit
status you will need to respond with an HTTP code 425 (Too Early: RFC 8470) with the expected body for the endpoint. We’ll look for the response to this request again a few milliseconds later.The communication between our backends must be strictly secure since the endpoints will allow crediting and deducting funds.
For this purpose, we require you to implement three measures:
All communication with us must be via HTTPS, regardless of who issues the certificate.
These are some of the most recognized providers
We always communicate with your backend from specific IPs. We recommend that you only accept requests from the following IPs and reject any others:
Pomelo IPs:
34.226.254.178
44.198.3.59
34.206.159.176
52.0.20.124
To ensure that the only participants in the communication are our backends (Pomelo and the Client), we provide you with an api-key and api-secret during onboarding to digitally sign the content of the communication.
The process looks something like this:
api-key
and api-secret
keys.During a payment authorization, Pomelo signs each authorization request with hmac-sha256 using the api-secret
.
api-key
.api-secret
.During the onboarding process, we create an api-key and api-secret specific to you.
It is also possible to use gpg or an email plugin (such as https://flowcrypt.com/).
Let’s look at an example using openssl on the command line.
$ echo -e 'api-key=$(openssl rand -base64 32)\napi-secret=$(openssl rand -base64 32)' > api-credentials.txt
$ cat api-credentials.txt
api-key=tgeAkX0795jKTxrVR0cJbb//D8UlhHn0KZwTcDG3gyg=
api-secret=un/OHwD+fMN1TTSaEhs0vupQEDQS7DVaUdlNOu7Fpyw=
$ openssl genrsa -out private.pem 2048
$ openssl rsa -in private.pem -pubout -out public.pem
public key
by email or Slack.$ openssl rsautl -encrypt -in api-credentials.txt -out api-credentials.txt.enc -inkey public.pem -pubin
api-credentials.txt.enc
file by email or Slackapi-credentials.txt.enc
file with your private.pem private key
:$ openssl rsautl -decrypt -in api-credentials.txt.enc -inkey private.pem
api-key=tgeAkX0795jKTxrVR0cJbb//D8UlhHn0KZwTcDG3gyg=
api-secret=un/OHwD+fMN1TTSaEhs0vupQEDQS7DVaUdlNOu7Fpyw=
api-secret
in a safe place that is accessible only through the “Authorize payments” application, associated with the api-key
.Along with the authorization or adjustment request we’ll send you HTTP headers with the signature, timestamp and the api-key so that you can verify the signature is correct.
The HTTP headers we send are:
x-api-key
: this header allows you to identify which api-secret you have to use in the event that multiple api-key and api-secret pairs have been configured.
x-signature
: this header contains the digital signature (body + timestamp + endpoint) that you must verify to ensure request integrity. If the signature does not match, the order must be rejected.
x-timestamp
: this header contains the moment the order was signed in unix-epoch format so that you can verify that the signature has not expired.
x-endpoint
: the endpoint to which the request is made. Use this header to regenerate the signature to be validated, check with your service endpoint and confirm that they match.
Let’s look at a sample curl indicating how this information is sent within the request:
curl --location --request POST 'localhost:9090/shipping/updates' \
--header 'x-api-key: h3Ws4Cv09JcCdw7732ig+1Eq3I2b+IWOI1anUu1A4dE=' \
--header 'x-signature: hmac-sha256 kLV3Jeyn7qbKfGHLDQKKuy5xzG/kbPrYEg8RvD8jb8A=' \
--header 'x-timestamp: 1637117179' \
--header 'x-endpoint: {clientPath}/shipping/updates'
--header 'Content-Type: application/json' \
--data-raw '{
'shipment_id' : 'shi-20VphpUWbbGm0Nwo8DMqsFBJgYv',
'meta' : {
'resource_url' : 'http://localhost:8080/v1/shi-20VphpUWbbGm0Nwo8DMqsFBJgYv'
}
}'
To set up a signature you can use the following code snippet (in python 3) such as:
import hmac, hashlib, base64, time
############# Pomelo's side ################
############################################
# pomelo's secret key
pomelo_secret_key = base64.b64decode('kLV3Jeyn7qbKfGHLDQKKuy5xzG/kbPrYEg8RvD8jb8A=')
# the update data pomelo is gonna use to make the signature
pomelo_update_body = '{
'shipment_id' : 'shi-20VphpUWbbGm0Nwo8DMqsFBJgYv',
'meta' : {
'resource_url' : 'http://localhost:8080/v1/shi-20VphpUWbbGm0Nwo8DMqsFBJgYv'
}
}'
client_req_endpoint = '/shipping/updates'
pomelo_timestamp = str(int(time.time()))
# the request data signed out by pomelo
pomelo_signature = hmac.new(pomelo_secret_key, bytes(pomelo_timestamp + client_req_endpoint + pomelo_update_body, 'utf-8'), hashlib.sha256).digest()
############# Client's side ################
############################################
# client's secret key
client_secret_key = base64.b64decode('kLV3Jeyn7qbKfGHLDQKKuy5xzG/kbPrYEg8RvD8jb8A=')
# client's api endpoint
client_api_endpoint = '/transactions/authorizations'
# signature expiration offset
signature_expiration_offset = 60 #A minute of expiration
# the authorizacion data the client needs to use to recreate the signature
client_request_data = bytes(pomelo_timestamp + client_req_endpoint + pomelo_update_body, 'utf-8')
# the signature the client has recreated
signature = hmac.new(client_secret_key, client_request_data, hashlib.sha256).digest()
# if signature is not expired and they match you can trust the request, otherwise reject it
now = int(time.time()) - signature_expiration_offset
signatureExpired = int(pomelo_timestamp) < now
signaturesMatch = hmac.compare_digest(signature, pomelo_signature)
endpointsMatch = client_api_endpoint in client_req_endpoint
requestIsValid = not signatureExpired and signaturesMatch
################ Results ###################
############################################
print('pomelo' signature = {0}'.format(base64.b64encode(pomelo_signature)))
print('client's signature = {0}'.format(base64.b64encode(signature)))
print('signature expired = {0}'.format(signatureExpired))
print('signatures match = {0}'.format(signaturesMatch))
print('endpoints match = {0}'.format(endpointsMatch))
print('request is valid = {0}'.format(requestIsValid))
Important: you will need to sign your body along with the timestamp and response endpoint with your api-secret
after impacting the operation. Please note that the signature will be validated and the transaction rejected if the signature does not match or has expired.
This is an optional process, but we recommend running it daily.
You will find these files in an S3 bucket that will be made available to you:
Contains the details of each transaction from the previous day.
The file name has this format: presentationsyyyy_mm_dd
{Atributo} | Description | Allowed values |
---|---|---|
TRANSACTION_ID | Unique ID to identify the transaction. | |
LOCAL_TRANSACTION_DATE_TIME | ||
TRANSACTION_TYPE | Indicates the transaction type. | PURCHASE WITHDRAWAL EXTRACASH REFUND PAYMENT REVERSAL_PURCHASE REVERSAL_WITHDRAWAL REVERSAL_EXTRACASH REVERSAL_REFUND REVERSAL_PAYMENT |
PRODUCT_TYPE | This is the product type | PREPAID CREDIT DEBIT |
PROVIDER | It is the brand of the issued card. | VISA MASTERCARD |
AFFINITY_GROUP_ID | ||
USER_ID | Pomelo cardholder’s user ID. | |
CARD_ID | ||
BIN | The first six or eight digits of the PAN. | |
LAST_FOUR | The last four digits of the PAN. | |
ORIGIN | DOMESTIC: The transaction occurred in the issuer’s country. INTERNATIONAL: The transaction was not made in the issuer’s country. | |
MERCHANT_ID | ||
MERCHANT_MCC | The merchant category code as defined in ISO-18245. | |
MERCHANT_NAME | ||
LOCAL_AMOUNT | This is the total transaction amount that must be deducted from the user's balance, with taxes and fees added (where applicable). Always converted to the card's local currency. | |
LOCAL_CURRENCY | The LOCAL_TOTAL currency code in ISO_4217 ALPHA-3 format. | |
TRANSACTION_AMOUNT | The transaction value before taxes and in the original currency sent by the merchant. | |
TRANSACTION_CURRENCY | The TRANSACTION_TOTAL currency code in [ISO_4217] (https://en.wikipedia.org/wiki/ISO_4217#Active_codes) formato ALPHA-3. | |
SETTLEMENT_AMOUNT | The transaction amount in USD, as sent by the network. Domestic transactions also have this field in USD. | |
SETTLEMENT_CURRENCY | The SETTLEMENT_TOTAL currency code in ISO_4217 ALPHA-3 format is always USD. | |
ENTRY_MODE | How the card was used at the merchant's point of sale. | UNKNOWN MANUAL CHIP CONTACTLESS CREDENTIAL_ON_FILE MAG_STRIPE OTHERS |
STATUS | Transaction status. | APPROVED REJECTED HELD |
STATUS_DETAIL | Additional reason why the transaction is approved or rejected. | See table below |
SOURCE | Indicates which flow/process triggered the transaction, as seen from Pomelo. | ONLINE: Originated during transactional flow from real-time transactions sent over the network CLEARING: Originated during the agreement process between Pomelo and the network when managing the settlement file PURGE: Transactions that were not presented in the network settlement file. |
ORIGINAL_TRANSACTION_ID | This value may be empty if the transaction is not related to another. | |
COUNTRY_CODE | This is the country code in [ISO-3166] format (https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes). | |
POINT_TYPE | POS ECOMMERCE ATM MOTO | |
CLIENT_NAME | El nombre del cliente que aprueba o rechaza la transacción, dado que el reporte se segmenta por cliente, va a tener el mismo valor para todas las filas | |
CLIENT_COUNTRY_CODE | El coódigo de país del cliente en formato ISO-3166 | |
INSTALLMENTS_GRACE_PERIOD | [OPCIONAL*] El período de gracia refiere a la cantidad de meses previo a que comiencen los pagos en cuotas. Puede ir de 0 a 99. | |
INSTALLMENTS_QUANTITY | [OPCIONAL*] La cantidad de cuotas | |
INSTALLMENTS_CREDIT_TYPE | [OPCIONAL*] El tipo de crédito otorgado | NO_PROMOTION WITHOUT_INTEREST WITH_INTEREST BUY_TODAY_PAY_LATER |
*_Para los clientes que operen con crédito, se agregan los datos del contrato de cuotas.
Status detail | Description |
---|---|
CARD_BLOCKED | The card status is BLOCKED. |
CARD_DISABLED | The card status is DISABLED |
CARD_NOT_ACTIVE | The card status is EMBOSSED or CREATED |
CARD_NOT_CONFIGURED | The card is missing configurations. |
CARD_NOT_FOUND | We cannot find the card’s PAN. |
CRYPTO_ERROR | There is a cryptogram error (EMV). |
DUPLICATE_TRANSMISSION_DETECTED | We received a repeated transaction from the network. |
EXPIRED_CARD | The card status is EXPIRED. |
EXTRA_FIELDS | Messaging from the network comes with unexpected fields. |
INSUFFICIENT_FUNDS | The client replies that the account has no funds. |
INVALID_AMOUNT | The affinity group’s limits are exceeded. |
INVALID_CVV | The CVV does not match. |
INVALID_EXPIRATION_DATE | The expiration date received does not match the card. |
INVALID_MERCHANT | The customer rejects the merchant for a specific reason. |
INVALID_PIN | The PIN is incorrect |
INVALID_TRANSACTION | The transaction is invalid. |
LOST_CARD | The card status is LOST. |
MISSING_FIELDS | Messaging from the network comes without the required fields. |
NOT_DECLINED | A transaction has a value of 0, verifying the account is active. |
ORIGINAL_NOT_FOUND | An attempt is made to reverse a transaction that we did not find. |
OTHER | The case is not recognized. |
RESTRICTED_USER | The user's status is not ACTIVE. |
SECURITY_VIOLATION | Exceeds a fraud threshold. |
SERVICE_UNAVAILABLE | The client or a Pomelo service is down. |
STOLEN_CARD | The card’s status is STOLEN. |
SYSTEM_ERROR | Unforeseen system error. |
APPROVED | The client approves a transaction. |
TRANSACTION_NOT_PERMITTED | The transaction type is not allowed in the affinity group. |
Is it at Pomelo? | Is it at the client? | Does it have the same status? | Action |
---|---|---|---|
Y | Y | Y | Do nothing / Mark as matching |
Y | Y | N | 1) Register an adjustment that debits/credits the end user if applicable. 2) Mark as matching. |
Y | N | N | 1) IF STATUS == APPROVED: Register an adjustment that debits/credits the end user if applicable. 2) Mark as matching. |
N | Y | N | It is not a possible use case. |
If you are trying to adjust a credit to an end user who does not have sufficient funds in their account, keep trying to get the funds from that user.
It becomes a debt between the customer and the end user.
Contains the details for each transaction that traders submitted the previous day.
The file name has this format: presentationsyyyy_mm_dd
Attribute | Description | Allowed values |
---|---|---|
PRESENTMENT_ID | ||
TRANSACTION_ID | The original transaction ID the presentation generated. | |
LOCAL_TRANSACTION_DATE_TIME | ||
TRANSACTION_TYPE | Indicates the transaction type. | PURCHASE WITHDRAWAL EXTRACASH REFUND PAYMENT |
PRODUCT_TYPE | This is the product type. | PREPAID CREDIT DEBIT |
PROVIDER | It is the brand of the issued card. | VISA MASTERCARD |
AFFINITY_GROUP_ID | ||
USER_ID | Pomelo cardholder’s user ID | |
CARD_ID | ||
BIN | The first six or eight digits of the PAN. | |
LAST_FOUR | The last four digits of the PAN. | |
ORIGIN | DOMESTIC: The transaction occurred in the issuer’s country. INTERNATIONAL: The transaction was not made in the issuer’s country. | |
MERCHANT_ID | ||
MERCHANT_MCC | The merchant category code as defined in ISO-18245. | |
MERCHANT_NAME | ||
TRANSACTION_AMOUNT | The transaction value before taxes and in the original currency sent by the merchant. | |
TRANSACTION_CURRENCY | The TRANSACTION_TOTAL currency code in [ISO_4217] (https://en.wikipedia.org/wiki/ISO_4217#Active_codes) formato ALPHA-3. | |
SETTLEMENT_AMOUNT | The transaction value presented by the brand. | |
SETTLEMENT_CURRENCY | The SETTLEMENT_AMOUNT currency code in ISO_4217 ALPHA-3 format. If it is a domestic transaction it will be presented in local currency, otherwise in USD. | |
DEBT_AMOUNT | The transaction value in the currency to be paid to Pomelo. If the sum is to be paid to Pomelo, it is always a positive value; otherwise, it will be negative. | |
DEBT_CURRENCY | The DEBT_AMOUNT currency code in ISO_4217 ALPHA-3 format. If it is a domestic transaction it must be paid in local currency, otherwise in USD. | |
RECONCILIATION_DATE | ||
INTERCHANGE_FEE | Transaction commission to be applied to the exchange. | |
INTERCHANGE_RATE | Alphanumeric value that identifies the transaction exchange rate presented by the purchaser. | |
TAX | This is the exchange rate tax in accordance with local regulations. These values must have VAT calculated. | |
FUNCTION_CODE | This is the presentation type. | FIRST_PRESENTMENT SECOND_PRESENTMENT_FULL SECOND_PRESENTMENT_PARTIAL |
REVERSE_PRESENTMENT | This means that the presentation was reverted from the network. | TRUE FALSE |
REASON_CODE | Reason for the second presentation. | |
ICA_ACQUIRER | ||
TAX_ID | ID asociado a los impuestos de la transacción | |
INSTALLMENTS_GRACE_PERIOD | [OPCIONAL*] El período de gracia refiere a la cantidad de meses previo a que comiencen los pagos en cuotas. Puede ir de 0 a 99. | |
INSTALLMENTS_QUANTITY | [OPCIONAL*] La cantidad de cuotas | |
INSTALLMENTS_CREDIT_TYPE | [OPCIONAL*] El tipo de crédito otorgado | NO_PROMOTION WITHOUT_INTEREST WITH_INTEREST BUY_TODAY_PAY_LATER |
*_Para los clientes que operen con crédito, se agregan los datos del contrato de cuotas.
Our finance team will send daily notifications for the debt owed. This will include all presentations we receive in the presentation file.
There is an SFTP server from which you can download Transaction and Presentation files.
Pomelo has two environments for SFTP servers, production and development.
To connect to the SFTP servers, first send a public key to create a user.
Here is the data to connect to each environment:
Host: sftp.pomelo.la
Port: 22
User: <tu_usuario> # the one created from your public keys.
Host: sftp-dev.pomelo.la
{Puerto}: 22
User: <tu_usuario> # the one created from your public keys.
To create a public key, use the command applicable to your operating system:
$Cliente
to the proper namessh-keygen -t rsa -b 2048 -C $Cliente
The command will create a 2048-bit RSA key pair by default. You can also create a larger 4096-bit key by entering -b 4096.
The command produces this output:
Generating public/prive rsa key pair.
Enter a file to save the key (/your_home/.ssh/id_rsa):
Press Enter
to save the key pair in .ssh /, or specify another location.
Press Enter
to leave it blank and use the key only to establish SSH connections. Enter a password for an additional layer of security.
cat ~/.ssh/id_rsa.pub
The key generated will start with ssh-rsa.
You can now copy and paste your public SSH key into your Shell console, or any server, to establish a secure connection.
Create SSH keys using PuTTY. Install PuTTY from the developer page: https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html
Install PuTTY from the developer page: https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html
PuTTYgen
.Run as administrator
.Yes
if the system asks you Do you want to allow this app to make changes to your device?
While the PuTTY keygen tool offers several other algorithms, here is how to create RSA keys, one of the most often used:
Build
.Save Public Key
button. Then choose a location to save the key and assign a name to it.Conversions
menu at the top.Yes
.The /transactions/authorizations endpoint allows you to authorize transactions.
A request to authorize or reject the transaction will be sent.
We expect a quick response to ensure a good experience. If the response is delayed, reject the transaction.
The /transactions/adjustments/{type}
endpoint allows you to make credit and debit adjustments to transactions.
A request informing you that the network (MC, VISA) forced an authorization will be sent.
This endpoint is used during reconciliation and online flows, mainly to make adjustments during the settlement process and also in the event of returns.
The Core service lets you create and manage your users' digital accounts.
To have an account your users must:
The accounts status is one of the following:
ACTIVE
: The account is active and can be used to make transactions normally. When an account is created its initial status will be ACTIVE.FROZEN
: The account can receive money but debit transactions are blocked.DISABLED
: No transactions are permitted for the account.DELETED
: The account is deleted and may not be reactivated.To change an account status from ACTIVE to FREEZED, and DISABLED, use the PATCH endpoint.
To change an account status to DELETED, use the DELETE endpoint.
If an operation fails, an error is returned with a list of possible associated operations:
ACCOUNT_VALIDATION_ERROR
: The account could not be successfully validated. For example, when the idempotency key used in the request is already in use by another user.
CREATE
USER_VALIDATION_ERROR
: The user’s identity could not be validated or does not exist.
CREATE
CLIENT_VALIDATION_ERROR
: The customer belonging to the user you're trying to create an account for could not be identified.
CREATE
USER_ACCOUNT_LIMIT_REACHED
: The user reached the limit of accounts that he can have, so a new one cannot be created.
CREATE
ACCOUNT_NOT_FOUND
: The account ID does not exist.
UPDATE
DELETE
ACCOUNT_DELETED
: The account ID was deleted.
UPDATE
DELETE
INVALID_ACCOUNT_STATUS
: The account update status is invalid.
UPDATE
DELETE
LOCKED_ACCOUNT_STATUS
: It is not possible to update an account modified from Pomelo.
UPDATE
DELETE
INVALID_UPDATE_STATUS_MOTIVE
: The reason for updating the account status you entered is invalid. For DELETE
the valid reasons are OTHER
, INTERNAL_REASON
, USER_REQUEST
and FRAUD
. For DISABLED
are OTHER
, LOST
, INTERNAL_REASON
, STOLEN
, FRAUD
and INHIBITION
. For FROZEN
are OTHER
and SEIZURE
UPDATE
DELETE
ACCOUNT_HAS_FUNDS
: It is not possible to delete an account that is not completely empty.
DELETE
Idempotent account creation identifier. This number is needed for each account you want to create. If two identical requests have the same idempotency id, only one account will be created, even if both receive a successful response.
status_update_motive
is OTHER
.The /core/accounts/v1/{id}
endpoint helps you change an account status.
Account status may be changed to ACTIVE
, FROZEN
, or DISABLED
.
For the last two, the reason for the change must be given, using the status_update_motive property.
ACTIVE
.status_update_motive
is OTHER
.Accounts Query API is a service that groups all Pomelo digital account information and makes it available for consultation.
You can consult:
An activity is any operation that was intended to modify the account balance. In other words:
Languages sorted according to your preference. Technical specification
Languages sorted according to your preference. Technical specification
This service allows you to authorize transactions.
There are two possibilities for the state of transactions created:
APPROVED
: If the transaction is approved.REJETED
: If the transaction is rejected.All transactions that are approved modify the account balance by the amount specified.
Todos los montos de las transacciones están expresados en la moneda de la cuenta y con signo positivo.
Para distinguir si la intención de la transacción es ingresar o retirar dinero de una cuenta utiliza el parámetro entry_type
. Este parámetro puede tomar estos valores:
DEBIT
: for transactions withdrawing money from the account.CREDIT
: for transactions depositing money into the account.All transactions have a type, indicated with the type parameter. Each type has different data sent along with the transaction in the tx_properties object.
You can request extra data from all transactions using the metadata object.
The details
property may be used to break down the total transaction sum into its constituent parts. For example, suppose you are processing a transaction in a digital store totaling $149.99. Let us further suppose that this total is composed of:
This breakdown may be reported by adding multiple items to the details list. Each detail must have a type associated with it:
BASE
: transaction base expense.FEE
: commission expenses.TAX
: Taxes.EXTRACASH
: money withdrawals.DISCOUNT
: Discounts.More than one detail may be added with the same type. The only restriction is that the details total is equal to the transaction total.
Each transaction has a process_type field that can take any of these values:
ORIGINAL
: New transaction.ADJUSTMENT
: Settings.REFUND
: refund or return.REVERSAL
: Reversal.For REFUND
or REVERSAL
transactions that are or can specify the original transaction they are based on. This transaction is known as a “parent transaction“, indicated by the parent_tx_id
field.
Transaction authorization requests have an idempotency mechanism to prevent duplicate processing.
For the transaction to be processed you must accompany each authorization request with an X-Idempotency-Key
header that has a unique identifier. If you do not get a response or receive one with status code type 5xx, repeat the request with the same idempotency key until you get a successful response (code 201).
Repeated requests using the same idempotency key will only result in a transaction being created. The first request creates the transaction and the next one gives the same response but does not create a new transaction.
If an authorization request has an idempotency key already used in another transaction, an error is returned.
Correctly processed transactions are reported with a status code 201. This status does not indicate whether the transaction was approved or not. Read the answer 'result' field and note if it is APPROVED
or REJECTED
.
Any other status code indicates that something went wrong and the reason for rejection is given in the rejection_reason field. This field may be filled out as follows:
INSUFFICIENT_FUNDS
: The account does not have sufficient funds.ACCOUNT_DISABLED
: the account has been disabled.ACCOUNT_FROZEN
: The account cannot process debit transactions.CLIENT_MONTHLY_AMOUNT_LIMIT_REACHED
: exceeded the monthly movement limit it had.CLIENT_DAILY_AMOUNT_LIMIT_REACHED
: exceeded the limit of daily movements it had.PROCESS_TIME_EXPIRED
: The transaction did not start processing before the time indicated in the process_before field, which is optional.When a transaction cannot be processed an error response is returned with the error_code field indicating the reason:
ACCOUNT_NOT_FOUND
: account could not be found.INVALID_AUTHORIZATION_REQUEST
: The transaction authorization request is not valid.INVALID_PARENT_TX_ID
: The parent transaction specified is invalid.DUPLICATED_IDEMPOTENCY_KEY
: You already used the idempotency key in another transaction.CREDIT
must be used to deposit money, and CREDIT
to debit money.This service notifies you of all account activities.
A notification may be an activity creation or modification. To determine which case it is, read the 'type' field, which will have one of the following:
ACTIVITY_CREATED
: We notify you when a new activity is created.ACTIVITY_UPDATED
: We notify you when an activity is modified. Activities may have their status changed from 'PENDING' to 'APPROVED' or from 'PENDING' to 'REJECTED'.Along with the notification, we will send a set of HTTP headers to verify its authenticity.
The HTTP headers we send are:
x-api-key
: this header allows you to identify which api-secret you have to use in the event that multiple api-key and api-secret pairs have been configured.
x-signature
: this header contains the digital signature that you must verify to ensure request integrity. If the signature does not match, the order must be rejected.
x-timestamp
: this header contains the moment the order was signed in unix-epoch format so that you can verify that the signature has not expired.
x-endpoint
: the endpoint to which the request is made. Use this header to regenerate the signature to be validated, check with your service endpoint and confirm that they match.
The digital signature is an HMAC-SHA256 code constructed using the 'api-secret' and a series of bytes, composed of a concatenation of the timestamp, endpoint and request body coded in UTF-8.
The following is a pseudo-code to verify that the digital signature of a request is legitimate:
requestSignature = request.headers['x-signature'] signatureData = encode(request.headers['x-timestamp'] + request.headers['x-endpoint'] + request.body , 'UTF-8') recreatedSignature = hmac(apiSecret, signatureData, 'SHA256') validSignature = requestSignature == recreatedSignature
api-secret
you have to use in the event that multiple api-key
and api-secret
pairs have been configured.timestamp + endpoint + body
) that you must verify to ensure request integrity. If the signature does not match, the order must be rejected.This service allows you to integrate with different cash networks to query account information and be able to add money (cash in) or log cash withdrawal attempts (cash out intent).
To cash in, each account will have an alias that will allow you to identify it in a payment network. That alias is generated automatically and associated with the account when it is created.
For withdrawals, you will need to log a cash out intent, which, combined with the alias, you can use to withdraw cash from an account on the enabled payment networks.
Country | Network | ID |
---|---|---|
Argentina | Pago Fácil | PAGO_FACIL |
The /networks/cash/v1/cashin/intents POST endpoint will allow you to generate a cash in attempt for a given account. Each attempt represents the intention to deposit money into an account’s balance through a payment network.
There can only be one active attempt per account and network. The attempt is resolved when the withdrawal is actually made through a cash network or when the expiration date elapses. Creating a new attempt overwrites the previous attempt.
The GET /networks/cash/v1/cashout/intents/{account_id} endpoint allows you to get the latest current cash out intent. To consider a current cash out, the following conditions must be met:
The GET /networks/cash/v1/alias/{account_id} endpoint will allow you to get the alias of an account. It is a unique value associated with the account, which will help you to perform a cash in operation in the payment network.
This service allows you to integrate with different cash networks to query an account’s data and record cash in intents for an account in a cash network.
To deposit funds, you must register a cash in intent in one of the enabled payment networks.
Country | Network | ID |
---|---|---|
Brazil | Boleto | BOLETO |
The /networks/cash/v1/cashout/intents POST endpoint will allow you to generate a cash out intent for a given account.. Each attempt represents the intention to withdraw money from an account balance through a payment network.
Lifecycle
The attempt is resolved when the money deposit is actually performed through a cash network or when the expiration date is reached, whichever occurs first.
The attempt can have different statuses depending on which action has been applied to it::
The Bank Account API service within the transfer flow is responsible for managing the bank attributes of the account and obtaining the information of a destination account when initiating a transfer.
Part of the attribute management of an account is the change of Alias. Each account is created with a CVU and an alias set by default, which may be modified by the user according to their preference.
As for obtaining information from a destination account, each transfer that is made begins with the validation of the destination account by using the CVU or alias. This service is responsible for performing this management and returning the destination account already validated with additional information of the holder (CBU, bank code, name and CUIT).
The Bank Account API service within the transfer flow is responsible for managing the bank attributes of the account.
Within the management of the attributes of an account is the ABM of the PIX key.
Considerations:
The transfer will be made by posting in the Transfer API, once the information of the destination account is validated by the Bank Account API service.
The transfer response can be synchronous or asynchronous. In the case of a synchronous response, the Transfer API service will return the final status of the transaction (SUCCESS or FAILED). If the response is asynchronous because it takes a few more seconds, the Transfer API service will return a pending status synchronously (IN_PROGRESS) and the notification of the final status of the transaction will be reported as Activity through the Core Webhooks service.
The transfer is performed in 2 simple steps:
The transfer response can be synchronous or asynchronous. In the case of a synchronous response, the Transfer API service will return the final status of the transaction (SUCCESS or FAILED). If the response is asynchronous (because it takes a few more seconds), the Transfer API service will return a pending status synchronously (IN_PROGRESS) and the notification of the final status of the transaction will be seen as Activity through the Core Webhooks service.
The identity/v1/sessions
endpoint lets you create a new identity validation session and returns a unique identifier for it.
The /sessions
endpoint allow you to perform a search with specific filters.
Filters must be specified as parameters following this pattern: filter[field]=value
. For example: filter[status]=IN_PROGRESS
The results will be paginated and you can specify the amount of data per page and also which page you wish to view.
There is a filter for the created_at field, which can be used to get sessions created within a date range. For example: filter[created_at][from]=2021-07-27&filter[created_at][to]=2021-07-28
You can specify the order of the results with certain parameters that you must send as list of strings in the sort filter type. For example: ?sort=status,user_id
The default sorting will be ascending. To specify a descending sorting, you must send the character '-' as a prefix of the attribute. For example: ?sort=status,-user_id.
The possible ordering attributes are: user_id, status and created_at.
If a parameter is incorrect or misspelled, it will return an error.
identity/v1/session/{id}
endpoint lets you get data from an identity validation session.identity/v1/sessions/{id}
endpoint lets you cancel an identity validation session.identity/v1/sessions/{id}/report
endpoint lets you obtain a user's data collected in an identity validation session.This service notifies you when an identity validation session is completed.
We send a set of HTTP headers to authenticate it along with the notification.
The HTTP headers we send are:
x-api-key
: this header allows you to identify which api-secret you have to use in the event that multiple api-key and api-secret pairs have been configured.
x-signature
: this header contains the digital signature (body + timestamp + endpoint) that you must verify to ensure request integrity. If the signature does not match, the order must be rejected.
x-timestamp
: this header contains the moment the order was signed in unix-epoch format so that you can verify that the signature has not expired.
x-endpoint
: the endpoint to which the request is made and used to generate the signature. Use this header to regenerate the signature to be validated, compare it with the endpoint of your service and verify that they match.
The digital signature is an HMAC-SHA256 code constructed using the 'api-secret' and a series of bytes, composed of a timestamp concatenation, endpoint and request body coded in UTF-8.
The following is a pseudo-code to verify that the digital signature of a request is legitimate:
requestSignature = request.headers['x-signature']
signatureData = encode(request.headers['x-timestamp'] + request.headers['x-endpoint'] + request.body , 'UTF-8')
recreatedSignature = hmac(apiSecret, signatureData, 'SHA256')
validSignature = requestSignature == recreatedSignature
You must inform us of this endpoint to receive identity validation session completion notifications. You must return a type 2xx HTTP code so that the notification is not sent again. Otherwise, we will send it again.
api-secret
to use if multiple api-key
and api-secret
pairs were configured.