Research & Deep Dives

Supporting material for the DBZ Developer Platform case study — infrastructure details, code samples, error references, regulatory analysis, and success metrics.

Shared Infrastructure

Authentication, response formats, webhooks, and conventions shared across all endpoints

Authentication & Security

All requests are scoped to a project and authenticated via the apikey header.

curl -H "apikey: your_project_api_key" \
     https://api.dbzpay.com/v1/project/balance
Scoped API Keys

Keys can be restricted to specific permissions: payout:read, payout:write, user:read, ledger:write. Production keys should use minimum required scopes.

Key Rotation

POST /v1/api-keys/rotate enables zero-downtime rotation. The old key remains valid for 24 hours after rotation.

IP Allowlisting

Production keys support IP allowlisting to restrict API access to known server addresses.

Webhook Signatures

X-DBZ-Signature header with HMAC-SHA256 of the raw request body using your webhook secret.

Idempotency

Idempotency-Key header on POST requests prevents duplicate operations. Keys are unique per-project and expire after 24 hours.

Base URL

https://api.dbzpay.com/v1

Response Envelope

All responses use a standard envelope:

{
  "success": true,
  "message": "Human-readable status",
  "data": { ... }
}

Error Format

{
  "success": false,
  "message": "Human-readable error description",
  "error": {
    "code": "kyc_required",
    "type": "invalid_request",
    "param": "userId",
    "retryable": false
  }
}

Rate Limiting

All responses include rate limit headers. Default: 1,000 requests/minute per API key.

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 997
X-RateLimit-Reset: 1679529600

Sandbox vs. Production

Sandbox Base URL: https://sandbox.api.dbzpay.com/v1

  • All sandbox object IDs prefixed with test_ (e.g., test_po_m4n5o6p7)
  • Includes test fixtures: pre-verified users, simulated KYC flows
  • Trigger amounts: $9.99 always fails, $1.00 always succeeds

Project Management

MethodEndpointDescription
GET/v1/project/balanceGet your project's current balance (available funds for payouts + prize pools).
GET/v1/project/transactionsProject-level transaction history (top-ups, payouts, fees, escrow holds).

Webhook Management

MethodEndpointDescription
POST/v1/webhooksRegister a webhook endpoint URL. Specify which events to subscribe to.
GET/v1/webhooksList registered webhook endpoints.
PATCH/v1/webhooks/{webhookId}Update a webhook endpoint (URL, events, active/inactive).
DELETE/v1/webhooks/{webhookId}Delete a webhook endpoint.
POST/v1/webhooks/{webhookId}/testSend a test event to verify your endpoint is receiving correctly.

This is an upgrade from DBZ's current per-request callbackUrl pattern to global webhook subscriptions (Stripe-style). The callbackUrl pattern is still supported for backwards compatibility.

Webhook Delivery Guarantees

At-least-once delivery — Events may be delivered more than once. Use the eventId field to deduplicate.
Retry schedule — If your endpoint returns a non-2xx status, DBZ retries with exponential backoff: 5s, 25s, 125s, 625s, 3125s (max 5 retries over ~1 hour).
No ordering guarantee — Events may arrive out of order. Use timestamp and object status to determine current state.
Event replay GET /v1/events returns a log of all events. Filter by type, createdAfter, createdBefore. Use this to replay missed events during outages.
Event TTL — Events are retained for 30 days.

Multi-Currency Support

All monetary amounts use the smallest unit of the specified currency (cents for USD, centimes for EUR). The currency field accepts ISO 4217 codes. Supported at launch: usd, eur.

  • Wallet balances are per-currency (a user can hold both USD and EUR)
  • Cross-currency payouts supported: DBZ handles FX conversion, disclosed via fxRate and fxFee fields
  • Tournament entry fees and prizes must be in a single currency per tournament

Code Samples

Node.js SDK examples for common integration patterns

Create a Payout

import DBZ from '@dbz/node';

const client = new DBZ('your_api_key');

// Create a payout (idempotency key goes in the options, sent as header)
const payout = await client.payouts.create({
  userId: 'usr_a1b2c3d4',
  bankAccountId: 'ba_x9y8z7',
  amount: 5000,
  currency: 'usd',
  description: 'Tournament winnings',
  internalId: 'match_789',
  metadata: { gameId: 'battle-royale-2' }
}, {
  idempotencyKey: 'payout_unique_abc123'
});

console.log(payout.data.id);     // "po_m4n5o6p7"
console.log(payout.data.status); // "pending"

Webhook Handler

import express from 'express';
import DBZ from '@dbz/node';

const app = express();
const client = new DBZ('your_api_key');

// IMPORTANT: Use express.raw() to get the raw body for signature verification
app.post('/webhooks/zbd', express.raw({ type: 'application/json' }), async (req, res) => {
  const signature = req.headers['x-dbz-signature'];

  // req.body is a raw Buffer here — required for HMAC verification
  if (!client.webhooks.verify(req.body, signature)) {
    return res.status(401).send('Invalid signature');
  }

  const { event, data } = JSON.parse(req.body);

  switch (event) {
    case 'payout.completed':
      await markPayoutComplete(data.internalId, data.amount);
      break;
    case 'payout.failed':
      await handlePayoutFailure(data.internalId, data.failureCode);
      break;
    case 'payout.returned':
      // Bank returned funds — re-credit player's in-game balance
      await reverseGamePayout(data.internalId, data.amount);
      break;
  }

  res.status(200).send('OK');
});

Error Codes Reference

Comprehensive error and failure codes across all API endpoints

Payout to Bank — Failure Codes

CodeDescriptionRetryable
insufficient_project_balanceProject doesn't have enough funds to cover payoutYes (after top-up)
kyc_requiredUser hasn't completed required KYC tierNo (redirect user to verify)
kyc_pendingKYC submitted but not yet approvedYes (after approval)
kyc_rejectedKYC verification failedNo
payout_limit_exceededExceeds user's tier limitNo (upgrade tier)
bank_account_not_verifiedBank account linking not completeNo
invalid_bank_accountBank account details invalidNo (re-link)
bank_account_closedDestination account is closedNo (re-link)
account_frozenDBZ flagged account for reviewNo (contact support)
sanctions_matchUser flagged by sanctions screeningNo
duplicate_payoutIdempotency key already usedNo
amount_too_smallBelow minimum payout ($1.00)No
amount_too_largeExceeds single-payout maximumNo (split into multiple)
velocity_limitToo many payouts in time windowYes (after cooldown)
internal_errorDBZ system errorYes (with backoff)

Wallet Loading — Error Codes

CodeDescriptionRetryable
bank_account_not_linkedNo verified bank accountNo (link first)
insufficient_bank_fundsPlayer's bank account has insufficient fundsYes (after player adds funds)
load_limit_exceededDaily/monthly load limit reachedYes (after limit resets)
kyc_requiredKYC tier insufficient for wallet loadingNo (upgrade tier)
wallet_suspendedWallet suspended for reviewNo
duplicate_loadIdempotency collisionNo

Virtual Currency — Error Codes

CodeDescriptionRetryable
insufficient_virtual_balanceUser doesn't have enough virtual currencyNo
conversion_limit_exceededDaily conversion limit reachedYes (after reset)
below_minimum_conversionAmount below minimum conversion thresholdNo
kyc_requiredKYC tier insufficient for conversionNo
currency_not_foundInvalid currency IDNo
reward_pool_depletedProject's reward pool is emptyYes (after top-up)
velocity_limitToo many ledger operations in time windowYes (after cooldown)

Tournaments — Error Codes

CodeDescriptionRetryable
tournament_fullMax players reachedNo
tournament_not_openTournament not accepting entriesNo
insufficient_wallet_balancePlayer can't cover entry feeYes (after wallet load)
region_restrictedPlayer's location not eligible for cash tournamentsNo (offer virtual currency instead)
age_verification_requiredPlayer hasn't verified age 18+No (complete KYC)
already_enteredPlayer already in this tournamentNo
min_players_not_metTournament canceled — not enough entriesNo (auto-refund)
results_mismatchSubmitted rankings don't match entry listNo (resubmit)

Webhook Events Reference

All webhook event types across the platform

Users & Identity

  • user.created — New user registered
  • user.kyc.submitted — Player started verification
  • user.kyc.approved — Verification passed (includes kycTier)
  • user.kyc.rejected — Verification failed (includes reason)
  • user.kyc.tier_upgraded — User qualified for higher tier

Payout to Bank

  • payout.pending — Payout created, awaiting processing
  • payout.processing — Submitted to banking partner
  • payout.in_transit — Funds left DBZ, in transit to bank
  • payout.completed — Funds deposited successfully
  • payout.failed — Payout failed (includes failureCode + failureMessage)
  • payout.canceled — Payout canceled by developer
  • payout.returned — Bank returned the deposit after completion

Wallet Loading

  • wallet.load.pending — Load initiated
  • wallet.load.completed — Funds added to wallet
  • wallet.load.failed — Load failed (includes reason)
  • wallet.balance.updated — Balance changed (any reason)

Checkout

  • checkout.completed — Payment succeeded, credit items to player
  • checkout.failed — Payment failed
  • checkout.refunded — Refund processed
  • checkout.dispute.created — Chargeback initiated
  • checkout.dispute.resolved — Chargeback resolved (won or lost)

Virtual Currency

  • ledger.credited — Virtual currency credited to user
  • ledger.debited — Virtual currency debited from user
  • ledger.transfer.completed — P2P transfer completed
  • conversion.pending — Conversion requested
  • conversion.completed — Conversion processed, wallet credited
  • conversion.failed — Conversion failed (includes reason)

Tournaments

  • tournament.created — Tournament created
  • tournament.entry.confirmed — Player successfully entered
  • tournament.entry.rejected — Entry rejected (ineligible region, insufficient funds, etc.)
  • tournament.started — Tournament now active
  • tournament.results.submitted — Results received, processing prizes
  • tournament.settled — All prizes distributed
  • tournament.canceled — Tournament canceled, refunds issued

Regulatory Landscape

Legal framework for paying players real money

Why This Is Not Gambling

US gambling law requires three elements: Prize + Chance + Consideration. Remove any one element and the activity is not gambling. In the studio-funded rewards model (studio pays players from its own budget, no buy-in from players), there is no consideration — the player pays nothing to participate. This means it fails the gambling test in most jurisdictions.

The model is legally classified as a promotional reward / marketing incentive — similar to a loyalty program. It is not a sweepstakes (rewards are deterministic, not chance-based) and not employment income (though the IRS still taxes it).

Risk Matrix

Area Risk Level Detail DBZ Mitigation
COPPA (minors) HIGH Paying players under 13 requires collecting PII, triggering COPPA. Penalties: $53,088 per violation. Age-gate rewards to 18+. KYC Tier 1+ requires age verification. DBZ handles this in the hosted verification flow.
Tax reporting (1099) MEDIUM Studios must issue 1099-MISC when payouts exceed $2,000/year (2026+ threshold per OBBBA). At $0.25/match, a player needs 8,000 wins to trigger. DBZ collects W-9s during KYC Tier 2 and auto-generates 1099s. Studio never handles tax data.
State restrictions MEDIUM ~9 states restrict skill-based real-money gaming (AZ, AR, CT, DE, LA, MT, SC, SD, TN). These laws mostly target buy-in models, but are untested for studio-funded rewards. DBZ's is-supported-region API enables geo-fencing. Rewards disabled in restricted states automatically.
FTC / dark patterns MEDIUM Advertising "earn real money" when typical earnings are $0.25/match could be deceptive. FTC fined Epic $520M (2022) and miHoYo $20M (2025) for gaming dark patterns. Require studios to display average earnings. DBZ dashboard provides disclosure templates and earnings analytics.
Gambling classification LOW No player buy-in means no "consideration" element. Fails the three-element gambling test. Guaranteed rewards (not chance-based) also remove the "chance" element. API design enforces separation: reward endpoints have no buy-in parameter. Tournament endpoints (with buy-in) use separate compliance flows.
Platform ToS (Apple/Google) LOW Play-to-earn apps (Mistplay, DBZ games, Swagbucks) already exist on both stores. Apple approved DBZ's SaruTobi with Bitcoin microtransactions. Structure as promotional rewards. DBZ's existing App Store precedent de-risks this for new studios.

Tournament Buy-Ins: Different Rules Apply

When players pay to enter a tournament, consideration IS present. The gambling test then hinges on whether outcomes are predominantly skill-based or chance-based:

Model Consideration Chance vs Skill Legal Classification States Allowed
Studio-funded rewards None (studio pays) N/A Promotional reward ~50 states
Skill tournament (buy-in) Yes (player pays entry) Predominantly skill Skill-based gaming ~41 states
Chance-based contest Yes Predominantly chance Gambling (requires license) Varies (heavily regulated)

DBZ's tournament API is designed for skill-based competitions only. The skillCertification field on tournament creation requires studios to attest that game outcomes are predominantly skill-determined. DBZ geo-fences tournaments with buy-ins out of the ~9 restricted states automatically.

Industry Precedent

Company Model Compliance Strategy
Mistplay Points redeemable for gift cards Caps redemptions at $550/year per user (under 1099 threshold). Requires 18+. Not a party to financial transactions.
Swagbucks Points for surveys, games, shopping Issues 1099-NEC at threshold. Collects tax info before allowing further redemptions. Each platform has independent threshold.
Skillz Skill-based tournaments with buy-in Geo-restricts to ~41 states. Skill certification process. No players under 18. Licensed in applicable jurisdictions.
DBZ (current) Lightning micropayments as gameplay rewards Holds US MTLs + EU MiCAR/EMI. Micropayments so small they rarely hit reporting thresholds. 120M+ transactions/year.

Why this strengthens DBZ's value proposition: Compliance is the hardest part of paying players. A studio like 343 Industries doesn't want to deal with 1099s, age-gating, state-by-state geo-fencing, and COPPA audits. DBZ handles all of it behind the API — the studio calls POST /v1/payouts and DBZ manages the regulatory complexity. That's the moat.

Compliance Deep Dive

PII edge cases, payout compliance flow, and developer communication strategy

Payout Compliance Flow

sequenceDiagram participant Dev as Developer Server participant DBZ as DBZ (Internal) participant Bank as Banking Partner Dev->>DBZ: POST /v1/payouts Note over DBZ: 1. Validate KYC tier Note over DBZ: 2. Check sanctions (OFAC/SDN) Note over DBZ: 3. Transaction monitoring Note over DBZ: 4. Velocity checks Note over DBZ: 5. Debit project balance Note over DBZ: If amount >$2,000/yr for user: flag for 1099-NEC DBZ->>Bank: Initiate ACH transfer DBZ-->>Dev: Webhook: payout.processing Bank-->>DBZ: ACH settled DBZ-->>Dev: Webhook: payout.completed

PII Edge Cases & Mitigations

Edge CaseRiskMitigation
Customer support Player contacts the game studio about a failed payout — studio may need info to troubleshoot Support handoff flow: POST /v1/support/tickets creates a DBZ support case linked to a userId. Player is redirected to DBZ's support portal. Developer never handles the PII.
Chargeback disputes Card network sends dispute evidence requests that may contain buyer PII Dispute proxy: DBZ acts as the Merchant of Record for checkout transactions. Developer receives only checkout.dispute.created webhook with dispute ID and amount — no PII.
Tax reporting for developer-funded prizes Who is the "payor" for 1099-NEC purposes when the developer funds tournament prizes? DBZ as payor of record: DBZ is the entity transmitting money to players, making DBZ responsible for tax reporting. Same model Skillz uses.
Player communications Developer wants to email players about payouts — needs at minimum an email address Scoped consent: POST /v1/users accepts email as an optional field the developer provides at registration. This is data the developer already has from their own signup flow.

How We Communicate Compliance to Developers

  1. "Zero PII" badge on every relevant API page — visual indicator that the endpoint keeps developers out of PCI/PII scope.
  2. "Honest edge cases" section — proactively list edge cases with mitigations. Builds trust vs. making claims that fall apart under scrutiny.
  3. Compliance checklist in integration guide:
    • You handle: game logic, reward rules, player UX
    • DBZ handles: identity verification, bank data, sanctions, tax reporting, dispute resolution
    • You never need: PCI certification, OFAC screening, 1099 filing, money transmitter license
  4. "What you don't build" section — explicitly list everything DBZ handles so developers feel confident.
  5. Sandbox with compliance simulation — test KYC flows, trigger failure scenarios, simulate returns, test dispute handling.

Execution Risks

Key risks to the 6-month phased roadmap and mitigation strategies

RiskImpactMitigation
Banking partner compliance review delays Phase 1Entire roadmap shifts rightStart banking partner conversations before engineering begins. Have backup partners identified.
KYC drop-off exceeds benchmarksLow payout adoptionTier 0 (no KYC) lets players engage immediately. Monitor conversion funnel weekly.
Skill gaming legal review blocks cash tournamentsLimited geo coverageVirtual currency tournaments launch everywhere. Cash tournaments roll out state-by-state.
Stripe/Xsolla announces competing productCompetitive pressureAccelerate micropayment support and tournament escrow — features they'd need 12+ months to build.

Fallback Plan

If timeline slips, Phase 1 (payouts) is the non-negotiable MVP. If we're behind, we ship payouts + wallet loading in months 1-4 and push virtual currency + tournaments to months 5-9, extending to a 9-month roadmap. The brief says payout-to-bank is the primary focus — we protect that.

Success Metrics

Measuring DX quality, integration adoption, and commercial outcomes

DX Quality

MetricTargetHow to Measure
Time to first API call<15 minSandbox analytics
Time to first payout (sandbox)<1 hourFunnel tracking
API p99 latency<500msAPM
API error rate (non-client errors)<0.1%Monitoring
Doc page completion rate>80% per guideAnalytics
Support tickets per integration<5 during onboardingZendesk

Integration Adoption

MetricTarget (6mo)How to Measure
Studios with API keys50+Dashboard
Studios live in production15+First production payout
Integration completion rate>40% (signup to live)Funnel
Monthly active integrations12+API call volume
SDK adoption rate>60% of integrations use SDKSDK vs raw API calls

Commercial Outcomes

MetricTarget (6mo)How to Measure
Total payout volume (GMV)$2M+ monthlyLedger
Payout success rate>95%Payout status tracking
Revenue per integration$5K+ monthly avgBilling
Net revenue retention>120%Cohort analysis
Time-to-live<14 days (signup to first prod payout)Funnel