Documentation

Merchant API Reference

Accept USDT payments on BNB Smart Chain. Customers pay to a unique deposit address per invoice; funds settle to your merchant balance.

Base URL

https://api.krovpay.com

Protocol

HTTPS only

Format

JSON


Response Envelope#

Every response is wrapped in a standard envelope with a success boolean and a data payload.

json
{
  "success": true,
  "data": { ... }
}

Paginated responses include a meta field:

json
{
  "success": true,
  "data": [ ... ],
  "meta": {
    "page": 1,
    "per_page": 20,
    "total": 42,
    "total_pages": 3
  }
}

Error responses:

json
{
  "success": false,
  "error": {
    "code": "Bad Request",
    "message": "amount_usdt must be a positive number"
  }
}

Authentication#

The API supports two authentication methods. Use whichever fits your integration.

Option 1 — JWT Bearer Token#

Log in to receive a JWT token and include it on every request. Best for dashboard sessions and server-side calls.

http
Authorization: Bearer <token>
Tokens are short-lived. Obtain a fresh token by calling POST /auth/login.

Option 2 — HMAC API Key#

Best for backend integrations. Each request must include three headers:

HeaderValue
X-API-KeyYour API key (obtained from POST /auth/api-keys)
X-TimestampCurrent UTC time in RFC 3339 format, e.g. 2024-01-15T10:30:00Z
X-SignatureHMAC-SHA256 signature (see below)

Signature construction:

text
message = METHOD + "\n" + PATH + "\n" + TIMESTAMP + "\n" + BODY
signature = HMAC-SHA256(api_secret, message)  # hex-encoded

Example (Python):

python
import hmac, hashlib, time, requests
from datetime import datetime, timezone

api_key    = "pgk_..."
api_secret = "your_api_secret"
timestamp  = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
method     = "POST"
path       = "/invoices"
body       = '{"amount_usdt":"100.00","customer_reference":"order_123"}'

message   = f"{method}\n{path}\n{timestamp}\n{body}"
signature = hmac.new(api_secret.encode(), message.encode(), hashlib.sha256).hexdigest()

resp = requests.post(
    "https://api.krovpay.com/invoices",
    data=body,
    headers={
        "Content-Type": "application/json",
        "X-API-Key":    api_key,
        "X-Timestamp":  timestamp,
        "X-Signature":  signature,
    }
)
Timestamps must be within 5 minutes of the server clock. Requests outside this window are rejected to prevent replay attacks.

Rate Limits#

ScopeLimit
Auth endpoints (/auth/register, /auth/login)10 requests/min per IP
All other endpoints120 requests/min per IP, plus per-merchant limits

Rate-limited requests receive 429 Too Many Requests.


Invoices#

An invoice represents a payment request. Each invoice gets a unique BSC deposit address. Once the customer sends the exact USDT amount and 12 block confirmations pass, the invoice is marked paid and your balance is credited.

Create Invoice#

Requires authentication (JWT or HMAC API key).
POST/invoices
FieldTypeRequiredDescription
amount_usdtstringYesAmount in USDT, e.g. "100.00"
customer_referencestringYesYour internal customer ID/customer phone number
metadataobjectNoAny JSON object — stored and returned as-is
expiry_minutesintegerNoMinutes until expiry (default: 60)
json
{
  "amount_usdt": "100.00",
  "customer_reference": "order_7821",
  "metadata": { "product": "Pro Plan", "user_id": 42 },
  "expiry_minutes": 30
}

Response 201:

json
{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440001",
    "deposit_address": "0xAbCd...",
    "amount_usdt": "100.00",
    "status": "pending",
    "customer_reference": "order_7821",
    "metadata": { "product": "Pro Plan", "user_id": 42 },
    "expires_at": "2024-01-15T11:00:00Z",
    "created_at": "2024-01-15T10:30:00Z"
  }
}

Invoice statuses:

StatusMeaning
pendingAwaiting payment
paidPayment confirmed, balance credited
expiredExpiry time passed without payment
underpaidPayment received but below the required amount
StatusMeaning
400Invalid or missing fields
503Payment processing temporarily unavailable (blockchain monitor is down)

Get Invoice#

Poll this endpoint to check payment status.

GET/invoices/{id}

Response 200: Same structure as the create response above.

StatusMeaning
400Invalid UUID format
404Invoice not found or belongs to another merchant

Deposits#

List Deposits#

Returns on-chain deposit records for your account.

GET/deposits?page=1&per_page=20
ParamDefaultMax
page1
per_page20100

Response 200:

json
{
  "success": true,
  "data": [
    {
      "id": "...",
      "invoice_id": "...",
      "tx_hash": "0xabc123...",
      "amount_usdt": "100.00",
      "confirmations": 12,
      "status": "confirmed",
      "created_at": "2024-01-15T10:40:00Z"
    }
  ],
  "meta": { "page": 1, "per_page": 20, "total": 1, "total_pages": 1 }
}

Health#

No authentication required. Returns the status of all backend workers.

GET/health

Response 200:

json
{
  "success": true,
  "data": {
    "status": "ok",
    "workers": {
      "bsc-watcher": "healthy",
      "sweep-worker": "healthy",
      "withdrawal-worker": "healthy",
      "reconciliation": "healthy",
      "hot-wallet-monitor": "healthy"
    }
  }
}
If bsc-watcher is unhealthy, POST /invoices will return 503 until it recovers.

Integration Checklist#

Follow this checklist to ensure a complete and secure integration.

1

Register and obtain a JWT token (or create an API key for server-to-server use)

2

Configure a webhook URL and save the secret securely

3

Verify webhook signatures on every incoming event

4

Use customer_reference and metadata to link invoices to your orders

5

Use a unique idempotency_key per withdrawal request

6

Poll GET /invoices/{id} as a fallback if webhooks are not received

7

Monitor GET /health to detect platform outages before creating invoices

Ready to start integrating?

Register your merchant account and get your API credentials in minutes.

View Registration Endpoint