DM Champ Docs

Sub-Account Auto-Recharge (Custom Payment Provider)

If you prefer to handle sub-account credit payments through your own provider instead of Stripe (bank transfers, local payment gateways, custom billing systems), the platform exposes a webhook + API pair so you can run the full charge-and-grant loop yourself. The non-technical overview lives on the Agency Accounts page; this page covers the exact webhook payload and the API call you make to grant credits afterwards.

The webhook is only one of the ways automatic top-ups get paid for. If you connected Stripe or PayPal in SaaS Mode, the platform charges the client’s saved card or PayPal account itself and grants the credits, so there is nothing on this page for you to build. Read on only if you want to handle the payment yourself.


The flow at a glance

  1. A sub-account’s credit balance drops below their auto-recharge threshold.
  2. The platform calls your webhook URL with the sub-account details and how many credits they need.
  3. Your server charges the customer through whichever provider you use.
  4. Your server calls the Grant Credits API to add credits to that sub-account.
  5. Your server responds 200 to acknowledge the webhook.

1. Webhook: agency_sub_account_auto_recharge

Configure the webhook URL by clicking SaaS Mode in the main sidebar, choosing Use a Custom Payment Provider Instead (or, once configured, opening the Custom Payment Provider card), and filling in the Auto-Recharge Webhook field.

When it fires

When a sub-account’s credit balance drops below their configured auto-recharge threshold.

Payload

{
  "event": "agency_sub_account_auto_recharge",
  "sub_account_id": "<sub-account-id>",
  "sub_account_email": "customer@example.com",
  "sub_account_name": "John Doe",
  "agency_id": "<agency-id>",
  "credits_requested": 500,
  "current_balance": 42,
  "threshold": 100,
  "price_per_credit_cents": 10,
  "price_per_credit_currency": "usd",
  "total_amount_cents": 5000,
  "timestamp": "2026-04-13T12:00:00.000Z",
  "idempotency_key": "auto_recharge_abc123_1681387200000"
}
Field Description
event Always agency_sub_account_auto_recharge for this webhook.
sub_account_id The unique ID of the sub-account that needs credits.
sub_account_email The sub-account’s email address.
sub_account_name The sub-account’s display name.
agency_id Your agency account’s unique ID.
credits_requested How many credits to grant. This is your configured recharge amount, but if the balance has fallen further below the threshold than that amount would cover, it is automatically raised to whatever is needed to bring the balance back above the threshold in one go. Always charge for (and grant) the credits_requested value from the payload — don’t hard-code your recharge amount.
current_balance The sub-account’s credit balance at the time the webhook was sent.
threshold The balance threshold that triggered the recharge.
price_per_credit_cents Your configured price per credit, in cents.
price_per_credit_currency The currency for the price (e.g., usd).
total_amount_cents The total amount to charge, in cents (credits_requested × price_per_credit_cents).
timestamp When the webhook was sent (ISO 8601 format).
idempotency_key A unique key for this specific recharge request. Use this to prevent granting credits twice if your server receives the same webhook more than once.

Important notes

  • 5-minute cooldown — After a recharge attempt for a sub-account, the platform will not send another webhook for that sub-account for at least 5 minutes, even if their balance drops further. Prevents duplicate charges during processing.
  • Use the idempotency key — Always check idempotency_key before granting credits. If your server crashed after granting credits but before responding, the platform may resend the webhook on the next credit drop.
  • Failures are safe and self-healing — If your webhook URL is unreachable or returns an error, no credits are granted. The platform keeps re-sending the webhook (once per 5-minute cooldown) as long as the sub-account stays below the threshold — it does not require the balance to climb back above the threshold and drop again first. A single missed charge can no longer leave a sub-account permanently un-recharged.
  • Set your recharge amount at or above the threshold — Your configured recharge amount must be greater than or equal to the auto-recharge threshold, so one recharge always restores the balance above the threshold. (If you ever need to fix a sub-account that drifted far below the threshold, the platform tops it up by the full deficit automatically — see credits_requested above.)

2. Grant Credits API

After your server has processed payment, call this endpoint to add the credits to the sub-account.

Request

POST https://api.dmchamp.com/v1/subaccounts/credits
X-API-Key: YOUR_API_KEY
Content-Type: application/json

{
  "email": "customer@example.com",
  "amount": 500,
  "description": "Auto-recharge via webhook"
}
Field Required Description
email Yes The sub-account’s email address (must match an existing sub-account under your agency).
amount Yes The number of credits to grant.
description No A note describing why credits were added (shown in the credit transaction history).

Authentication: Send your API key in a request header — either X-API-Key: YOUR_API_KEY or Authorization: Bearer YOUR_API_KEY. Headers are the recommended way, because a key in the URL ends up in browser history, proxy logs and server access logs. The ?apiKey=YOUR_API_KEY query parameter and an apiKey field in the JSON body also still work, so older integrations keep running unchanged.

Response

{
  "success": true,
  "sub_account_id": "abc123xyz",
  "credits_added": 500,
  "new_balance": 542
}

Tip: Store the idempotency_key from the webhook payload and check it before calling this endpoint. This prevents accidentally granting credits twice if your server receives the same webhook more than once.

What happens to granted credits at the monthly reset

This depends on how the sub-account is set up:

  • Reselling (the sub-account pays you for credits): credits you grant here are recorded as purchased credits and carry over every month. Whatever the sub-account has not spent stays on the balance.
  • Allocation (you give the sub-account a monthly allowance): the balance is refilled to the monthly allowance on the reset date, so anything unspent is not carried over. This is intentional — the allowance is granted fresh each month.

If you want a sub-account’s leftover balance to be added on top of its new monthly allowance instead of replacing it, turn on credit roll-over:

PUT https://api.dmchamp.com/v1/subaccounts/{subAccountUid}/limits
X-API-Key: YOUR_API_KEY
Content-Type: application/json

{
  "usageLimits": { "roll_over_to_next_month": true }
}

If the sub-account — or the plan it is on — also has a roll-over cap or an expiry set, the reset is the moment those apply: the carried-over allowance is trimmed to the months you allow, and allowance left unused for longer than the expiry window is dropped, before the new allowance is added. Credits granted through this endpoint, auto-recharges and the client’s own top-ups are one-time credits and are never trimmed. See Capping what rolls over.


End-to-end example

A typical handler looks like this:

on POST /your-recharge-webhook:
  payload = request.body

  if seen(payload.idempotency_key):
    return 200  // already processed, ack and exit

  charge_result = your_payment_provider.charge(
    email = payload.sub_account_email,
    amount_cents = payload.total_amount_cents,
    currency = payload.price_per_credit_currency,
  )

  if not charge_result.ok:
    return 500  // platform will retry on next balance drop

  api.post("/v1/subaccounts/credits", {
    email = payload.sub_account_email,
    amount = payload.credits_requested,
    description = "Auto-recharge via " + your_provider_name,
  })

  mark_seen(payload.idempotency_key)
  return 200