Skip to content

Authentication

All payment-related APIs require identity and signature information in the request to ensure the request is from a valid merchant and has not been tampered with.

Auth method

API Key + Merchant ID + signature:

  • Request header x-api-key: your application API Key
  • Request header x-merchant-id: merchant ID
  • Request header x-signature: signature of the request body (format: sha256=<hex>)
  • Request header x-timestamp: Unix second-level timestamp (unit: seconds); must be valid within 5 minutes or the request will be rejected

Signature flow (overview)

  1. Get current timestamp: Take the current Unix second-level timestamp and use it as the x-timestamp request header (unit: seconds).
  2. Build string to sign: timestamp + "." + raw request body (keep the body as the original JSON string; do not reformat).
  3. Compute HMAC-SHA256: Using your appSecret as the key, compute HMAC-SHA256 over the above string and convert the result to lowercase hex.
  4. Set signature header: Put the signature with prefix sha256= into x-signature (e.g. sha256=a1b2c3...).
  5. Time validity: The server checks that x-timestamp is valid within 5 minutes; requests outside this window are rejected.
  6. Verify signature: The server recomputes the signature with the same rule and compares it with the signature in the request header using a timing-safe comparison.

Signature algorithm

Input to sign

Concatenation rule: timestamp + "." + body

  • timestamp: Same as request header x-timestamp, a second-level Unix timestamp
  • body: Raw request body JSON string (do not reformat or add/remove spaces)

Compute signature

  1. Apply HMAC-SHA256 to the string timestamp + "." + body (key: appSecret) to obtain the binary digest.
  2. Convert the digest to a lowercase hex string.
  3. Prepend sha256= to the signature string and use it as the value of request header x-signature.

Example (Node.js / TypeScript)

typescript
import * as crypto from 'crypto'

// const timestampS = Math.floor(Date.now() / 1000)
function generateSignature(timestamp: number, payload: string, secretKey: string) {
  const signData = `${timestamp}.${payload}`  // String to sign: timestamp.payload
  const signature = crypto
    .createHmac('sha256', secretKey)
    .update(signData, 'utf8')
    .digest('hex')
  return `sha256=${signature}`
}


const timestampS = 1771912638
// Usage: raw request body + appSecret; also send x-api-key and x-merchant-id in request headers
const body = {"amount":100,"currency":"PHP"}
const str = JSON.stringify(body)
const secret = 'sk_live_xupsyzX1RxwUTQU2fjsZXUnOZboLciZfoSppBoiwkcA'
const signature = generateSignature(timestampS, str, secret)
console.log(signature)
// sha256=8535a7d16b35eb1d22822f0a6fc9432509ec07276b7b0dda5f0326e063c34c07

Request headers

HeaderRequiredDescription
Content-TypeYesapplication/json
x-api-keyYesApplication API Key
x-merchant-idYesMerchant ID
x-timestampYesCurrent Unix second-level timestamp (unit: seconds); must be valid within 5 minutes
x-signatureYesSignature from the algorithm above

Crypto scenarios

For cryptocurrency collection scenarios, the request header requirements are the same as other payment-related APIs. You still need to send x-api-key, x-merchant-id, x-timestamp, and x-signature as described above.

Currently, only USDT and USDC tokens are supported.

The cryptocurrency collection flow is as follows:

  1. Apply to Velora separately for the qualification information required for cryptocurrency collection and enable the cryptocurrency collection permission
  2. Configure the callback push URL in the API Key section of the management console
  3. Call Get Wallet Address to get the merchant user's dedicated wallet address
  4. The user transfers funds to the specified wallet address
  5. Receive the cryptocurrency collection callback from Velora
  6. Complete merchant-side business processing

Environments

  • Production: https://api.veloraglobal.com
  • Sandbox: https://api-dev.veloraglobal.com (for integration only; no real funds)

Recommend completing integration in sandbox first, then switching to production.

Next steps