विषय पर बढ़ें

Brand Partner API

mintbot orders बनाने, उनका status poll करने, और lifecycle events receive करने के लिए एक छोटा, predictable REST API। JSON in, JSON out। Bearer-token auth। Idempotent writes। Signed webhooks।

API access dashboard Webhooks पर जाएँ


एक नज़र में

Base URL https://mint.mintbot.ai/api/v1
Auth `Authorization: Bearer ***
Idempotency हर POST पर Idempotency-Key: <uuid>
Content type application/json
Rate limit 120 req / 60 s per partner
Webhooks HMAC-SHA256 से signed, 7 बार तक retry

Authentication

हर request Authorization header में partner API key भेजती है। Key dashboard में generate या rotate करें।

Authorization: Bearer mo_liv...xxxx
Content-Type: application/json

Rotation में grace window नहीं है

Key rotate करने से previous key atomically revoke हो जाती है। Rotate पर click करने से पहले अपने config में value swap करने की planning करें।

Idempotency

हर POST के लिए Idempotency-Key header चाहिए। अलग-अलग request के लिए कोई भी UUID चलेगा।

  • हम response को 24 hours तक cache करते हैं। Same key के साथ retry original response को Idempotent-Replay: true के साथ replay करता है।
  • Same key को different body के साथ reuse करने पर 409 idempotency_key_mismatch return होता है।

Orders

Order बनाएँ

POST /orders

Order बनाता है और Stripe Checkout URL return करता है। Payment confirm होते ही mintbot agent provision करता है और partner-cut revenue event automatically record हो जाता है।

Request

{
  "tier": "s1",
  "duration_months": 1,
  "credit_usd": 10,
  "language": "en",
  "external_id": "your-side-id",
  "success_url": "https://your.app/thanks?id={ORDER_ID}",
  "cancel_url":  "https://your.app/cart",
  "webhook_url": "https://your.app/mintbot-webhook"
}
tier
trial, s1, s2, s4 में से एक।
duration_months
सर्वर जीवनकाल कैलेंडर महीनों में। 1, 3, या 12 में से एक होना चाहिए।
credit_usd
Optional. Order के साथ bundled pre-funded chat credit।
language
Optional. Stripe Checkout locale और welcome-email language को affect करता है।
external_id
Optional. हर webhook और order response में वापस echo होता है — इसका इस्तेमाल mintbot orders को अपने system की rows से जोड़ने के लिए करें।
success_url · cancel_url
Stripe Checkout return URLs। {ORDER_ID} server-side substitute होता है।
webhook_url
Optional. Partner-level webhook URL का per-order override।

Response — 201 Created

{
  "id": 42,
  "tier": "s1",
  "duration_months": 1,
  "credit_usd": 10,
  "amount_cents": 1200,
  "currency": "usd",
  "status": "awaiting_payment",
  "checkout_url": "https://checkout.stripe.com/c/pay/cs_test_…",
  "panel_url": null,
  "expires_at": null,
  "language": "en",
  "external_id": "your-side-id",
  "created_at": "2026-05-16 09:58:00",
  "paid_at": null
}

Example

curl -X POST https://mint.mintbot.ai/api/v1/orders \
  -H "Authorization: Bearer *** \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "tier": "s1",
    "duration_months": 1,
    "credit_usd": 10,
    "success_url": "https://your.app/thanks?id={ORDER_ID}",
    "cancel_url":  "https://your.app/cart"
  }'
import os, uuid, requests

r = requests.post(
    "https://mint.mintbot.ai/api/v1/orders",
    headers={
        "Authorization": f"Bearer {os.environ['MINTBOT_API_KEY']}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "tier": "s1",
        "duration_months": 1,
        "credit_usd": 10,
        "success_url": "https://your.app/thanks?id={ORDER_ID}",
        "cancel_url":  "https://your.app/cart",
    },
    timeout=10,
)
r.raise_for_status()
order = r.json()
redirect_to = order["checkout_url"]

Order लें

GET /orders/{id}

एक single order को उसके mintbot id से fetch करता है। POST /orders जैसी same shape return करता है।

curl https://mint.mintbot.ai/api/v1/orders/42 \
  -H "Authorization: Bearer ***

Orders list करें

GET /orders

Cursor-paginated list, newest first।

Query parameters

status
Optional. awaiting_payment, completed, deployed, deploy_failed, या expired से filter करें।
cursor
Optional. Continue करने के लिए previous page से next_cursor pass करें।

Response

{
  "items": [ /* OrderResponse … */ ],
  "next_cursor": "37"
}

जब और pages नहीं होते, next_cursor null होता है।


Order renew करें

POST /orders/{id}/renew

Existing agent को another duration_months के लिए extend करता है। Infra-only — fresh chat credit bundled नहीं होता। New order id और fresh Stripe Checkout URL return करता है।

Request

{
  "duration_months": 1,
  "external_id": "your-side-id",
  "success_url": "https://your.app/thanks?id={ORDER_ID}",
  "cancel_url":  "https://your.app/account"
}

Revenue

Revenue पढ़ें

GET /revenue

Totals plus latest 200 ledger events।

Query parameters

include_paid
Optional, default true. सिर्फ वे events देखने के लिए false set करें जिनका payout अभी नहीं हुआ है।

Response

{
  "currency": "usd",
  "gross_cents": 12000,
  "partner_cut_cents": 2000,
  "mintbot_cut_cents": 10000,
  "unpaid_cents": 800,
  "events": [
    {
      "id": 7,
      "order_id": 42,
      "kind": "order_paid",
      "gross_cents": 1200,
      "partner_cut_cents": 200,
      "mintbot_cut_cents": 1000,
      "currency": "usd",
      "created_at": "2026-05-16 09:58:00",
      "payout_id": null,
      "payout_at": null
    }
  ]
}

Partner profile

Profile लें

GET /partner

आपकी partner profile और unpaid balance echo करता है — अपने admin UI के अंदर earnings दिखाने के लिए handy है, उन्हें खुद store किए बिना।

Response

{
  "id": 12,
  "email": "you@kliendifirma.com",
  "pricing_currency": "usd",
  "balance_unpaid_cents": 800,
  "webhook_url": "https://your.app/mintbot-webhook",
  "api_key_prefix": "mo_live_a12b"
}

Webhooks

जब किसी order के साथ कुछ होता है, हम आपके configured webhook URL पर signed JSON event POST करते हैं।

Event types

Event कब fire होता है
order.created Stripe Checkout session minted, payment का इंतज़ार।
order.paid Stripe ने payment confirm किया। Revenue event recorded।
order.cancelled Order timed out या explicitly cancelled।
agent.provisioning_started इस order के लिए deploy pipeline शुरू हुई।
agent.ready Deploy successful। Payload में panel_url और expires_at हैं।
agent.failed Deploy pipeline errored। टूटे हुए step के लिए error field check करें।
agent.expired Agent TTL elapsed। Partner POST /orders/{id}/renew से renew कर सकता है।

Delivery & retries

  • Exponential schedule पर 7 attempts तक: 0s, 30s, 2m, 10m, 1h, 6h, 24h
  • Last attempt के बाद delivery exhausted mark हो जाती है और retry बंद हो जाता है।
  • Acknowledge करने के लिए 10 seconds के अंदर 2xx status के साथ respond करें।

Request headers

Content-Type: application/json
User-Agent: mintbot-webhook/1.0
X-Mintbot-Signature: t=<unix_ts>,v1=<hex_hmac_sha256>
X-Mintbot-Event-Id: evt_42_order.paid_1747371234567
X-Mintbot-Event-Type: order.paid

Sample payload — order.paid

{
  "id": 42,
  "tier": "s1",
  "duration_months": 1,
  "credit_usd": 10,
  "amount_cents": 1200,
  "currency": "usd",
  "status": "completed",
  "external_id": "your-side-id",
  "paid_at": "2026-05-16 10:02:14"
}

Signature verify करना

Signature HMAC-SHA256(secret, "{timestamp}.{raw_body}") है। हमेशा raw request body verify करें — parsed JSON को re-serialise करने से comparison टूट जाएगा।

import hmac, hashlib, time

def verify(secret: str, body: bytes, header: str, tolerance: int = 300) -> bool:
    try:
        ts_part, v1_part = header.split(",", 1)
        ts  = int(ts_part.split("=", 1)[1])
        sig = v1_part.split("=", 1)[1]
    except Exception:
        return False
    if abs(int(time.time()) - ts) > tolerance:
        return False
    expected = hmac.new(
        secret.encode(),
        f"{ts}.".encode() + body,
        hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest(expected, sig)
const crypto = require("crypto");

function verify(secret, rawBody, header, toleranceSec = 300) {
  const [tsPart, v1Part] = header.split(",");
  const ts  = Number(tsPart.split("=")[1]);
  const sig = v1Part.split("=")[1];
  if (Math.abs(Date.now() / 1000 - ts) > toleranceSec) return false;
  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${ts}.`)
    .update(rawBody)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected, "hex"),
    Buffer.from(sig, "hex"),
  );
}

Idempotent receivers

X-Mintbot-Event-Id को अपनी dedup key के रूप में use करें — retries same id reuse करते हैं, इसलिए उस column पर row-level INSERT … ON CONFLICT DO NOTHING आपके handler को safe रखता है।


Errors

हर error response एक stable code carry करता है जिस पर आप programmatically branch कर सकते हैं। message field human-readable hint है और releases के बीच बदल सकता है। request_id, X-Request-Id response header को echo करता है — इसे support tickets में include करें।

{
  "error": {
    "code": "invalid_api_key",
    "message": "API key is unknown or revoked.",
    "request_id": "f0c2d6c4-…"
  }
}
Code Meaning
unauthenticated Missing या malformed Authorization header।
invalid_api_key API key unknown है या rotate होकर बाहर हो गई है।
rate_limited Per-partner या per-IP rate limit exceeded — Retry-After देखें।
missing_idempotency_key Idempotency-Key के बिना POST request।
idempotency_key_mismatch Same key different request body के साथ reuse हुई।
validation_error Request body schema validation fail हुआ।
not_found Resource मौजूद नहीं है या आपके partner से belong नहीं करता।
payment_gateway_error Stripe ने Checkout session creation reject किया।

Rate limits

  • 120 requests / 60 s rolling window, per partner। Burst और steady-state same bucket share करते हैं।
  • 60 requests / 60 s unauthenticated और failed-auth requests के लिए separate per-IP bucket — bearer brute-force को partner quota consume करने से रोकता है।
  • Excess requests 429 rate_limited के साथ Retry-After header return करती हैं (back off करने के seconds)।

Help चाहिए?

ये docs उन partners के लिए लिखे गए हैं जो API सच में इस्तेमाल करते हैं। अगर कुछ missing, confusing, या stale है, तो अपने mintbot agent को बताएँ — वे feedback forward करेंगे और हम page update कर देंगे।