Implementamos el estándar OAuth 2.0 para que puedas comunicarte con nuestras APIs con un único token del tipo Bearer.
Una vez que recibas el token de acceso deberás incluirlo como un header de autorización cada vez que te comuniques con nuestras APIs.
Ejemplo en curl:
curl https://api.pomelo.la -H 'Authorization: Bearer eyJhbGciOiJSUzI1Ni'
Cada API validará el token de acceso y verificará que el scope coincida con los permisos requeridos.
Para que los request sean válidos, deberás comunicarte con nuestras APIs únicamente por HTTPS e incluir el header de autorización indicando que es del tipo Bearer.
El endpoint /oauth/token
se usa para obtener un token de acceso. Al realizar una autenticación exitosa, guárdalo ya que lo necesitarás para comunicarte con nuestras APIs.
Cada token es un JWT que contiene un tiempo de expiración. Deberás solicitar un nuevo token únicamente cuando el que tengas haya expirado.
La API de Usuarios contiene todos los endpoints necesarios para administrar las bases de usuarios. Podrás usarla para crear, actualizar o incluso buscar usuarios bajo determinados parámetros.
El endpoint /users/v1/
te permite crear un nuevo usuario en nuestra base de datos.
La cantidad de parámetros requeridos para crear un usuario varía dependiendo del producto que hayas contratado, pero siempre te pediremos email y operation_country.
Para los campos operation_country
y nationality
esperamos un código de 3 caracteres respetando el estándar ISO 3166 alpha-3.
Dejamos una lista de ejemplos:
Cada usuario debe tener un email único, También debe ser única la combinación de tipo de documento de identidad y valor.
Los tipos de documento de identidad aceptados son los siguientes:
En el caso del DNI, validaremos que su extensión sea de 7 u 8 caracteres.
El tipo de documento fiscal aceptado es el CUIL.
Los tipos de documento de identidad aceptados son los siguientes:
El tipo de documento fiscal aceptado es el CPF. Validaremos que su extensión sea de 11 caracteres.
Los tipos de documento de identidad aceptados son los siguientes:
El tipo de documento fiscal aceptado es el RFC, pero no será obligatorio incluirlo.
Si operas en Argentina, el domicilio legal del usuario tendrá que ser de alguna de estas provincias:
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.
En caso que el país de operatoria sea México, no existe ningún requisito especial respecto a los campos de dirección legal del usuario.
El endpoint /users/v1/
te permite buscar un grupo de usuarios y recibir una lista ordenada en base a los parámetros especificados.
Tendrás que especificar tus filtros como parámetros siguiendo este patrón: filter[campo]=valor
. Por ejemplo: /users/v1/?filter[status]=ACTIVE
Para filtrar un atributo con varios valores posibles, deberás separar los valores con comas.
Veamos un ejemplo: filter[status]=ACTIVE,BLOCKED
Los resultados serán paginados y podrás especificar la cantidad de datos por página y también qué página ver utilizando: page[number]=valor
y page[size]=valor
Podrás especificar el orden de los resultados con determinados parámetros que deberás enviar como una lista de strings en el filtro de tipo sort. Por ejemplo: ?filter[status]=ACTIVE&sort=status,gender
El ordenamiento por defecto será ascendente. Para especificar un orden descendente, deberás enviar el carácter '-' como prefijo del atributo. Por ejemplo: /users/v1/?filter[status]=ACTIVE&sort=status,-gender
Los posibles atributos para ordenar son:
id
gender
identification_type
identification_value
status
Si un parámetro es incorrecto o está mal escrito, responderemos con un error.
El endpoint de /users/v1/{id}
te permite consultar la información de un usuario a través de su id.
El endpoint /users/v1/{id}
permite actualizar la información de un usuario a través de su id.
Para bloquear un usuario deberás enviar el status
con el valor BLOCKED
y el valor CLIENT_INTERNAL_REASON
en el campo status_reason
.
Para reactivar un usuario que bloqueaste, deberás enviar status
con valor ACTIVE
.
Cada usuario debe tener un email único. También debe ser única la combinación de tipo de documento de identidad y valor.
Los tipos de documento de identidad aceptados son los siguientes:
En el caso del DNI, validaremos que su extensión sea de 7 u 8 caracteres.
El tipo de documento fiscal aceptado es el CUIL.
Los tipos de documento de identidad aceptados son los siguientes:
El tipo de documento fiscal aceptado es el CPF. Validaremos que su extensión sea de 11 caracteres.
Los tipos de documento de identidad aceptados son los siguientes:
El tipo de documento fiscal aceptado es el RFC, pero no será obligatorio incluirlo.
Si operas en Argentina, el domicilio legal del usuario tendrá que ser de alguna de estas provincias:
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.
En caso que el país de operatoria sea México, no existe ningún requisito especial respecto a los campos de dirección legal del usuario.
La API de Cards contiene todos los endpoints necesarios para crear tarjetas nominadas e innominadas, activarlas, hacer búsquedas, obtener la información de una tarjeta en particular y más.
El endpoint /cards/v1/{id}
te permite obtener información sobre una tarjeta en particular.
El parámetro extend
se usa para obtener datos adicionales de una tarjeta.
El endpoint /cards/v1/{id}
te permite actualizar el estado de una tarjeta, su grupo de afinidad y el PIN.
Deberás especificar una razón del siguiente listado para poder actualizar el estado de una tarjeta:
Nuevo estado | Razón válida |
---|---|
BLOCKED / DISABLED | CLIENT_INTERNAL_REASON |
BLOCKED / DISABLED | USER_INTERNAL_REASON |
DISABLED | FRAUDULENT |
DISABLED | LOST |
DISABLED | STOLEN |
DISABLED | BROKEN |
DISABLED | UPGRADE |
El endpoint /cards/v1/{id}/shipment
te permite actualizar el domicilio de envío de una tarjeta.
La tarjeta deberá ser física nominada y tener estado CREATED
.
El endpoint /cards/v1/
te permite buscar un grupo de tarjetas según los atributos que especifiques.
Tendrás que especificar tus filtros como parámetros siguiendo este patrón: filter[campo]=valor
. Por ejemplo: filter[status]=CREATED
.
Para filtrar un atributo con varios valores posibles, deberás separar los valores con comas.
Veamos un ejemplo: filter[status]=CREATED,ACTIVE
Los resultados serán paginados y podrás especificar la cantidad de datos por página y también qué página ver utilizando: page[number]=valor
y page[size]=valor
Podrás especificar el orden de los resultados con determinados parámetros que deberás enviar como una lista de strings en el filtro de tipo sort. Por ejemplo: /cards/v1/?sort=status,card_type
.
El ordenamiento por defecto será ascendente. Para especificar un orden descendente, deberás enviar el carácter '-' como prefijo del atributo. Por ejemplo: /cards/v1/?sort=status,-card_type
.
Los atributos para ordenar son:
card_type
user_id
status
affinity_group_id
status_detail
shipment_id
innominate
.Si un parámetro es incorrecto o está mal escrito, responderemos con un error.
El endpoint /cards/v1/
permite crear una nueva tarjeta nominada que puede ser física o virtual.
Para crear una nueva tarjeta física, deberás especificar el domicilio de envío.
Podrás usar el parámetro previous_card_id
, para especificar que una tarjeta es reemplazo de una anterior.
Para asegurar que una solicitud no se ejecute más de una vez te pediremos que envíes el header: x-idempotency-key con un ID único para usar nuestro esquema de idempotencia. Si dos solicitudes tienen el header con el mismo ID, solo crearemos una tarjeta y las dos solicitudes tendrán la misma respuesta positiva
Si operas en Brasil, deberás completar el campo region
con el código UF de dos caracteres.
Ejemplo: SP
para São Paulo
La información que necesitamos de los usuarios para emitir una tarjeta varía según el país:
Los siguientes campos son obligatorios:
name
surname
birthdate
email
identification_type
identification_value
gender
street_name
zip_code
city
region
country
Los siguientes campos son obligatorios:
tax_identification_type
tax_identification_value
Los siguientes campos son obligatorios:
tax_identification_type
tax_identification_value
El endpoint /cards/v1/batches
te permite crear un lote de tarjetas innominadas.
Un lote puede tener un máximo de 1000 tarjetas.
La dirección de envío es obligatoria si el tipo de distribución es CLIENT
.
Procesaremos la llamada de forma asincrónica, es decir que es posible que las tarjetas no estén disponibles inmediatamente.
Si operas en Brasil, deberás completar el campo region
con el código UF de dos caracteres.
Ejemplo: SP
para São Paulo
El endpoint /cards/v1/batches/shipments/{shipmentId}
te permite actualizar el domicilio de envío de un lote de tarjetas.
El lote de tarjetas deberá ser física innominada y tener estado CREATED
.
El endpoint /cards/v1/activation
te permite activar una tarjeta física y también configurar un PIN.
El usuario deberá estar activo y la tarjeta deberá tener estado EMBOSSED
.
El PIN a configurar:
Podrás usar el parámetro previous_card_id
, para especificar que una tarjeta es reemplazo de una anterior.
La información que necesitamos de los usuarios para activar una tarjeta varía según el país:
Los siguientes campos son obligatorios:
name
surname
birthdate
email
identification_type
identification_value
gender
street_name
zip_code
city
region
country
Los siguientes campos son obligatorios:
tax_identification_type
tax_identification_value
Los siguientes campos son obligatorios:
tax_identification_type
tax_identification_value
La API de Envíos contiene todos los endpoints y webhooks necesarios para crear un envío, obtener información sobre un envío y mantenerse actualizado sobre los eventos que afectan a un envío.
Necesitarás un endpoint público para que podamos comunicarte las novedades de los envíos en tiempo real.
Tu endpoint deberá terminar en /shipping/updates
Ahí te notificaremos si hay actualizaciones sobre un envío. Serás responsable de buscar el recurso para obtener el estado actualizado.
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'
}
}'
Como medida de seguridad, todas las notificaciones de novedades incluirán una firma hmac-sha256, pero no es necesario que la respuesta sea firmada por los clientes.
Para asegurarnos de que los únicos participantes en la comunicación sean nuestros backends (Pomelo y el Cliente), en el momento del onboarding le proporcionaremos una api-key y api-secret para firmar digitalmente el contenido de la comunicación.
A continuación explicamos con más profundidad los procesos de Intercambio de llaves y firma del pedido.
Durante el proceso de onboarding, crearemos una api-key
y api-secret
específicas para ti.
También es posible usar gpg o algún plugin de correo electrónico (como por ejemplo https://flowcrypt.com/).
Veamos un ejemplo usando openssl en la línea de comandos.
$ 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
Nos envías tu clave pública public.pem
por email o Slack.
Encriptamos el archivo de credenciales con la clave pública que nos diste:
$ openssl rsautl -encrypt -in api-credentials.txt -out api-credentials.txt.enc -inkey public.pem -pubin
Enviamos el archivo api-credentials.txt.enc
por email o Slack
Desencriptas el archivo api-credentials.txt.enc
con tu clave privada private.pem
:
$ openssl rsautl -decrypt -in api-credentials.txt.enc -inkey private.pem
api-key=tgeAkX0795jKTxrVR0cJbb//D8UlhHn0KZwTcDG3gyg=
api-secret=un/OHwD+fMN1TTSaEhs0vupQEDQS7DVaUdlNOu7Fpyw=
api-secret
en un lugar seguro y que sea accesible únicamente por la aplicación de “Autorizar pagos”, asociada al api-key
.Junto con el pedido de autorización o ajuste te enviaremos headers HTTP con la firma, el timestamp de la firma y la api-key
para que verifiques que la firma sea correcta.
Los headers HTTP que enviamos son:
x-api-key
: este header te permitirá identificar qué api-secret
tenés que usar en el caso que se hayan configurado múltiples pares de api-key
y api-secret
.
x-signature
: este header contiene la firma digital (body + timestamp + endpoint) que deberás verificar para asegurar la integridad del request. Si la firma no coincide, deberás rechazar el pedido.
x-timestamp
: este header contiene el momento en el que se firmó el pedido en formato unix-epoch para que puedas corroborar que la firma no expiró.
x-endpoint
: el endpoint al que se realiza el pedido y usaste para generar la firma. Usa este header para regenerar la firma a validar, compararlo con el endpoint de tu servicio y verificar que coinciden.
Veamos un curl de ejemplo indicando cómo se envía esta información dentro del 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'
}
}'
Para el armado de la firma se puede utilizar el siguiente snippet de código (en python 3) como por ejemplo:
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))
El endpoint /shipping/v1/
se usa para crear un nuevo envío.
region
con el código UF de dos caracteres. Ejemplo: 'SP' para São Paulo
El endpoint /shippining/v1/
te permite buscar un grupo de envios según los atributos que especifiques.
Tendrás que especificar tus filtros como parámetros siguiendo este patrón: filter[campo]=valor
. Por ejemplo: filter[shipment_type]=BOX
.
Para filtrar un atributo con varios posibles valores, deberás separar los valores por coma. Veamos un ejemplo: filter[shipment_type]=BOX,WAREHOUSE
Los resultados serán paginados y podrás especificar la cantidad de datos por página y también qué página ver utilizando: page[1]
y page[2]
Podrás especificar el orden de los resultados con determinados parámetros que deberás enviar como una lista de strings en el filtro de tipo sort. Por ejemplo: /shipping/v1/?sort=status,shipment_type
.
El ordenamiento por defecto será ascendente. Para especificar un orden descendente, deberás enviar el carácter '-' como prefijo del atributo. Por ejemplo: /shipping/v1/?sort=status,-shipment_type
.
Los atributos para ordenar son:
shipment_type
status
status_detail
Si un parámetro es incorrecto o está mal escrito, responderemos con un error.
El endpoint /shipping/v1/{shipment_id}
te permite obtener información sobre un envío en particular.
Deberás especificar el shipment_id
para hacer la consulta.
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.
Deberás implementar y exponer en tu backend los endpoints de “Autorización” y “Ajustes” para que podamos comunicarnos.
Cada vez que un usuario utiliza su tarjeta en cualquier tienda o comercio electrónico.
Cuando la red (Mastercard, Visa, etc) solicita la conciliación de todos los pagos que presentan los comerciantes.
Si hubiera una diferencia en la conciliación, solicitaremos una corrección a tu API. Necesitaremos que tus endpoints respondan lo más rápido posible para garantizar una buena experiencia de usuario. Si la respuesta se demora, rechazaremos la transacción.
Como una solicitud HTTP puede dar timeout, tenemos que asegurarnos de que al reintentar se procese una única vez. Para eso, en cada solicitud, te enviaremos un header x-idempotency-key
con ID único que deberás procesar con un caché en memoria (por ejemplo: redis).
Al comienzo de cada transacción, deberás verificar si la clave de idempotencia que te enviamos ya está en la caché en memoria y dependiendo de si está o no, deberás realizar lo siguiente:
Deberás almacenar en la caché en memoria la relación clave de idempotencia → pedido con un estado en tránsito con un TTL de 3 minutos.
Cuando apruebes o rechaces la transacción, deberás almacenar el resultado en la caché y actualizar el estado de la clave de idempotencia a terminado
.
En caso de una solicitud duplicada, deberás verificar el estado de la transacción en la caché.
terminado
deberás responder con un código HTTP 200 con el body esperado para el endpoint y completarlo con el resultado de la caché.en tránsito
deberás responder con un código HTTP 425 (Too Early: RFC 8470) con el body esperado para el endpoint. Nosotros volveremos a buscar la respuesta de esta solicitud unos milisegundos más tarde.La comunicación entre nuestros backends debe ser estrictamente segura ya que los endpoints permitirán cargar y deducir fondos.
Para eso, requerimos que implementes tres medidas:
Toda comunicación con nosotros debe ser vía HTTPS, sin importar quien emite el certificado.
Te acercamos algunos de los proveedores más reconocidos
Siempre nos comunicaremos con tu backend desde IPs específicas. Recomendamos que solo aceptes request de las siguientes IPs y que rechaces cualquier otra:
IPS de Pomelo:
34.226.254.178
44.198.3.59
34.206.159.176
52.0.20.124
Para asegurarnos de que los únicos participantes en la comunicación sean nuestros backends (Pomelo y el Cliente), en el momento del onboarding le proporcionaremos una api-key
y api-secret
para firmar digitalmente el contenido de la comunicación.
El proceso será algo así:
api-key
y api-secret
.Al momento de una autorización de pago, nosotros firmamos con hmac-sha256 cada pedido de autorización con el api-secret
.
api-key
del request.api-secret
.Durante el proceso de onboarding, crearemos una api-key
y api-secret
específicas para ti.
También es posible usar gpg o algún plugin de correo electrónico (como por ejemplo https://flowcrypt.com/).
Veamos un ejemplo usando openssl en la línea de comandos.
$ 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.pem
por email o Slack.$ openssl rsautl -encrypt -in api-credentials.txt -out api-credentials.txt.enc -inkey public.pem -pubin
api-credentials.txt.enc
por email o Slackapi-credentials.txt.enc
con tu clave privada private.pem
:$ openssl rsautl -decrypt -in api-credentials.txt.enc -inkey private.pem
api-key=tgeAkX0795jKTxrVR0cJbb//D8UlhHn0KZwTcDG3gyg=
api-secret=un/OHwD+fMN1TTSaEhs0vupQEDQS7DVaUdlNOu7Fpyw=
api-secret
en un lugar seguro y que sea accesible únicamente por la aplicación de “Autorizar pagos”, asociada al api-key
.Junto con el pedido de autorización o ajuste te enviaremos headers HTTP con la firma, el timestamp de la firma y la api-key
para que verifiques que la firma sea correcta.
Los headers HTTP que enviamos son:
x-api-key
: este header te permitirá identificar qué api-secret
tenés que usar en el caso que se hayan configurado múltiples pares de api-key
y api-secret
.
x-signature
: este header contiene la firma digital (body + timestamp + endpoint) que deberás verificar para asegurar la integridad del request. Si la firma no coincide, deberás rechazar el pedido.
x-timestamp
: este header contiene el momento en el que se firmó el pedido en formato unix-epoch para que puedas corroborar que la firma no expiró.
x-endpoint
: el endpoint al que se realiza el pedido y que se uso para generar la firma. Usa este header para regenerar la firma a validar, compararlo con el endpoint de tu servicio y verificar que coinciden.
Veamos un curl de ejemplo indicando cómo se envía esta información dentro del 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'
}
}'
Para el armado de la firma se puede utilizar el siguiente snippet de código (en python 3) como ejemplo:
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))
Importante: deberás firmar tu body junto con el timestamp y el endpoint utilizando tu api-secret
luego de impactar la operación. Ten en cuenta que validaremos la firma y rechazaremos la transacción si la firma no coincide o expiró.
Este es un proceso opcional, pero recomendamos ejecutarlo a diario.
En un bucket de S3 que te disponibilizaremos encontrarás estos archivos:
Contiene el detalle de cada transacción que te generamos el día anterior.
El nombre del archivo tiene el siguiente formato: presentacionesyyyy_mm_dd
{Atributo} | Descripción | Valores permitidos |
---|---|---|
TRANSACTION_ID | El id que permite identificar la transacción como única. | |
LOCAL_TRANSACTION_DATE_TIME | ||
TRANSACTION_TYPE | Indica el tipo de transacción. | PURCHASE WITHDRAWAL EXTRACASH REFUND PAYMENT REVERSAL_PURCHASE REVERSAL_WITHDRAWAL REVERSAL_EXTRACASH REVERSAL_REFUND REVERSAL_PAYMENT |
PRODUCT_TYPE | Es el tipo de producto | PREPAID CREDIT DEBIT |
PROVIDER | Es la marca de la tarjeta emitida. | VISA MASTERCARD |
AFFINITY_GROUP_ID | ||
USER_ID | El id del usuario de Pomelo titular de la tarjeta. | |
CARD_ID | ||
BIN | Los primeros seis u ocho dígitos del PAN. | |
LAST_FOUR | Los últimos cuatro dígitos del PAN. | |
ORIGIN | DOMESTIC: la transacción ocurrió en el país del emisor. INTERNATIONAL: la transacción no se realizó en el país del emisor. | |
MERCHANT_ID | ||
MERCHANT_MCC | El código de categoría de comerciante según se define en el ISO-18245. | |
MERCHANT_NAME | ||
LOCAL_AMOUNT | Es el monto total de la transacción que debe ser deducido del balance del usuario, con impuestos y tasas agregadas (cuando aplica). Siempre se convierte a la moneda local de la tarjeta. | |
LOCAL_CURRENCY | El código de la moneda de LOCAL_TOTAL en ISO_4217 formato ALPHA-3. | |
TRANSACTION_AMOUNT | El monto de la transacción sin impuestos y en la moneda original enviada por el comerciante. | |
TRANSACTION_CURRENCY | El código de la moneda de TRANSACTION_TOTAL en ISO_4217 formato ALPHA-3. | |
SETTLEMENT_AMOUNT | El monto de la transacción según lo enviado por la red. Para Argentina siempre lo mostraremos en USD, mientras que para el resto de los países, en la moneda local. | |
SETTLEMENT_CURRENCY | El código de la moneda de SETTLEMENT_TOTAL en ISO_4217 formato ALPHA-3. Para Argentina siempre lo mostraremos en USD, mientras que para el resto de los países, en la moneda local. | |
ENTRY_MODE | El modo en que se usó la tarjeta en el punto de venta del comerciante. | UNKNOWN MANUAL CHIP CONTACTLESS CREDENTIAL_ON_FILE MAG_STRIPE OTHERS |
STATUS | El estado de la transacción. | APPROVED REJECTED HELD |
STATUS_DETAIL | Razón adicional por la que la transacción se aprueba o rechaza. | Ver tabla a continuación |
SOURCE | Indica qué flujo / proceso desencadenó la transacción, visto desde Pomelo. | ONLINE: Se origina durante el flujo transaccional a partir de transacciones en tiempo real enviadas por la red CLEARING: Se origina durante el proceso de acuerdo entre Pomelo y la red al gestionar el archivo de liquidación PURGE: transacciones que no se presentaron en el archivo de liquidación de la red. |
ORIGINAL_TRANSACTION_ID | Este valor podría estar vacío si la transacción no está relacionada con otra. | |
COUNTRY_CODE | Este es el código de país en formato ISO-3166. | |
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 | Descripción |
---|---|
CARD_BLOCKED | El estado de la tarjeta es BLOCKED. |
CARD_DISABLED | El estado de la tarjeta es DISABLED |
CARD_NOT_ACTIVE | El estado de la tarjeta es EMBOSSED o CREATED |
CARD_NOT_CONFIGURED | A la tarjeta le faltan configuraciones. |
CARD_NOT_FOUND | No podemos encontrar el PAN de la tarjeta. |
CLIENT_TIMEOUT | El cliente demora en responder. |
CLIENT_UNAVAILABLE | No podemos conectar con el cliente o recibimos un 5XX. |
CLIENT_SIGNATURE_ERROR | Cuando hay una falla en la firma del cliente. |
CRYPTO_ERROR | Hay un error en los criptogramas (EMV). |
DUPLICATE_TRANSMISSION_DETECTED | Recibimos una transacción repetida por parte de la network. |
EXPIRED_CARD | El estado de la tarjeta es EXPIRED. |
EXTRA_FIELDS | La mensajería de parte de la network viene con campos no esperados. |
INSUFFICIENT_FUNDS | El cliente nos responda que la cuenta no tiene fondos. |
INTERNAL_ERROR | Fallo imprevisto en el sistema de Pomelo. |
INVALID_AMOUNT | Se superan los límites del grupo de afinidad. |
INVALID_CVV | El CVV no coincide. |
INVALID_EXPIRATION_DATE | La fecha de expiración recibida no coincide con la tarjeta. |
INVALID_MERCHANT | El cliente rechaza al merchant por algún motivo específico. |
INVALID_PIN | El PIN es incorrecto |
INVALID_TRANSACTION | La transacción es inválida. |
LOST_CARD | El estado de la tarjeta es LOST. |
MISSING_FIELDS | La mensajería de parte de la network viene sin campos obligatorios. |
NOT_DECLINED | Una transacción viene con monto en 0 para validar si la cuenta está activa. |
ORIGINAL_NOT_FOUND | Se intenta hacer una reversal de una transacción que no encontramos. |
OTHER | No reconocemos el caso. |
RESTRICTED_USER | El estado del usuario no es ACTIVE. |
SECURITY_VIOLATION | Supera un umbral de fraude. |
SERVICE_UNAVAILABLE | El cliente o un servicio de Pomelo están caídos. |
STOLEN_CARD | El estado de la tarjeta es STOLEN. |
SYSTEM_ERROR | El cliente nos indica que tuvo un error inesperado. |
APPROVED | El cliente aprueba una transacción. |
TRANSACTION_NOT_PERMITTED | El tipo de transacción no está permitido en el grupo de afinidad. |
¿Está en Pomelo? | ¿Está en el cliente? | ¿Tiene el mismo estado? | Action |
---|---|---|---|
Y | Y | Y | No hacer nada / Marcar como coincidente |
Y | Y | N | 1) Registrar un ajuste que debite / acredite al usuario final si corresponde. 2) Marcar como coincidente. |
Y | N | N | 1) IF STATUS == APPROVED: Registrar un ajuste que debite / acredite al usuario final si corresponde. 2) Marcar como coincidente. |
N | Y | N | No es un caso de uso posible. |
En caso de que esté intentando ajustar un crédito a un usuario final que no tenga fondos suficientes en la cuenta, debe seguir intentando obtener los fondos de ese usuario.
Se convierte en una deuda entre el cliente y el usuario final.
Contiene el detalle de cada transacción que presentan los comerciantes el día anterior.
El nombre del archivo tiene el siguiente formato: presentacionesyyyy_mm_dd
Atributo | Descripción | Valores permitidos |
---|---|---|
PRESENTMENT_ID | ||
TRANSACTION_ID | El id de la transacción original que generó la presentación. | |
LOCAL_TRANSACTION_DATE_TIME | ||
TRANSACTION_TYPE | Indica el tipo de transacción. | PURCHASE WITHDRAWAL EXTRACASH REFUND PAYMENT |
PRODUCT_TYPE | Es el tipo de producto. | PREPAID CREDIT DEBIT |
PROVIDER | Es la marca de la tarjeta emitida. | VISA MASTERCARD |
AFFINITY_GROUP_ID | ||
USER_ID | El id del usuario de Pomelo titular de la tarjeta | |
CARD_ID | ||
BIN | Los primeros seis u ocho dígitos del PAN. | |
LAST_FOUR | Los últimos cuatro dígitos del PAN. | |
ORIGIN | DOMESTIC: la transacción ocurrió en el país del emisor. INTERNATIONAL: la transacción no se realizó en el país del emisor. | |
MERCHANT_ID | ||
MERCHANT_MCC | El código de categoría de comerciante según se define en el ISO-18245. | |
MERCHANT_NAME | ||
TRANSACTION_AMOUNT | El monto de la transacción sin impuestos y en la moneda original enviada por el comerciante. | |
TRANSACTION_CURRENCY | El código de la moneda de TRANSACTION_TOTAL en ISO_4217 formato ALPHA-3. | |
SETTLEMENT_AMOUNT | El monto de la transacción presentado por la marca. | |
SETTLEMENT_CURRENCY | El código de la moneda de SETTLEMENT_AMOUNT en ISO_4217 formato ALPHA-3. Para Argentina siempre lo mostraremos en USD, mientras que para el resto de los países, en la moneda local. | |
DEBT_AMOUNT | El monto de la transacción en la moneda a pagar a Pomelo. Si el monto se debe pagar a Pomelo siempre es un valor positivo, de lo contrario será un valor negativo. | |
DEBT_CURRENCY | El código de la moneda de DEBT_AMOUNT en ISO_4217 formato ALPHA-3, si es una transacción doméstica deberá pagarse en moneda local, de lo contrario en USD. | |
RECONCILIATION_DATE | ||
INTERCHANGE_FEE | Comisión por una transacción aplicada al intercambio de la misma. | |
INTERCHANGE_RATE | Valor alfanumérico que identifica la tasa de intercambio de la transacción presentada por el adquirente. | |
TAX | Este es el impuesto asociado a la tasa de intercambio, debido a la regulación local, esos montos deben tener un IVA calculado. | |
FUNCTION_CODE | Este es el tipo de presentación. | FIRST_PRESENTMENT SECOND_PRESENTMENT_FULL SECOND_PRESENTMENT_PARTIAL |
REVERSE_PRESENTMENT | Significa que la presentación fue revertida desde la red. | TRUE FALSE |
REASON_CODE | Razón de la segunda presentación. | |
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 | |
CURRENT_INSTALLMENT | [OPCIONAL*] Indica qué número de cuota está pagando el cliente. | |
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.
Nuestro equipo de finanzas enviará diariamente un detalle con la deuda a pagar. Ese detalle tendrá todas las presentaciones que recibimos en el archivo de presentación.
Disponibilizaremos un servidor SFTP desde donde podrás descargar los archivos de Transacciones y Presentaciones.
Tenemos dos ambientes para los servidores SFTP: un ambiente productivo y otro de desarrollo.
Para conectarte a los servidores SFTP necesitaremos que nos envíes una llave pública para generarte un usuario.
Estos son los datos para conectarte a cada ambiente:
Host: sftp.pomelo.la
Puerto: 22
Usuario: <tu_usuario> # el que te generamos a partir de tus llaves públicas.
Host: sftp-dev.pomelo.la
{Puerto}: 22
Usuario: <tu_usuario> # el que te generamos a partir de tus llaves públicas.
Para generar la clave pública tendrás que usar el comando acorde a tu sistema operativo:
$Cliente
por el nombre propiossh-keygen -t rsa -b 2048 -C $Cliente
El comando creará un par de claves RSA de 2048 bits de forma predeterminada. También podrás crear una clave más grande de 4096 bits ingresando -b 4096.
El comando produce esta salida:
Generating public/prive rsa key pair.
Ingresa un archivo en el que guardar la clave (/your_home/.ssh/id_rsa):
Presiona Enter
para guardar el par de claves en .ssh /, o especifica otra ubicación.
Presiona Enter
para dejarlo en blanco y usa solo la clave para establecer conexiones SSH. Ingresa una contraseña para una capa de seguridad adicional.
cat ~/.ssh/id_rsa.pub
La clave generada comenzará con ssh-rsa.
Ahora puedes copiar y pegar tu clave SSH pública en tu consola Shell, o en cualquier servidor, para establecer una conexión segura.
Genera claves SSH usando PuTTY. Instala PuTTY desde la página del desarrollador: https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html
Instala PuTTY desde la página del desarrollador: https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html
puttygen
.PuTTYgen
.Ejecutar como administrador
.Sí
si el sistema te consulta “¿Desea permitir que esta aplicación realice cambios en su dispositivo?”Si bien la herramienta PuTTY keygen ofrece varios otros algoritmos, te contaremos cómo generar claves RSA, una de las más usadas:
Generar
.Guardar clave pública
. Luego tendrás que elegir una ubicación para guardar la clave y asignarle un nombre a la clave.Conversiones
en la parte superior.Sí
.El endpoint /transactions/authorizations
permite autorizar las transacciones.
Te enviaremos una solicitud para autorizar o rechazar la transacción.
Esperamos una respuesta rápida para garantizar una buena experiencia. Si la respuesta se demora, rechazaremos la transacción.
El endpoint /transactions/adjustments/{type}
nos permite hacer ajustes de crédito y débito en las transacciones.
Te enviaremos una solicitud para informarle que la red (MC, VISA) forzó una autorización.
Este endpoint se usa durante la conciliación y los flujos online, principalmente para hacer ajustes durante el proceso de liquidación y también en caso de devoluciones.
El servicio de Core te permite crear y administrar las cuentas digitales de tus usuarios.
Para tener una cuenta tus usuarios deberán:
Las cuentas tendrán alguno de estos estados:
ACTIVE
: La cuenta está activa y se puede usar para hacer transacciones normalmente. Cuando se crea una cuenta su estado inicial será ACTIVE
.FROZEN
: La cuenta podrá recibir dinero pero las transacciones de débito estarán bloqueadas.DISABLED
: La cuenta no tiene permitida ninguna transacción.DELETED
: La cuenta está eliminada sin posibilidad de volver a activarla.Para cambiar el estado de una cuenta entre los estados ACTIVE
, FREEZED
y DISABLED
deberás usar el endpoint PATCH
de este servicio.
Para cambiar el estado de una cuenta a DELETED
usa el endpoint DELETE
.
Si falla alguna operación, devolveremos un error con una lista de las posibles operaciones asociadas:
ACCOUNT_VALIDATION_ERROR
: No se pudo validar correctamente la cuenta. Por ejemplo, cuando la key de idempotencia utilizada en la request, ya está en uso por otro usuario.
CREATE
USER_VALIDATION_ERROR
: No pudimos validar la identidad del usuario o el usuario no existe.
CREATE
CLIENT_VALIDATION_ERROR
: No pudimos identificar a qué cliente pertenece el usuario al que estás intentando crearle una cuenta.
CREATE
USER_ACCOUNT_LIMIT_REACHED
: El usuario alcanzó el límite de cuentas que puede tener y por eso no es posible crearle una nueva.
CREATE
ACCOUNT_NOT_FOUND
: El ID de cuenta no existe.
UPDATE
DELETE
ACCOUNT_DELETED
: El ID de cuenta fue eliminado.
UPDATE
DELETE
INVALID_ACCOUNT_STATUS
: El estado de actualización de la cuenta es inválido.
UPDATE
DELETE
LOCKED_ACCOUNT_STATUS
: No es posible actualizar una cuenta que modificamos nosotros desde Pomelo.
UPDATE
DELETE
INVALID_UPDATE_STATUS_MOTIVE
: El motivo de actualización del estado de la cuenta que ingresaste es inválido. Para DELETE
los motivos válidos son OTHER
, INTERNAL_REASON
, USER_REQUEST
y FRAUD
. Para DISABLED
son OTHER
, LOST
, INTERNAL_REASON
, STOLEN
, FRAUD
y INHIBITION
. Para FROZEN
son OTHER
y SEIZURE
UPDATE
DELETE
ACCOUNT_HAS_FUNDS
: No es posible eliminar una cuenta que no está completamente vacía.
DELETE
/core/accounts/v1
te permite crear una cuenta digital para un usuario de Pomelo. Si creas bien la cuenta, te devolveremos un status 201
Identificador idempotente de creación de cuenta. Deberás generar este valor para cada cuenta que quieras crear. Si dos requests idénticos tienen el mismo identificador de idempotencia solo crearás una cuenta aunque ambos reciban una respuesta exitosa.
/core/accounts/v1/{id}
te permitirá eliminar una cuenta específica. Al hacerlo, su estado pasará a DELETED
y ya no se podrá usar para hacer transacciones.status_update_motive
es OTHER
.El endpoint /core/accounts/v1/{id}
te servirá para cambiar el estado de una cuenta.
Los estados de la cuenta pueden alterarse entre
Para los últimos dos estados es necesario indicar el motivo del cambio de estado
ACTIVE
.status_update_motive
es OTHER
.Accounts Query API es un servicio que agrupa toda la información de las cuentas digitales de Pomelo y la disponibiliza para que puedas consultarla.
Te permitirá consultar:
Es cualquier operación que tuvo la intención de modificar el balance de una cuenta. Es decir:
/core/activities/v1
devuelve un listado paginado de todas las actividades. Puedes usar filtros para especificar que solo se devuelvan las actividades de una cuenta particular.Lenguajes ordenados según tu preferencia. Especificación técnica
/core/activities/v1/{id}
permite obtener información de la actividad que especifiques.Lenguajes ordenados según tu preferencia. Especificación técnica
/core/accounts/v1
devuelve un listado paginado de las cuentas digitales junto con sus balances./core/accounts/v1/{id}
devuelve la información de la cuenta solicitada, junto con su balance.Este servicio te permite autorizar transacciones.
Las transacciones solo tienen dos estados posibles:
APPROVED
: Si la transacción es aprobada.REJETED
: Si la transacción es rechazada.Todas las transacciones que son aprobadas modificarán el balance de la cuenta por el monto especificado.
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
: Para transacciones que quieran retirar dinero de la cuenta.CREDIT
: Para transacciones que quieran ingresar dinero a la cuenta.Todas las transacciones tienen un tipo, que indicamos con el parámetro type
.
Cada tipo de transacción tiene distintos datos que se envían con la transacción dentro del objeto tx_properties
.
Podrás solicitar datos extras de todas las transacciones usando el objeto metadata
.
La propiedad details
se puede usar para descomponer el monto total de una transacción en las partes que lo componen. Por ejemplo supongamos que se está procesando una transacción que representa una compra en una tienda digital por un total de $149,99. Supongamos además, que este total se compone por:
Esta descomposición se puede informar agregando multiples items a la lista details
. Cada detalle debe tener un tipo asociado:
BASE
: Gasto base de la transacción.FEE
: Gastos de comisión.TAX
: Impuestos.EXTRACASH
: Extracciones de dinero.DISCOUNT
: Descuentos.Es posible agregar más de un detalle con el mismo tipo. La única restricción es que la sumatoria de los montos de los detalles sea igual al monto total de la transacción.
Cada transacción lleva un campo process_type
que puede tomar alguno de estos valores:
ORIGINAL
: Transacción nueva.ADJUSTMENT
: Ajuste.REFUND
: Reintegro o devolución.REVERSAL
: Reversa.Para las transacciones que sean REFUND
, REVERSAL
o ADJUSTMENT
se puede especificar la transacción originaria que las motiva. Esa transacción se conoce como “transacción padre” y la indicamos mediante el campo parent_tx_id
.
Los pedidos de autorización de transacciones tienen un mecanismo de idempotencia para prevenir el procesamiento duplicado.
Deberás acompañar cada request de autorización con un header X-Idempotency-Key
que tenga un identificador único para la transacción a procesar. En caso de que no obtengas respuesta o recibas una respuesta con status code del tipo 5xx, deberás volver a repetir el request con la misma key de idempotencia hasta obtener una respuesta exitosa (code 201).
Los requests repetidos que utilicen la misma key de idempotencia solo tendrán como resultado la creación de una transacción. El primer request creará la transacción y los siguientes devolverán la misma respuesta que se devolvió para el primer request, pero no crearán una transacción nueva.
Si un pedido de autorización tiene una key de idempotencia que ya usaste en otra transacción, responderemos con un error.
Las transacciones que procesamos correctamente se informan con un status code 201
. Pero atención: este estado no indica si la transacción fue aprobada. Para saber eso, tendrás que leer el campo 'result' de la respuesta e identificar si su valor es APPROVED
o REJECTED
.
Cualquier otro status code indica que algo salió mal y te indicaremos el motivo de rechazo en el campo rejection_reason
.
Este campo puede tomar los siguientes valores:
INSUFFICIENT_FUNDS
: La cuenta no tiene fondos suficientes.ACCOUNT_DISABLED
: La cuenta está deshabilitada.ACCOUNT_FROZEN
: La cuenta no puede procesar transacciones de débito (DEBIT
).CLIENT_MONTHLY_AMOUNT_LIMIT_REACHED
: Superó el límite de movimientos mensual que teníaCLIENT_DAILY_AMOUNT_LIMIT_REACHED
: Superó el límite de movimientos diarios que tenía.PROCESS_TIME_EXPIRED
: La transacción no comenzó a procesarse antes del tiempo indicado por el campo process_before
, que es opcional.Cuando no podemos procesar una transacción devolveremos una respuesta de error con el campo error_code
indicando el motivo:
ACCOUNT_NOT_FOUND
: No encontramos la cuenta.INVALID_AUTHORIZATION_REQUEST
: El request para autorizar la transacción no es válido.INVALID_PARENT_TX_ID
: La transacción padre que especificaste es inválida.DUPLICATED_IDEMPOTENCY_KEY
: Ya usaste la key de idempotencia en otra transacción./core/transactions/v1
te permite autorizar transacciones de entrada y salida de dinero de las cuentas digitales. Las transacciones procesadas correctamente devolverán el status code 201
, ya sea que fueran aprobadas o rechazadas. Revisa el campo result
para ver el resultado.CREDIT
y para debitar CREDIT
.Este servicio será el encargado de notificarte todas las actividades de tus cuentas.
Una notificación puede tratarse de una creación o de una modificación de una actividad. Para determinar de qué caso se trata podrás leer el campo type
, el cual puede tener alguno de estos valores:
ACTIVITY_CREATED
: La notificación se trata de la creación de una nueva actividad.ACTIVITY_UPDATED
: La notificación se trata de la modificación de una actividad. Las actividades pueden cambiar su estado de PENDING
a APPROVED
o de PENDING
a REJECTED
.Junto con la notificación enviaremos un conjunto de headers HTTP que te servirán para verificar la autenticidad de la misma.
Los headers HTTP que enviamos son:
x-api-key
: este header te permitirá identificar qué api-secret
tenés que usar en el caso que se hayan configurado múltiples pares de api-key
y api-secret
.
x-signature
: este header contiene la firma digital que deberás verificar para asegurar la integridad del request. Si la firma no coincide, deberás rechazar el pedido.
x-timestamp
: este header contiene el momento en el que se firmó el pedido en formato unix-epoch para que puedas corroborar que la firma no expiró.
x-endpoint
: el endpoint al que se realiza el request. Usa este header para regenerar la firma a validar, compararlo con el endpoint de tu servicio y verificar que coinciden.
La firma digital es un código HMAC-SHA256 que se construye utilizando él api-secret
y una serie de bytes que está compuesta por la concatenación del timestamp, endpoint y request body codificados en UTF-8.
El siguiente es un pseudo-código para verificar que la firma digital de un request sea legítima:
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
tenés que usar en el caso que se hayan configurado múltiples pares de api-key
y api-secret
timestamp + endpoint + body
) que deberás verificar para asegurar la integridad del request.Si la firma no coincide, deberás rechazar el pedido.Este servicio te permite integrarte con distintas redes de efectivo para consultar los datos de una cuenta y poder ingresar dinero (cash in) o registrar intenciones de extracción de dinero (cash out intent).
Para ingresar dinero, cada cuenta tendrá un alias que te permitirá identificarla en una red de pagos. Ese alias se autogenera y asocia a la cuenta cuando se crea.
Para los casos de extracciones, deberás registrar un cash out intent, que, combinado con el alias, podrás usar para extraer efectivo de una cuenta en las redes de pagos habilitadas.
País | Network | ID |
---|---|---|
Argentina | Pago Fácil | PAGO_FACIL |
El endpoint POST /networks/cash/v1/cashout/intents
te permitirá generar un intento de cash out para una cuenta determinada. Cada intento representa la intención de extraer dinero del saldo de una cuenta a través de una red de pago.
Solo podrá existir un intento activo por cuenta y red. El intento se resuelve cuando se realice efectivamente la extracción a través de una red de cash o cuando llegue la fecha de expiración. La creación de un nuevo intento sobreescribe el intento anterior.
El endpoint GET /networks/cash/v1/cashout/intents/{account_id}
te permite obtener el último cash out intent vigente. Para considerar un cash out vigente se deben cumplir las siguientes condiciones:
El endpoint GET /networks/cash/v1/alias/{account_id}
te permitirá obtener el alias de una cuenta. Se trata de un valor único asociado a la cuenta, que te servirá para hacer una operación de cash in en la red de pagos.
Este servicio te permite integrarte con distintas redes de efectivo para consultar los datos de una cuenta y registrar intenciones de ingresos de dinero (cash in intent) para una cuenta en una red de efectivo.
Para ingresar dinero, deberás registrar un cash in intent en alguna de las redes de pagos habilitadas.
País | Network | ID |
---|---|---|
Brasil | Boleto | BOLETO |
El endpoint POST /networks/cash/v1/cashin/intents te permitirá generar un intento de cash in para una cuenta determinada. Cada intento representa la intención de ingresar dinero al balance de una cuenta a través de una red de pago.
Ciclo de vida
El intento se resuelve cuando se realice efectivamente el ingreso de dinero a través de una red de cash o cuando se alcance la fecha de expiración, lo primero que ocurra.
El intento puede tener distintos estados dependiendo qué acción haya sido aplicada al mismo:
expires_at
). Cuando llega la fecha de expiración no podrás usar ese intent para ingresar dinero, deberás generar uno nuevo.El servicio de Bank Account API dentro del flujo de transferencias es el que se encarga de la gestión de los atributos bancarios de la cuenta y de obtener la información de una cuenta destino al iniciar una transferencia.
Dentro de la gestión de los atributos de una cuenta se encuentra el cambio de Alias. Cada cuenta nace con un CVU y un alias seteado por defecto, este último podrá ser modificado por el usuario según su preferencia.
En cuanto a la obtención de información de una cuenta destino, cada transferencia que se realiza comienza con la validación de la cuenta destino mediante el uso del CVU o alias. Este servicio es el que se encarga de hacer esa gestión y de devolver la cuenta destino ya validada con información adicional del titular (CBU, código de banco, nombre y CUIT).
El servicio de Bank Account API dentro del flujo de transferencias es el que se encarga de la gestión de los atributos bancarios de la cuenta.
Dentro de la gestión de los atributos de una cuenta se encuentra el ABM de la llave PIX.
Consideraciones:
La transferencia se realizará mediante un posteo en la Transfer API, una vez que la información de la cuenta destino se valide por el servicio de Bank Account API.
La respuesta de la transferencia puede ser sincrónica o asincrónica. En el caso de una respuesta sincrónica el servicio de Transfer API devolverá el estado final de la transacción (SUCCESS or FAILED). Si la respuesta es asincrónica porque se demora algunos segundos más, el servicio de Transfer API devolverá un estado pendiente de manera sincrónica (IN_PROGRESS) y la notificación del estado final de la transacción se notificará como Actividad a través del servicio de Webhooks de Core.
La transferencia se realiza en 2 simples pasos:
La respuesta de la transferencia puede ser sincrónica o asincrónica. En el caso de una respuesta sincrónica, el servicio de Transfer API devolverá el estado final de la transacción (SUCCESS or FAILED). Si la respuesta es asincrónica (porque se demora algunos segundos más), el servicio de Transfer API devolverá un estado pendiente de manera sincrónica (IN_PROGRESS) y la notificación del estado final de la transacción se verá como Actividad a través del servicio de Webhooks de Core.
El endpoint identity/v1/sessions
te permite crear una nueva sesión de validación de identidad y te devuelve un identificador único de la misma.
El endpoint /sessions
te permite realizar una búsqueda con filtros específicos.
Tendrás que especificar tus filtros como parámetros siguiendo este patrón: filter[field]=value
. Por ejemplo: filter[status]=IN_PROGRESS
Los resultados serán paginados y podrás especificar la cantidad de datos por página y también qué página ver.
Hay un filtro para el campo created_at
, que podrás usar para obtener las sesiones creadas dentro un rango de fechas. Por ejemplo: filter[created_at][from]=2021-07-27&filter[created_at][to]=2021-07-28
Podrás especificar el orden de los resultados con determinados parámetros que deberás enviar como una lista de strings en el filtro de tipo sort. Por ejemplo: ?sort=status,user_id
El ordenamiento por defecto será ascendente. Para especificar un orden descendente, deberás enviar el carácter '-' como prefijo del atributo. Por ejemplo: ?sort=status,-user_id.
Los atributos para ordenar son user_id
, status
y created_at
.
Si un parámetro es incorrecto o está mal escrito, responderemos con un error.
identity/v1/sessions/{id}
te permite obtener datos de una sesión de validación de identidad.identity/v1/sessions/{id}
te permite cancelar una sesión de validación de identidad.identity/v1/sessions/{id}/report
te permite obtener los datos de un usuario recabados en una sesión de validación de identidad.Este servicio será el encargado de notif