🔏 POS Device Signing (Ed25519)
Every production call toPOST /api/v1/sdk/payments/process must include a cryptographic signature. This prevents spoofing — no request can be fabricated without access to the physical device’s private key.
How Signing Works
Generate a Key Pair on First Launch
When the POS app starts for the first time on a new device, generate an Ed25519 key pair and store the private key in the device’s hardware Keystore or Keychain. Never expose the private key outside the secure enclave.
Register the Device
Send the hex-encoded public key and a stable
device_uuid to TapRails when onboarding the device:Verification (Server Side)
Our backend performs the following checks in sequence:X-Device-SignatureandX-Device-Uuidheaders are present.- The
device_uuidmaps to an ACTIVE registered device for the payment’s merchant. - The Ed25519 signature is verified against the stored public key using the raw request body.
- If any check fails →
401 Unauthorizedis returned. The payment is not processed.
📜 Atomic Financial Ledger
TapRails maintains a double-entry bookkeeping ledger to ensure complete financial integrity. Not a single cent of USDC can be moved without a corresponding audit record.Ledger Entry Structure
Every balance-changing event creates aMerchantTransaction record simultaneously with the payment update, inside a single atomic database transaction:
| Field | Description |
|---|---|
id | Unique ledger entry ID |
type | PAYMENT, DEBIT, CREDIT, WITHDRAWAL |
amount | Amount in USDC (decimal string) |
balance_before | Merchant balance before this event |
balance_after | Merchant balance after this event |
payment_id | Linked payment ID (if applicable) |
status | COMPLETED, PENDING, FAILED |
description | Human-readable description |
created_at | ISO 8601 timestamp |
Querying the Ledger
If a ledger entry creation fails, the entire payment confirmation is rolled back. Payments are never confirmed without a corresponding ledger record.
🛡️ Compliance & Sanction Screening
Every customer wallet is automatically screened for compliance before a payment is confirmed.Screening Process
- Internal Blacklist: The wallet address is checked against TapRails’
BlacklistedWallettable. - External Integration (optional): A hook is available to connect to 3rd-party providers like TRM Labs or Chainalysis for broader sanctions coverage.
- Rejection: If the wallet is flagged →
403 Forbiddenwith error codeCOMPLIANCE_REJECTEDis returned. No funds move.
Merchant Status Enforcement
Merchants that are notACTIVE are blocked from receiving payments at the API level:
| Merchant Status | Payment Request Result |
|---|---|
ACTIVE | ✅ Processed |
PAUSED | ❌ 403 Forbidden |
FROZEN | ❌ 403 Forbidden |
BLACKLISTED | ❌ 403 Forbidden |
SUSPENDED | ❌ 403 Forbidden |
⛓️ High-Availability RPC
TapRails prevents single-provider failures on the Base network by supporting a multi-provider failover rail:- Configuration: Set
BASE_RPC_URLas a comma-separated list of endpoints. - Automatic Failover: Built on Viem’s
fallbacktransport. If the primary RPC is slow or down, the system cycles through backups automatically. - Strict Transfer Decoding: We decode ERC-20
Transferevent logs from the block data (not just transaction receipts) to confirm the exact amount arrived at the correct merchant wallet.
🔔 Webhook Reliability & Signature Verification
Automatic Retries
Failed webhook deliveries are retried with exponential backoff for up to 24 hours. You can also view logs and trigger manual retries via the dashboard.Verifying Signatures
Every TapRails webhook payload includes a signature header:POST /api/v1/dashboard/webhooks/config with { "rollSecret": true }.
