Introduction
About Koywe
- 🌳 What is Koywe
- ✨ Use Cases
Documentation
API Documentation
GraphQL API
Testing URL: https://api-sandbox.koywe.com/graphql
This URL runs an Apollo explorer instance, in case you want to test directly from your browser.
Contact us at hola@koywe.com to get your Credentials or to schedule a personalized tour around the platoform.
Testing: Our testing API works on the different testnets of major blockchains. We have a limited token stock, so we ask your help in not using them all or returning the tokens once the testing is done.
Queries and Mutations
To send requests to the GraphQL API, you always have to send a POST request to the base URL, including the query and any variable as a JSON object. An example to authenticate using CURL (Authorization header included for illustrative purposes):
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"}}}'
In the following examples, we will only write down the JSON object.
Returns a Bearer Token that lasts for 24 hours.
Require: clientId
, secret
Optional: email
. This field associates the transactions and requests to a specific user account.
mutation Authenticate($input: AuthInput!) {
authenticate(input: $input) {
token
}
}
"variables" :
{
"input": {
"clientId": "63631a561f41f8fd18f8c3e0",
"secret": "secretpassword",
"email": "email@domain.com" # optional
}
}
The next two services allows in a directly way the validation of a final user. The first service sends a code to an email specified by the user’s input. This code must be provided as an input to the second service, where the user will be validated and session data will be returned.
Sends a 6-digit code to the email specified.
mutation validateAccount($input: ValidateAccountInput!) {
validateAccount(input: $input) {
_id
}
}
"variables" :
{
"input": {
"email": "email@domain.com",
"clientId": "f87aad3as90fe5489bb5099f"
}
}
Value of code must be retrieved from the email sent by the previous service.
mutation validateCode($input: ValidateCodeInput!) {
validateCode(input: $input) {
token
isIdentify
needVerificate
identity
firstOp
}
}
"variables" :
{
"input": {
"clientId": "40401a5615d9d8fd18f8a0b4",
"code": "940577",
"email": "example@domain.com"
}
}
Returns supported currency-tokens pairs.
Optional: symbol:
Currency symbol to filter pairs. 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
}
}
Returns supported token-currencies pairs.
Optional: 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
}
}
Returns a list of available payment methods with each method’s fees and details for a specific currency.
Require: symbol
. currencyId
.
Optional: clientId
. Payment method list could vary according to this parameter.
query GetPaymentProviderList($input: GetPaymentProviderListInput!) {
getPaymentProviderList(input: $input) {
_id
name
fee
image
description
details
}
}
"variables":
{
"input": {
"symbol": "COP"
"clientId": "f87aad3as90fe5489bb5099f"
"currencyId": "489bb507aad3as90fe0f"
}
}
Rules for Bank Transfer Payments WIRE: For payments made through bank transfer, the following rules have been established:
- Users are allowed to have only one active order per client if they use bank transfer as their payment method. This implies that if a user creates a new order via bank transfer, any previous orders will be canceled, and only the latest order will remain active.
- If a user makes a payment through bank transfer, and the balance is not equal to the order amount, the system will automatically adjust the order. This adjustment is necessary for both payments that are less than the order amount and orders that exceed the specified amount.
Returns a list of available payout providers with each method’s fees and details for a specific currency.
Require: symbol
. currencyId
.
Optional: clientId
. Payment method list could vary according to this parameter.
query GetPayoutProviderList($input: GetPayoutProviderListInput!) {
getPayoutProviderList(input: $input) {
_id
name
fee
image
description
details
}
}
"variables":
{
"input": {
"symbol": "COP"
"clientId": "f87aad3as90fe5489bb5099f"
"currencyId": "489bb507aad3as90fe0f"
}
}
Get Quote
Returns a quote associated with a 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
}
Create Quote
Requires: amountIn
o amountOut
, one or the other. symbolIn
, symbolOut
Optional: paymentMethodId
, clientId
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.
}
}
In all the previous queries, the clientId
parameter will be ignored if there’s a JWT Bearer Token in the headers.
Authenticated Queries
All the following queries require a Bearer Token in the headers:
Authorization: Bearer [token]
These user services include: the creation of new user profiles, the ability to update user information,
the possibility of consulting user details, and a validation function that checks if the user has provided enough personal data to be able to operate.
See Considerations
Check account
It verifies the user account information and determines if it is possible to perform any operation. If any user data is missing, it could be added through the user update service detailed further below.
query CheckAccount($input: InputEmailAccountDto!) {
checkAccount(input: $input) {
canOperate
errors {
field
message
}
accountStatus
nextVerificationDate
}
}
"variables" :
{
"input": {
"email": "email@domain.com"
}
}
Get account
Returns the registered information of the user.
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
Creates a new user account.
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
Updates user data. If an updated email is present, the API validates whether it is a valid email and ensures that another account with that email does not already exist.
If an updated document number or type is present, the API validates that it has a valid format, does not exist on another account, has no executed orders, and initiates an asynchronous validation for mismatching personal data.
The results of the asynchronous validation will be sent to the configured callback. You can find more information in the webhooks section.
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": ""
},
"updateDocumentNumber",
"updateDocumentType",
"updateEmail"
}
}
Create Order
It creates a buy or sell order, returning a UUID to identify it (orderId
) and, depending on the payment method, a URL (providedData
) to proceed to payment. It accepts amounts for crypto o currency, not both.
For authenticated calls without an email, this parameter must be included to associate the transaction to a specific account.
amountIn
or amountOut
must be provided as an input, but not both.
On ramp
Requires: destinationAddress
, quoteId
.
Off ramp
Requires: destinationAddress
, quoteId
.
Optional: email
(required if user is not suthenticated with email), documentNumber (to facilitate bank reconciliation)
Data Description: see 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/",
}
}
Get Order
Returns order information. Receives a 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
}
}
Get Order by ExternalId
Returns order information. Receives a 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
}
}
Get Order(s) by txHash
Returns order(s) information. Receives a 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"
}
}
List of past orders
Returns a list of all orders associated to the clientId
or email
specified when completing the user’s authentication.
pagesize
: This value has a limit of 300, represents the number of responses per page.
pageNumber
: Number of pages shown.
initDate
: The initial date from which records are retrieved. Format: YYYY-MM-DD. Records from this date onwards will be included unless an ‘endDate’ is specified.
endDate
: The end date until which records are retrieved. Format: YYYY-MM-DD. Only records up to this date will be included. If omitted, records up to the current date are returned.
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", # optional
"endDate": "2024-03-01", # optional
}
}
Add txHash Off Ramp order
Add txHash to an off ramp order. Checks hash is valid for the chosen network.
mutation SetTxHashOrder($input: TxHashOrderInputDto!) {
setTxHashOrder(input: $input) {
orderId
message
}
}
"variables":
{
"input": {
"txHash": "0xcef85d0123ea3d2a3c4bdfaa6d13019c1b3d2aa6943e6ba853644d443ab83ad7",
"orderId": "ec2af111-acdc-43bb-a0f3-eb1ed1800bbc"
}
}
Refund Order
Initiate a refund request for an off-ramp order due to errors in the fiat transfer details, returning the orderId and the status of the request.
mutation OffRampRefund($input: OrderRefundInputDto!) {
offRampRefund(input: $input) {
code
data {
orderId
}
message
timestamp
}
}
"variables":
{
"input": {
"orderId": "ec2af111-acdc-43bb-a0f3-eb1ed1800bbc"
}
}
#### Example of Error Response
{
"errors": [
{
"message": "Refund already requested",
"status": "INTERNAL_SERVER_ERROR"
}
],
"data": null
}
#### Example of Successful Response
{
"data": {
"offRampRefund": {
"code": "REFUND_000",
"data": {
"orderId": "ec2af111-acdc-43bb-a0f3-eb1ed1800bbc"
},
"message": "ok",
"timestamp": "2024-06-27T22:34:04.685Z"
}
}
}
Reprocessing order
Service responsible for reprocessing an order in case of banking errors. The objective is to be able to finalize the transaction of converting crypto to the corresponding currency, where a transfer is made to the bank account associated with the order.
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
Creates a new bank account and saves it for future operations.
optional: bankCode
, documentNumber
, payoutMethodId (deprecated)
documentNumber
is required when the user has not been KYC’d.
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"
}
}
Colombian Bank validations
To avoid rejections, you need to take into account the requirements of the destination accounts according to the bank to which you are going to send the payment:
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 |
UALA | Account number must be 15 numeric digits |
Warning: The bankAccountNumber: Bank Account Number field must contain only numbers and be different from 0.
Get Bank Account
Returns a list of bank accounts the users has associated, filtered using countryCode
, currencySymbol
and email
.
query getBankAccount($filters: FiltersBankAccount!) {
getBankAccount(filters: $filters) {
_id
name
bankCode
countryCode
currencySymbol
accountNumber
account
}
}
"variables":
{
"filters": {
"countryCode": "CHL",
"currencySymbol": "CLP",
"email": "test@koywe.com"
}
}
Delete Bank Account
Deletes a Bank Account from the lists of the client’s bank accounts.
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
Returns a list of available banks for a given countryCode
.
query getBankInfoByCountry($countryCode: String!) {
getBankInfoByCountry(countryCode: $countryCode) {
bankCode
name
institutionName
transferCode
}
}
"variables":
{
"countryCode": "CHL"
}