1. Read before you start an integration

1.1. About Service

Bellow you can find scheme representing general flow.

flow 2
You can find detailed description of the flow here.

1.2. Testing of an integration

  • We will review implementation following those requirements

    • Successful order execution using the orderInit method

    • Handle postback response with Order status and process it. (we’ll check it on your sandbox)

  • Test data

    • Access to merchant account https://app-stage.utpay.io. For integration/testing purposes please request a demo account from support team.

To test on behalf of an end customer in the "email" parameter of the order/init request, you should send any of your own emails - it will receive information about the payment status and access to profile which can access end customer (if he wants)
  • Test cards:

Please use any valid card (Visa/MC). We recommend https://www.bincodes.com/random-creditcard-generator/ On sandbox we permit more countries than on production so before release on production please request an actual list of supported countries.

    • Test crypto addresses Testnet crypto addresses should be used on our sandbox

1.3. Environments

2. Authorization

  • Basic

    • Basic authorisation requires to pass two variables in requests:

      • X-AUTH-SID will be provided by utPay support

      • X-AUTH-NONCE should be random string for each request

3. REST API

3.1. Merchant API

3.1.1. Partners orders controller

Init order

Initiate new order for purchase. In case of successful response, you will get URL where to redirect your customer to proceed with transaction.

Wallet address must be unique for each customer or transaction
Curl example
$ curl 'https://app.utpay.io/api/merchant/v1/order/init' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -H 'X-AUTH-SID: xMCvx83...7Gh09' \
    -H 'X-AUTH-NONCE: 123456' \
    -d '{
  "type" : "FIAT_TO_CRYPTO",
  "currency" : "BTC",
  "paymentCurrency" : "EUR",
  "paymentAmount" : 100.0,
  "externalId" : "some-external-id",
  "address" : "mmWjhvLvEzF8jpQC7jfygVH2zx7YkYyzqS",
  "email" : "[email protected]",
  "postbackUrl" : "https://merchant.com/utPay/callback",
  "successUrl" : "https://merchant.com/utPay/success",
  "failUrl" : "https://merchant.com/utPay/fail",
  "invoiceId" : "72147184djf384",
  "countryOfResidence" : "PT"
}'
HTTP Request
POST /api/merchant/v1/order/init HTTP/1.1
Content-Type: application/json;charset=UTF-8
X-AUTH-SID: xMCvx83...7Gh09
X-AUTH-NONCE: 123456
Content-Length: 454
Host: app.utpay.io

{
  "type" : "FIAT_TO_CRYPTO",
  "currency" : "BTC",
  "paymentCurrency" : "EUR",
  "paymentAmount" : 100.0,
  "externalId" : "some-external-id",
  "address" : "mmWjhvLvEzF8jpQC7jfygVH2zx7YkYyzqS",
  "email" : "[email protected]",
  "postbackUrl" : "https://merchant.com/utPay/callback",
  "successUrl" : "https://merchant.com/utPay/success",
  "failUrl" : "https://merchant.com/utPay/fail",
  "invoiceId" : "72147184djf384",
  "countryOfResidence" : "PT"
}
Request headers
Name Description

X-AUTH-SID

Authorization SID value

X-AUTH-NONCE

Authorization nonce value

Request parameters
Path Type Optional Description

type

String

false

Order type: FIAT_TO_CRYPTO

currency

String

false

Order crypto currency

paymentAmount

Number

true

Payment amount nominated in payment currency

paymentCurrency

String

true

If you’ll pass this parameter customer won’t be able change payment currency on UI

externalId

String

false

Unique ID of transaction on merchant platform

address

String

true

Crypto Wallet address (valid Crypto address).

email

String

true

Customer email address. If field will be provided, customer will see it on UI

postbackUrl

String

true

You can provide us global URL where we should send data via postback

successUrl

String

true

URL where to redirect customer after successful payment. (you can provide us URL which will be used for each order)

failUrl

String

true

URL where to redirect customer after failed payment. (you can provide us URL which will be used for each order)

invoiceId

String

true

Invoice ID of transaction (you can use this parameter if it is enabled for your API key)

countryOfResidence

String

true

Default value of customer’s Country of residence

The list of order types can be viewed in the order types table.
Success HTTP response
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 838

{
  "success" : true,
  "timestamp" : 1689950567320,
  "data" : {
    "id" : 1000,
    "createdAt" : 1689950567319,
    "updatedAt" : 1689950567319,
    "externalId" : "some-external-id",
    "currency" : "BTC",
    "address" : "mmWjhvLvEzF8jpQC7jfygVH2zx7YkYyzqS",
    "unDomain" : "example.domain",
    "paymentCurrency" : "EUR",
    "paymentCurrencyLocked" : true,
    "paymentAmountLocked" : false,
    "acceptedById" : 1,
    "status" : "NEW",
    "postbackUrl" : "https://merchant.com/utPay/callback",
    "url" : "https://app.utpay.io/order/1000/transaction?pid=1000",
    "successUrl" : "https://merchant.com/utPay/success",
    "failUrl" : "https://merchant.com/utPay/fail",
    "type" : "FIAT_TO_CRYPTO",
    "kycInvolved" : false,
    "invoiceId" : "72147184djf384",
    "mId" : "356a192b7913b04c54574d18c28d46e6395428ab"
  }
}
Search order

Find order by it’s ID.

Curl example
$ curl 'https://app.utpay.io/api/merchant/v1/order/find' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -H 'X-AUTH-SID: xMCvx83...7Gh09' \
    -H 'X-AUTH-NONCE: 123456' \
    -d '{
  "id" : 1000
}'
HTTP Request
POST /api/merchant/v1/order/find HTTP/1.1
Content-Type: application/json;charset=UTF-8
X-AUTH-SID: xMCvx83...7Gh09
X-AUTH-NONCE: 123456
Content-Length: 17
Host: app.utpay.io

{
  "id" : 1000
}
Request headers
Name Description

X-AUTH-SID

Authorization SID value

X-AUTH-NONCE

Authorization nonce value

Success HTTP response
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 736

{
  "success" : true,
  "cursor" : 1000,
  "left" : 0,
  "timestamp" : 1689950565916,
  "data" : [ {
    "id" : 1000,
    "createdAt" : 1689950565912,
    "updatedAt" : 1689950565912,
    "externalId" : "some-external-id1",
    "amount" : 1,
    "currency" : "BTC",
    "address" : "mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef",
    "unDomain" : "example.domain",
    "paymentCurrency" : "EUR",
    "paymentCurrencyLocked" : true,
    "paymentAmountLocked" : false,
    "paymentAmount" : 7900.0,
    "status" : "EXECUTED",
    "blockchainTxId" : "4c8af628c15d4e8bf0505f29ee2dde0fec9682e947d750b8da60e4e66b69e79e",
    "conversionRate" : 7877.6,
    "type" : "FIAT_TO_CRYPTO",
    "kycInvolved" : false,
    "invoiceId" : "72147184djf384"
  } ]
}
Response fields
Path Type Description

success

Boolean

Request status

error

Object

Error information

cursor

Number

Page cursor

left

Number

Missed elements count

timestamp

Number

Response timestamp

data

Array

Response data

data[].id

Number

Unique Order identifier

data[].createdAt

Number

Order creation time

data[].updatedAt

Number

Order update time

data[].amount

Number

Order amount in crypto

data[].currency

String

Order crypto currency

data[].address

String

Wallet address

data[].unDomain

String

Unstoppable domain

data[].paymentCurrency

String

Payment currency

data[].paymentAmount

Number

Payment amount

data[].externalId

String

Order external (merchant) identifier

data[].status

String

Order status

data[].blockchainTxId

String

Order blockchain transaction identifier

data[].postbackUrl

String

Postback URL (if exists)

data[].postbackSentAt

Number

Postback sent time

data[].postbackStatus

String

Postback sent status: EXECUTED or FAILED

data[].sendAmount

Number

Send amount value

data[].paymentCurrencyLocked

Boolean

End customer won’t be able to change payment currency during purchase process.

data[].paymentAmountLocked

Boolean

Order crypto amount will be recalculated instead of payment amount if rate changed since order init.

data[].requestedById

Number

Merchant identifier

data[].acceptedById

Number

Customer identifier

data[].conversionRate

Number

Conversion rate value

data[].error

String

Order error message

data[].type

String

Order type

data[].kycInvolved

Boolean

Is KYC invloved

data[].invoiceId

String

Invoice ID of transaction

The list of statuses can be viewed in the order statuses table.
List orders
Curl example
$ curl 'https://app.utpay.io/api/merchant/v1/order/list' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -H 'X-AUTH-SID: xMCvx83...7Gh09' \
    -H 'X-AUTH-NONCE: 123456' \
    -d '{
  "cursor" : 0,
  "limit" : 5,
  "filter" : {
    "dateFrom" : 46800000,
    "dateTo" : 1690555367615,
    "paymentCurrency" : [ "EUR" ],
    "status" : [ "EXECUTED" ]
  }
}'
HTTP Request
POST /api/merchant/v1/order/list HTTP/1.1
Content-Type: application/json;charset=UTF-8
X-AUTH-SID: xMCvx83...7Gh09
X-AUTH-NONCE: 123456
Content-Length: 175
Host: app.utpay.io

{
  "cursor" : 0,
  "limit" : 5,
  "filter" : {
    "dateFrom" : 46800000,
    "dateTo" : 1690555367615,
    "paymentCurrency" : [ "EUR" ],
    "status" : [ "EXECUTED" ]
  }
}
Request headers
Name Description

X-AUTH-SID

Authorization SID value

X-AUTH-NONCE

Authorization nonce value

Success HTTP response
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 797

{
  "success" : true,
  "cursor" : 123456,
  "hasNext" : false,
  "timestamp" : 1689950567753,
  "data" : [ {
    "id" : 123456,
    "createdAt" : 1689950567752,
    "updatedAt" : 1689950567752,
    "amount" : 1,
    "currency" : "BTC",
    "address" : "mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef",
    "unDomain" : "example.domain",
    "paymentCurrency" : "EUR",
    "paymentCurrencyLocked" : true,
    "paymentAmountLocked" : false,
    "paymentAmount" : 70000,
    "acceptedById" : 1,
    "status" : "ACCEPTED",
    "url" : "https://app.utpay.io/order/123456/transaction?pid=1000",
    "conversionRate" : 1.11,
    "type" : "FIAT_TO_CRYPTO",
    "kycInvolved" : false,
    "invoiceId" : "72147184djf384",
    "finalPaymentAmount" : 70000,
    "mId" : "356a192b7913b04c54574d18c28d46e6395428ab"
  } ]
}

3.1.2. Merchant settings controller

Get currencies list

Currencies which are available for purchase.

Curl example
$ curl 'https://app.utpay.io/api/merchant/v1/settings/currency' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -H 'X-AUTH-SID: xMCvx83...7Gh09' \
    -H 'X-AUTH-NONCE: 123456' \
    -d '{
  "country" : "US"
}'
HTTP Request
POST /api/merchant/v1/settings/currency HTTP/1.1
Content-Type: application/json;charset=UTF-8
X-AUTH-SID: xMCvx83...7Gh09
X-AUTH-NONCE: 123456
Content-Length: 22
Host: app.utpay.io

{
  "country" : "US"
}
Request headers
Name Description

X-AUTH-SID

Authorization SID value

X-AUTH-NONCE

Authorization nonce value

Success HTTP response
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 582

{
  "success" : true,
  "timestamp" : 1689950548032,
  "data" : [ {
    "currency" : "BTC",
    "display" : "BTC",
    "type" : "CRYPTO",
    "enabled" : true,
    "depositMin" : 0.003,
    "depositMax" : 1.0,
    "withdrawalMin" : 0.003,
    "withdrawalMax" : 1.0,
    "addressValidator" : "BTC",
    "precision" : 8
  }, {
    "currency" : "ETH",
    "display" : "ETH",
    "type" : "CRYPTO",
    "enabled" : true,
    "depositMin" : 0.15,
    "depositMax" : 10.0,
    "withdrawalMin" : 0.15,
    "withdrawalMax" : 10.0,
    "addressValidator" : "ETH",
    "precision" : 6
  } ]
}
The list of types can be viewed in the currency types table.
Set merchant postback URL
Curl example
$ curl 'https://app.utpay.io/api/merchant/v1/settings/postback' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -H 'X-AUTH-SID: xMCvx83...7Gh09' \
    -H 'X-AUTH-NONCE: 123456' \
    -d '{
  "url" : "https://merchant.com/utPay/callback",
  "kycUrl" : "https://merchant.com/utPay/kycCallback",
  "kycNotification" : false
}'
HTTP Request
POST /api/merchant/v1/settings/postback HTTP/1.1
Content-Type: application/json;charset=UTF-8
X-AUTH-SID: xMCvx83...7Gh09
X-AUTH-NONCE: 123456
Content-Length: 135
Host: app.utpay.io

{
  "url" : "https://merchant.com/utPay/callback",
  "kycUrl" : "https://merchant.com/utPay/kycCallback",
  "kycNotification" : false
}
Request headers
Name Description

X-AUTH-SID

Authorization SID value

X-AUTH-NONCE

Authorization nonce value

Request parameters
Path Type Optional Description

url

String

false

Postback URL

kycUrl

String

false

Postback KYC notification URL

kycNotification

Boolean

false

Enabled KYC change status notification

Success HTTP response
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 808

{
  "success" : true,
  "timestamp" : 1689950548947,
  "data" : {
    "postback" : {
      "url" : "https://merchant.com/utPay/callback",
      "publicKey" : "AAAAB3NzaC1yc2EAAAADAQABAAABgQC2tsj5BbjaGvIBAHXfMd6CtxhQEp8TY13ciUSSXahSsVvxchFeTPu1ol6iIle/E6Wd+ywpceyRpusOSuhn519tcYGaBy/ecdzUIOLe9OsNZd+1Q2q7zqriuQ93jAM+H4PsLW9GGN24hGUJvEAqf38bJrzg0st6XTJK6mulOn509omOQmud0H1GhfL3/ifjOsaG7sDQLa1BM+zt8x4kMIsZ61AW8PRX+g5PG+n3AYiSbhgD1A7eRaB+yMnS9AgabUNAwCq2Aj6mX3iJd/0EeEhO1YDouYJgmAUXTR8S4dgMiYC0nR+RiQESIMKl61YUGPORI51gYfxRsA+beBOK86qjRhllVOMuoc+kppr01sIQXN/Vd87XNs0hiH5agESyVn09/jmxsogWy19wHEbA8aIxNr9BIFw+sNdYHSFeZSDl5uEJ8eSX1pLSbLL6qey3T3VW/gsq5sVwMYjJwgW4kMIlcwDGiIeF59wx7O/9TdNL+THzlCQfu+zU6T1pEsoax3U=",
      "kycNotification" : false,
      "kycUrl" : "https://merchant.com/utPay/kycCallback"
    }
  }
}
Set order success URL
Curl example
$ curl 'https://app.utpay.io/api/merchant/v1/settings/successUrl' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -H 'X-AUTH-SID: xMCvx83...7Gh09' \
    -H 'X-AUTH-NONCE: 123456' \
    -d '{
  "url" : "https://merchant.com/utPay/success"
}'
HTTP Request
POST /api/merchant/v1/settings/successUrl HTTP/1.1
Content-Type: application/json;charset=UTF-8
X-AUTH-SID: xMCvx83...7Gh09
X-AUTH-NONCE: 123456
Content-Length: 50
Host: app.utpay.io

{
  "url" : "https://merchant.com/utPay/success"
}
Request headers
Name Description

X-AUTH-SID

Authorization SID value

X-AUTH-NONCE

Authorization nonce value

Request parameters
Path Type Optional Description

url

String

false

Success URL

Success HTTP response
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 127

{
  "success" : true,
  "timestamp" : 1689950544211,
  "data" : {
    "successUrl" : "https://merchant.com/utPay/success"
  }
}
Set order fail URL
Curl example
$ curl 'https://app.utpay.io/api/merchant/v1/settings/failUrl' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -H 'X-AUTH-SID: xMCvx83...7Gh09' \
    -H 'X-AUTH-NONCE: 123456' \
    -d '{
  "url" : "https://merchant.com/utPay/fail"
}'
HTTP Request
POST /api/merchant/v1/settings/failUrl HTTP/1.1
Content-Type: application/json;charset=UTF-8
X-AUTH-SID: xMCvx83...7Gh09
X-AUTH-NONCE: 123456
Content-Length: 47
Host: app.utpay.io

{
  "url" : "https://merchant.com/utPay/fail"
}
Request headers
Name Description

X-AUTH-SID

Authorization SID value

X-AUTH-NONCE

Authorization nonce value

Request parameters
Path Type Optional Description

url

String

false

Fail URL

Success HTTP response
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 121

{
  "success" : true,
  "timestamp" : 1689950549402,
  "data" : {
    "failUrl" : "https://merchant.com/utPay/fail"
  }
}

3.1.3. Merchant tools controller

Convert fiat assets to crypto

Convert amount from FIAT currency to CRYPTO currency for future order init.

Curl example
$ curl 'https://app.utpay.io/api/merchant/v1/tools/convert' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -H 'X-AUTH-SID: xMCvx83...7Gh09' \
    -H 'X-AUTH-NONCE: 123456' \
    -d '{
  "fromCurrency" : "EUR",
  "toCurrency" : "BTC",
  "paymentAmount" : 10000
}'
HTTP Request
POST /api/merchant/v1/tools/convert HTTP/1.1
Content-Type: application/json;charset=UTF-8
X-AUTH-SID: xMCvx83...7Gh09
X-AUTH-NONCE: 123456
Content-Length: 79
Host: app.utpay.io

{
  "fromCurrency" : "EUR",
  "toCurrency" : "BTC",
  "paymentAmount" : 10000
}
Request headers
Name Description

X-AUTH-SID

Authorization SID value

X-AUTH-NONCE

Authorization nonce value

Success HTTP response
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 74

{
  "success" : true,
  "timestamp" : 1689950558620,
  "data" : 1.157943
}
Convert crypto assets to fiat

Convert amount from CRYPTO currency to FIAT currency for future order init.

Curl example
$ curl 'https://app.utpay.io/api/merchant/v1/tools/convert' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -H 'X-AUTH-SID: xMCvx83...7Gh09' \
    -H 'X-AUTH-NONCE: 123456' \
    -d '{
  "fromCurrency" : "EUR",
  "toCurrency" : "BTC",
  "amount" : 0.013
}'
HTTP Request
POST /api/merchant/v1/tools/convert HTTP/1.1
Content-Type: application/json;charset=UTF-8
X-AUTH-SID: xMCvx83...7Gh09
X-AUTH-NONCE: 123456
Content-Length: 72
Host: app.utpay.io

{
  "fromCurrency" : "EUR",
  "toCurrency" : "BTC",
  "amount" : 0.013
}
Request headers
Name Description

X-AUTH-SID

Authorization SID value

X-AUTH-NONCE

Authorization nonce value

Success HTTP response
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 53

{
  "success" : true,
  "timestamp" : 1689950557704
}

5. Annex

5.1. Postback example

Here you can find an example of a postback which is sent from utPay to the URL which you have to provide in orderInit request

{
    "id": 31928166809894,
    "createdAt": 1611310347398,
    "updatedAt": 1611310604965,
    "externalId": "25f19c42-3335-4b8f-9350-839ac68c6dfb",
    "amount": 0.7,
    "currency": "BTC",
    "address": "2N72VXSb9hPLzVHkFM39aREB3ph3NGtJHuq",
    "paymentCurrency": "EUR",
    "paymentCurrencyLocked": true,
    "paymentAmountLocked": false,
    "paymentAmount": 19596.17,
    "requestedById": 10179680225734,
    "acceptedById": 31926285357326,
    "acceptedByEmail": "[email protected]",
    "status": "EXECUTED",
    "type": "FIAT_TO_CRYPTO",
    "maskedCardNumber": "",
    "sendAmount": 0.6,
    "blockchainTxId": "10179680225738",
    "blockchainTxIds": ["10179680225738"],
    "chain": "AVALANCHE",
    "kyc": {
        "applicationId": 89472872447892,
        "updatedAt": 1611310604965,
        "status": "SUCCESS"
    }
}

If you would like to validate our postback please request Public Key from our Support teeam. With provided Key you will be able to verify that you have received a postback from utPay. Here is an example of a validation

const crypto = require("crypto");
// X-SIGN header value from postback response
const signature = ''
// Body of the payload as is
const body = ''
// Public key received from utPay team
const publicKey = ''
// Convert to PEM for nodejs crypto: add prefix, posfix and split by 64 symbols. It doesn't need for java, golang etc.
const publicKeyPem = `-----BEGIN PUBLIC KEY-----
${publicKey.replace(/(.{64})/g,"$1\n")}
-----END PUBLIC KEY-----`
const verifier = crypto.createVerify('RSA-SHA256');
verifier.update(body);
const isValid = verifier.verify(publicKeyPem, signature, 'base64');
console.log("isValid? ", isValid);

5.2. Currencies types

Table 3. Currency types
Type Description

FIAT

A currency without intrinsic value that has been established as money, often by government regulation

CRYPTO

a digital asset designed to work as a medium of exchange that uses strong cryptography to secure financial transactions, control the creation of additional units, and verify the transfer of assets

5.3. utPay IP addresses

Sandbox IP address

95.217.104.219

Production IP addresses

34.90.55.199, 34.91.26.119, 34.141.142.236