Introducción
Sobre Koywe
- 🌳 ¿Qué es Koywe?
- ✨ Casos de Uso
Documentación API
GraphQL API
URL de pruebas: https://api-sandbox.koywe.com/graphql
Esta URL corre una instancia del explorador Apollo, por si es que quieres probar la API desde tu navegador.
Envíanos un email a hola@koywe.com para obtener tus credenciales de prueba o que te hagamos un tour personalizado.
Pruebas: La API de pruebas funciona en las testnets de las distintas blockchains. Tenemos un stock limitado de tokens, por lo que te pedimos criterio al probarlas.
Queries y Mutaciones
Para hacer llamados a la API GraphQL, siempre debes enviar un request POST a la URL base, incluyendo la query y variables como objeto JSON. Un ejemplo en CURL de autenticación (header de Authorization incluido ilustrativamente):
curl --request POST \
--header 'content-type: application/json' \
--header 'Authorization: Bearer JWTTOKEN' \
--url 'https://api-sandbox.koywe.com/graphql' \
--data '{"query":"mutation authenticate($input: AuthInput!) {\n authenticate(input: $input) {\n token\n }\n}","variables":{"input":{"clientId":"63631a561f41f8fd18f8c3e0","secret":"supersecretstringFTW"}}}'
En los ejemplos siguientes sólo pondremos el objeto JSON del request.
devuelve un Bearer Token que dura 24 horas.
Require: clientId
, secret
Opcional: email
. Este campo asocia las transacciones a una cuenta de usuario específica y permite ver la información asociada a esta.
mutation Authenticate($input: AuthInput!) {
authenticate(input: $input) {
token
}
}
"variables" :
{
"input": {
"clientId": "63631a561f41f8fd18f8c3e0",
"secret": "secretpassword",
"email": "email@domain.com" # optional
}
}
Los dos siguientes servicios permiten la validación de un usuario final de manera directa. El primer servicio enviará un código al correo deseado. Ese código debe ser ingresado en el segundo servicio para recibir la información de la sesión.
Envía un código de 6 dígitos al email entregado en el input.
mutation validateAccount($input: ValidateAccountInput!) {
validateAccount(input: $input) {
_id
}
}
"variables" :
{
"input": {
"email": "email@domain.com",
"clientId": "f87aad3as90fe5489bb5099f"
}
}
El valor de code en el input debe ser recogido del correo enviado por el servicio anterior.
mutation validateCode($input: ValidateCodeInput!) {
validateCode(input: $input) {
token
isIdentify
needVerificate
identity
firstOp
}
}
"variables" :
{
"input": {
"clientId": "40401a5615d9d8fd18f8a0b4",
"code": "940577",
"email": "example@domain.com"
}
}
Obtiene los pares de moneda-tokens soportados.
Opcional: symbol:
El símbolo de la moneda a elección. clientId
.
query GetCurrencyTokensV2($input: GetCurrenciesInput!) {
GetCurrencyTokensV2(input: $input) {
_id
name
symbol
decimals
clientId
logo
locate
limits {
min
max
}
tokens {
_id
name
symbol
decimals
logo
}
}
}
"variables":
{
"input": {
"symbol": null,
"clientId": null
}
}
Obtiene los pares de token-monedas soportados.
Opcional: symbol
. El símbolo del cripto a elección. clientId
query GetTokenCurrencies($input: GetCurrenciesInput!) {
GetTokenCurrencies(input: $input) {
_id
name
symbol
decimals
logo
currencies {
_id
name
symbol
decimals
locale
logo
limits {
min
max
}
}
}
}
"variables":
{
"input": {
"symbol": null,
"clientId": null
}
}
Listado de los medios de pago disponibles y sus detalles (fee, datos de transferencia, etc) para una moneda específica.
Requiere: symbol
. currencyId
.
Opcional: clientId
. La lista de medios de pago disponibles pueden variar de acuerdo a este parámetro.
query GetPaymentProviderList($input: GetPaymentProviderListInput!) {
getPaymentProviderList(input: $input) {
_id
name
fee
image
description
details
}
}
"variables":
{
"input": {
"symbol": "COP"
"clientId": "f87aad3as90fe5489bb5099f"
"currencyId": "489bb507aad3as90fe0f"
}
}
Reglas para Pagos por Transferencia Bancaria WIRE: Para los pagos realizados mediante transferencia bancaria, se han establecido las siguientes reglas:
- Se permite a los usuarios tener solo una orden activa por cliente si utilizan la transferencia bancaria como su método de pago. Esto implica que si un usuario crea una nueva orden mediante transferencia bancaria, las órdenes anteriores se cancelarán, y solo se mantendrá activa la orden más reciente.
- Si un usuario realiza un pago mediante transferencia bancaria y el saldo no es igual al monto de la orden, el sistema ajustará automáticamente la orden. Este ajuste es necesario tanto para los pagos que son inferiores al monto de la orden como para las órdenes que superan el monto especificado.
Listado de los payouts disponibles y sus detalles (fees, tiempos, etc) para una moneda específica.
Requiere: symbol
. currencyId
.
Opcional: clientId
. La lista de medios de pago disponibles pueden variar de acuerdo a este parámetro.
query GetPayoutProviderList($input: GetPayoutProviderListInput!) {
getPayoutProviderList(input: $input) {
_id
name
fee
image
description
details
}
}
"variables":
{
"input": {
"symbol": "COP"
"clientId": "f87aad3as90fe5489bb5099f"
"currencyId": "489bb507aad3as90fe0f"
}
}
Consultar Quote
Devuelve un “Quote”. Recibe un quoteId.
query getQuote($quoteId: String!) {
getQuote(quoteId: $quoteId) {
amountIn
amountOut
co2
exchangeRate
symbolIn
symbolOut
paymentMethodId
koyweFee
networkFee
validFor
validUntil
}
}
"variables":
{
"quoteId": "63c59396a38c6506a620162f" #Created when calling mutation quote
}
Crear Quote
mutation quote($input: QuoteInput!) {
quote(input: $input) {
quoteId
amountIn
amountOut
co2
exchangeRate
symbolIn
symbolOut
paymentMethodId
koyweFee
networkFee
validFor
validUntil
}
}
"variables":
{
"input": {
"amountIn": 3716338,
"amountOut": 3.3,
"clientId": "cse7fj283rkn2x6v7rr",
"symbolIn": "CLP",
"symbolOut": "ETH",
"paymentMethodId": null, # This value corresponds to the _id value returned after calling GetPaymentProviderList
"executable": false #set false by default. If value is set true, we store it and return a UUID.
}
}
Queries Privadas
Todas las queries a continuación requieren un Bearer Token en los headers:
Authorization: Bearer [token]
Estos servicios de usuario incluye: la creación de nuevos perfiles de usuario, la capacidad de actualizar información de usuarios,
la posibilidad de consultar detalles de usuario, y una función de validación que verifica si el usuario brindo datos suficientes de su persona para poder operar.
Ver Consideraciones
Check account
Verifica la información de la cuenta del usuario y determina si es posible realizar alguna operación. Si llegase a faltar algún dato del usuario, podría agregarlo mediante el servicio de actualización de usuario detallado mas abajo.
query CheckAccount($input: InputEmailAccountDto!) {
checkAccount(input: $input) {
canOperate
errors {
field
message
}
accountStatus
nextVerificationDate
}
}
"variables" :
{
"input": {
"email": "email@domain.com"
}
}
Get account
Devuelve la información registrada del usuario.
query GetAccountProfile($input: InputEmailAccountDto!) {
getAccountProfile(input: $input) {
document {
documentNumber
documentType
country
isCompany
others {
documentNumber
documentType
country
}
}
address {
addressStreet
addressCountry
addressZipCode
addressNeighborhood
addressCity
addressState
}
personalInfo {
names
firstLastname
secondLastname
nationality
gender
dob
phoneNumber
activity
}
email
}
}
"variables" :
{
"input": {
"email": "email@domain.com"
}
}
Create account
Crea una cuenta nueva de usuario.
mutation CreateAccount($input: InputCreateAccountDto!) {
createAccount(input: $input) {
document {
documentNumber
documentType
country
isCompany
others {
documentNumber
documentType
country
}
}
address {
addressStreet
addressCountry
addressNeighborhood
addressCity
addressState
addressZipCode
}
personalInfo {
names
firstLastname
secondLastname
nationality
gender
dob
phoneNumber
activity
}
email
}
}
"variables" :
{
"input": {
"email": "email@domain.com",
"document": {
"documentNumber": "",
"documentType": "",
"country": "",
"isCompany": false,
"others": [
{
"documentNumber": "",
"documentType": "",
"country": ""
}
]
},
"address": {
"addressStreet": "",
"addressCountry": "",
"addressZipCode": "",
"addressCity": "",
"addressState": ""
},
"personalInfo": {
"names": "",
"firstLastname": "",
"secondLastname": "",
"nationality": "",
"dob": "",
"gender": "",
"phoneNumber": "",
"activity": ""
}
}
}
Update account
Actualiza datos del usuario. Si updateEmail está presente, la API valida que sea un email válido y que no exista ya otra cuenta con ese email.
Si updateDocumentNumber o updateDocumentType está presente, la API valida que tenga un formato válido, que no exista en otra cuenta, que no tenga ordenes ejecutadas y ejecuta una validación asíncrona para corroborar que los datos personales sean correctos.
Los resultados de la validación asíncrona serán enviados a el callback configurado. Puedes ver más información en la sección de webhooks.
mutation UpdateAccount($input: InputUpdateAccountDto!) {
updateAccount(input: $input) {
document {
documentNumber
documentType
country
isCompany
others {
documentNumber
documentType
country
}
}
address {
addressStreet
addressCountry
addressNeighborhood
addressCity
addressState
addressZipCode
}
personalInfo {
names
firstLastname
secondLastname
nationality
gender
dob
phoneNumber
activity
}
email,
resultUpdateDocumentNumber
}
}
"variables" :
{
"input": {
"email": "email@domain.com"
"document": {
"documentNumber": "",
"documentType": "",
"country": "",
"others": [
{
"documentNumber": "",
"documentType": "",
"country": ""
}
]
},
"address": {
"addressStreet": "",
"addressCountry": "",
"addressZipCode": "",
"addressCity": "",
"addressState": "",
"addressNeighborhood": ""
},
"personalInfo": {
"names": "",
"firstLastname": "",
"secondLastname": "",
"nationality": "",
"dob": "",
"activity": "",
"gender": "",
"phoneNumber": ""
},
"updateEmail",
"updateDocumentNumber"
"updateDocumentType"
}
}
Create Order
Crea una orden de compra o venta, retorna un UUID para seguimiento (orderId
) y, dependiendo del medio de pago, una URL para realizarlo (providedAction
).
Para llamadas autenticadas sin haber asociado un email
, debe incluirse uno como parámetro para asociar la transacción a un usuario específico.
Necesitas introducir amountIn
o amountOut
, no ambos.
On ramp
Requiere: destinationAddress
, quoteId
.
Off ramp
Requiere: destinationAddress
, quoteId
.
Opcional: email
(obligatorio si no se está autenticado con email), documentNumber
(para facilitar la conciliación bancaria).
Descripción de datos: ver Order Rest
mutation createOrder($input: OrderInput!) {
createOrder(input: $input) {
orderId
amountIn
amountOut
documentNumber
email
metadata
orderId
paymentMethodId
providedAction
providedAddress
quoteId
symbolIn
symbolOut
externalId
}
}
"variables":
{
"input": {
"quoteId": "63e154dbc47d9176668a9af6",
"amountIn": 1.100.000,
"amountOut": 1,
"email": "example@domain.com", #for API calls
"documentNumber": null,
"paymentMethodId": "632d7fe6237ded3a748112cf", # This value corresponds to the _id value returned after calling GetPaymentProviderList
"destinationAddress": "0x40f9bf922c23c43acdad71Ab4425280C0ffBD697", # Will return error if address is invalid
"symbolIn": "CLP",
"symbolOut": "ETH",
"metadata": null,
"externalId": "12A2324A",
"callbackUrl": "https://urlexample/mytracing/",
}
}
Consultar Orden
Retorna información de una order. Recibe un orderId
.
query getOrder($input: GetOrderInput!) {
getOrder(input: $input){
orderId # unique identifier
quoteId # quote id
orderType # currency-crypto for on ramp, crypto-currency for off ramp
symbolIn
symbolOut
amountIn
amountOut
email
exchangeRate
koyweFee
partnerFee
networkFee
status # see the webhooks and states docs for more info
outReceipt
bankAccountId # bank account id for off ramps
metaData
externalId
feesInFiat { #Only if the order has a partnerFee and is greather than 0
koyweFee
netFee
partnerFee
}
feesInUSD { #Only if the order has a partnerFee and is greather than 0
koyweFee #(koyweFee / exchangeRate) truncated to 4 digits after the comma
netFee #(netFee / exchangeRate) truncated to 4 digits after the comma
partnerFee #(partnerFee / exchangeRate) truncated to 4 digits after the comma
}
dates {
confirmationDate
paymentDate
executionDate
deliveryDate
}
destinationAddress # wallet address to send or receive tokens
paymentMethodId
logoIn # logo url for symbolIn
logoOut # logo url for symbolOut
refund { # refund details for off ramps
dates {
startDate
processDate
deliveredDate
}
destinationAddress
transactionReceipt
}
errors { # error details for off ramps
invalidWithdrawalsDetails {
_id
name
bankCode
countryCode
currencySymbol
accountNumber
account
accountType
entityName
}
}
}
}
"variables":
{
"input": {
"orderId": "02a5f0c7-b9bf-48e0-8b5d-190d2e2f7fc1" #Created when calling mutation Order
}
}
Consultar Orden Por ExternalId
Retorna información de una order. Recibe un ExternalId
.
query getOrderByExternalId($input: GetExternalIdOrderInput!) {
getOrderByExternalId(input: $input){
orderId # unique identifier
quoteId # quote id
orderType # currency-crypto for on ramp, crypto-currency for off ramp
symbolIn
symbolOut
amountIn
amountOut
email
exchangeRate
koyweFee
partnerFee
networkFee
status # see the webhooks and states docs for more info
outReceipt
bankAccountId # bank account id for off ramps
metaData
externalId
feesInFiat { #Only if the order has a partnerFee and is greather than 0
koyweFee
netFee
partnerFee
}
feesInUSD { #Only if the order has a partnerFee and is greather than 0
koyweFee #(koyweFee / exchangeRate) truncated to 4 digits after the comma
netFee #(netFee / exchangeRate) truncated to 4 digits after the comma
partnerFee #(partnerFee / exchangeRate) truncated to 4 digits after the comma
}
dates {
confirmationDate
paymentDate
executionDate
deliveryDate
}
destinationAddress # wallet address to send or receive tokens
paymentMethodId
logoIn # logo url for symbolIn
logoOut # logo url for symbolOut
refund { # refund details for off ramps
dates {
startDate
processDate
deliveredDate
}
destinationAddress
transactionReceipt
}
errors { # error details for off ramps
invalidWithdrawalsDetails {
_id
name
bankCode
countryCode
currencySymbol
accountNumber
account
accountType
entityName
}
}
}
}
"variables":
{
"input": {
"externalId": "12A2324A" #Defined when calling mutation Order
}
}
Consultar Ordenes Por txHash
Retorna la información de las ordenes vinculadas al txHash. Recibe un txHash
.
query GetOrderByTxHash($input: GetTxHashOrderInput!) {
getOrderByTxHash(input: $input) {
orderId # unique identifier
quoteId # quote id
orderType # currency-crypto for on ramp, crypto-currency for off ramp
symbolIn
symbolOut
amountIn
amountOut
email
exchangeRate
koyweFee
partnerFee
networkFee
status # see the webhooks and states docs for more info
outReceipt
bankAccountId # bank account id for off ramps
metaData
externalId
feesInFiat { #Only if the order has a partnerFee and is greather than 0
koyweFee
netFee
partnerFee
}
feesInUSD { #Only if the order has a partnerFee and is greather than 0
koyweFee #(koyweFee / exchangeRate) truncated to 4 digits after the comma
netFee #(netFee / exchangeRate) truncated to 4 digits after the comma
partnerFee #(partnerFee / exchangeRate) truncated to 4 digits after the comma
}
dates {
confirmationDate
paymentDate
executionDate
deliveryDate
}
destinationAddress # wallet address to send or receive tokens
paymentMethodId
logoIn # logo url for symbolIn
logoOut # logo url for symbolOut
refund { # refund details for off ramps
dates {
startDate
processDate
deliveredDate
}
destinationAddress
transactionReceipt
}
errors { # error details for off ramps
invalidWithdrawalsDetails {
_id
name
bankCode
countryCode
currencySymbol
accountNumber
account
accountType
entityName
}
}
}
}
"variables":
{
"input": {
"txHash": "0x7bd90e6285dbf85b48f0907288bdbd79ba082bc2c639640ie8234a5867cgd190"
}
}
Lista de órdenes pasadas
Retorna una lista de todas las órdenes asociadas al clientId
o al email
especificado al autenticarse.
pagesize
: Límite de 300, representa la cantidad de respuestas por página.
pageNumber
: Número de páginas a mostrar.
initDate
: Fecha de inicio desde la cual se obtienen los registros. Formato: YYYY-MM-DD. Se incluirán los registros desde esta fecha en adelante, a menos que se especifique un endDate.
endDate
: Fecha de fin hasta la cual se obtienen los registros. Formato: YYYY-MM-DD. Se incluirán solo los registros hasta esta fecha. Si se omite, se retornarán los registros hasta la fecha actual.
query orders($input: PaginationInput!) {
orders(input: $input) {
pagination {
totalCount
pageSize
pageNumber
}
data {
orderId # unique identifier
quoteId # quote id
orderType # currency-crypto for on ramp, crypto-currency for off ramp
symbolIn
symbolOut
amountIn
amountOut
email
exchangeRate
koyweFee
partnerFee
networkFee
status # see the webhooks and states docs for more info
outReceipt
bankAccountId # bank account id for off ramps
metaData
externalId
feesInFiat { #Only if the order has a partnerFee and is greather than 0
koyweFee
netFee
partnerFee
}
feesInUSD { #Only if the order has a partnerFee and is greather than 0
koyweFee #(koyweFee / exchangeRate) truncated to 4 digits after the comma
netFee #(netFee / exchangeRate) truncated to 4 digits after the comma
partnerFee #(partnerFee / exchangeRate) truncated to 4 digits after the comma
}
dates {
confirmationDate
paymentDate
executionDate
deliveryDate
}
destinationAddress # wallet address to send or receive tokens
paymentMethodId
logoIn # logo url for symbolIn
logoOut # logo url for symbolOut
refund { # refund details for off ramps
dates {
startDate
processDate
deliveredDate
}
destinationAddress
transactionReceipt
}
errors { # error details for off ramps
invalidWithdrawalsDetails {
_id
name
bankCode
countryCode
currencySymbol
accountNumber
account
accountType
entityName
}
}
}
}
}
"variables":
{
"input": {
"pageNumber": 100,
"pageSize": 1,
"initDate": "2024-01-01", # opcional
"endDate": "2024-03-01", # opcional
}
}
Agrega txHash para orden Off Ramp
Agrega el txHash a una orden de off ramp. Valida que el hash sea válido para la red de la operación.
mutation SetTxHashOrder($input: TxHashOrderInputDto!) {
setTxHashOrder(input: $input) {
orderId
message
}
}
"variables":
{
"input": {
"txHash": "0xcef85d0123ea3d2a3c4bdfaa6d13019c1b3d2aa6943e6ba853644d443ab83ad7",
"orderId": "ec2af111-acdc-43bb-a0f3-eb1ed1800bbc"
}
}
Reembolso de Orden
Inicia una solicitud de reembolso para una orden off-ramp debido a errores en los detalles de la transferencia de fiat, devolviendo el orderId y el estado de la solicitud.
mutation OffRampRefund($input: OrderRefundInputDto!) {
offRampRefund(input: $input) {
code
data {
orderId
}
message
timestamp
}
}
"variables":
{
"input": {
"orderId": "ec2af111-acdc-43bb-a0f3-eb1ed1800bbc"
}
}
#### Ejemplo de Respuesta de Error
{
"errors": [
{
"message": "Refund already requested",
"status": "INTERNAL_SERVER_ERROR"
}
],
"data": null
}
#### Ejemplo de Respuesta Exitosa
{
"data": {
"offRampRefund": {
"code": "REFUND_000",
"data": {
"orderId": "ec2af111-acdc-43bb-a0f3-eb1ed1800bbc"
},
"message": "ok",
"timestamp": "2024-06-27T22:34:04.685Z"
}
}
}
Reprocesando una orden
Servicio responsable de reprocesar un pedido en caso de errores bancarios. El objetivo es poder finalizar la transacción OFF correspondiente, donde se realiza una transferencia a la cuenta bancaria asociada.
mutation UpdateOrderWithdrawalDetails($input: UpdateBankInTransactionInput!) {
updateOrderWithdrawalDetails(input: $input) {
_id
name
bankCode
countryCode
currencySymbol
accountNumber
account
accountType
entityName
}
}
"variables":
{
"input": {
"orderId": "8bc5b15e-7d9a-4748-b343-cc7d01d20e5f",
"destinationAddress": "665a3d05320291a30b6befef" // New bank account id without errors
}
}
Create Bank Account
Crea una nueva cuenta bancaria y la guarda para futuras operaciones.
opcional: bankCode
, documentNumber
, payoutMethodId (deprecado)
documentNumber
es requerido en el caso de que el usuario no haya hecho el KYC.
mutation createBankAccount($input: BankAccountInput!) {
createBankAccount(input: $input) {
_id
name
bankCode
countryCode
currencySymbol
accountNumber
account
}
}
"variables":
{
"input": {
"bankCode": "SANTANDER",
"accountNumber": "0123123123",
"countryCode": "CHL",
"currencySymbol": "CLP",
"documentNumber": "12345678",
"email": "example@domain.com"
}
}
Validaciones Bancos en Colombia
Para evitar rechazos, debes cumplir con estos requerimientos al crear una cuenta en Colombia:
Bank | Validations |
---|---|
NEQUI | Maximum account number size must be 11 |
DAVIVIENDA | Minimum account number size must be 12 |
BANCOLOMBIA | Maximum account number size must be 11 |
DAVIPLATA | The account number must start with 3 and the minimum size must be 10 |
BANCO CAJA SOCIAL BCSC SA | Maximum account number size must be 11 |
BANCO DE BOGOTÁ | Maximum account number size must be 9 |
SCOTIABANK COLPATRIA SA | Maximum account number size must be 10 |
Warning: El número de cuenta: el campo Bank Account Number debe contener sólo números y ser distinto a 0.
Get Bank Account
Retorna una lista de cuentas bancarias asociadas al usuario, filtrados de acuerdo a countryCode
, currencySymbol
y email
.
query getBankAccount($filters: FiltersBankAccount!) {
getBankAccount(filters: $filters) {
_id
name
bankCode
countryCode
currencySymbol
accountNumber
account
}
}
"variables":
{
"filters": {
"countryCode": "CHL",
"currencySymbol": "CLP"
}
}
Delete Bank Account
Elimina una cuenta bancaria de la lista de cuentas guardadas.
mutation deleteBankAccount($input: DeleteBankAccountInput!) {
deleteBankAccount(input: $input) {
_id
name
bankCode
countryCode
currencySymbol
accountNumber
account
}
}
"variables":
{
"input": {
"_id": "63bd75901ea16ea6e23109b5", #Bank account identifier
"countryCode": "CHL",
"currencySymbol": "CLP"
}
}
Get Bank Info by Country
Retorna una lista con los bancos que son soportados para un countryCode
dado.
query getBankInfoByCountry($countryCode: String!) {
getBankInfoByCountry(countryCode: $countryCode) {
bankCode
name
institutionName
transferCode
}
}
"variables":
{
"countryCode": "CHL"
}