cred.diy/ docs
    Sign inGet an API key
    All documentation

    Saved Cards & Auto Top-Up - cred.diy API documentation

    Saved Cards & Auto Top-Up

    Keep a buyer's card from a one-time checkout, then buy packs on it later without the buyer present — for example when their balance runs low. A card is saved only when the checkout request sends save_payment_method: true. One card per user; saving again replaces it.

    POSThttps://eutdgemlrpvnxfkkpvlu.supabase.co/functions/v1/hosted-checkout

    One-time checkout that also saves the card for off-session charges. Not allowed with billing: recurring.

    Body parameters

    • user_idstringrequiredYour unique identifier for the customer
    • pricing_tier_idstringrequiredThe pack to buy now
    • save_payment_methodbooleanrequiredSet to true to keep the card
    • user_emailstringCustomer email

    Example request

    curl -X POST "https://eutdgemlrpvnxfkkpvlu.supabase.co/functions/v1/hosted-checkout" \
      -H "x-api-key: sk_live_your_api_key" \
      -H "Content-Type: application/json" \
      -d '{ "user_id": "user_123", "pricing_tier_id": "tier_10k", "save_payment_method": true }'

    Response

    { "url": "https://checkout.stripe.com/...", "session_id": "cs_...", "purchase_id": "..." }
    GET/payment-method

    The user's saved card, or null. Stripe ids are never returned.

    Query parameters

    • user_idstringrequiredExternal user ID

    Example request

    curl "https://eutdgemlrpvnxfkkpvlu.supabase.co/functions/v1/credits-api/payment-method?user_id=user_123" \
      -H "x-api-key: sk_live_your_api_key"

    Response

    { "payment_method": { "brand": "visa", "last4": "4242", "exp_month": 12, "exp_year": 2030, "created_at": "...", "updated_at": "..." } }
    DELETE/payment-method

    Detach the saved card in Stripe and forget it. Send user_id in the JSON body.

    Body parameters

    • user_idstringrequiredExternal user ID

    Example request

    curl -X DELETE "https://eutdgemlrpvnxfkkpvlu.supabase.co/functions/v1/credits-api/payment-method" \
      -H "x-api-key: sk_live_your_api_key" \
      -H "Content-Type: application/json" \
      -d '{ "user_id": "user_123" }'

    Response

    { "deleted": true }
    // no card saved:
    { "deleted": false, "code": "no_saved_payment_method" }
    POST/charge-saved

    Buy a one-time pack on the saved card, off-session. Requires an idempotency key: a retry with the same key returns the first attempt's outcome and never charges twice. Credits are issued before a 200 returns (a credits.issued webhook with billing: auto_topup also fires). requires_action (3-D Secure) cannot be completed without the buyer, so it is a 402 — send them through checkout instead.

    Body parameters

    • user_idstringrequiredExternal user ID with a saved card
    • pricing_tier_idstringrequiredA one_time or both pricing tier
    • idempotency_keystringrequiredOr the Idempotency-Key header; max 255 chars
    • credit_type_idstringWhen the tier applies to several credit types

    Example request

    curl -X POST "https://eutdgemlrpvnxfkkpvlu.supabase.co/functions/v1/credits-api/charge-saved" \
      -H "x-api-key: sk_live_your_api_key" \
      -H "Idempotency-Key: autotopup-user_123-0001" \
      -H "Content-Type: application/json" \
      -d '{ "user_id": "user_123", "pricing_tier_id": "tier_10k" }'

    Response

    // 200 — charged and credited
    { "status": "succeeded", "purchase_id": "...", "payment_intent_id": "pi_...", "credits": 10000, "new_balance": 12500 }
    // 202 — settling; credits arrive by webhook
    { "status": "processing", "purchase_id": "...", "payment_intent_id": "pi_..." }
    // 402 — declined or needs the buyer
    { "status": "failed", "purchase_id": "...", "code": "card_declined", "decline_code": "insufficient_funds", "message": "...", "requires_action": false }
    // 404 — { "error": "...", "code": "no_saved_payment_method" }
    // 409 — "IDEMPOTENCY_KEY_REUSED" (other user) or "saved_payment_method_unusable" (card on a Stripe account the project no longer uses)
    // 502 — "charge_not_started": retry with the SAME key

    Your first credit is one request away.

    Create a project, copy an API key, and issue a credit from your server.