কনটেন্টে যান

Brand Partner API

mintbot orders তৈরি করা, তাদের status poll করা, এবং lifecycle events গ্রহণ করার জন্য ছোট, 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 প্রতি partner 120 req / 60 s
Webhooks HMAC-SHA256 দিয়ে signed, সর্বোচ্চ 7 বার retry

Authentication

প্রতিটি request Authorization header-এ একটি partner API key পাঠায়। dashboard-এ key generate বা rotate করুন।

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

Rotation-এর কোনো grace window নেই

Key rotate করলে আগের key atomically revoke হয়। Rotate-এ click করার আগে আপনার config-এ value swap করার পরিকল্পনা করুন।

Idempotency

প্রতিটি POST-এর জন্য Idempotency-Key header দরকার। আলাদা request প্রতি যেকোনো UUID কাজ করে।

  • আমরা response 24 hours cache করি। একই key দিয়ে retry করলে original response Idempotent-Replay: true সহ replay হয়।
  • একই 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 back হয় — আপনার নিজের system-এর rows-এর সঙ্গে mintbot orders thread করতে এটি ব্যবহার করুন।
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}

তার mintbot id দিয়ে একটি single order fetch করে। POST /orders-এর মতো একই 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"
}

আর কোনো page না থাকলে next_cursor হলো null


Order renew করুন

POST /orders/{id}/renew

Existing agent-কে আরেক 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 এবং সর্বশেষ 200 ledger events।

Query parameters

include_paid
Optional, default true. শুধু এখনও paid out হয়নি এমন events দেখতে false set করুন।

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 দেখাতে সুবিধাজনক, নিজে 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, awaiting payment.
order.paid Stripe payment confirm করেছে। Revenue event recorded।
order.cancelled Order timed out হয়েছে বা explicitly cancelled হয়েছে।
agent.provisioning_started এই order-এর জন্য deploy pipeline started।
agent.ready Deploy succeeded। 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 হিসেবে ব্যবহার করুন — retries একই id reuse করে, তাই ওই column-এ row-level INSERT … ON CONFLICT DO NOTHING আপনার handler নিরাপদ রাখে।


Errors

প্রতিটি error response একটি stable code বহন করে, যাতে আপনি programmatically branch করতে পারেন। message field human-readable hint এবং releases-এর মধ্যে change হতে পারে। 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 Authorization header missing বা malformed।
invalid_api_key API key unknown বা rotate out হয়ে গেছে।
rate_limited Per-partner বা per-IP rate limit exceeded — Retry-After দেখুন।
missing_idempotency_key Idempotency-Key ছাড়া POST request।
idempotency_key_mismatch একই key different request body দিয়ে reuse করা হয়েছে।
validation_error Request body schema validation failed।
not_found Resource নেই বা আপনার partner-এর নয়।
payment_gateway_error Stripe Checkout session creation reject করেছে।

Rate limits

  • প্রতি partner 120 requests / 60 s rolling window। Burst এবং steady-state একই bucket share করে।
  • Unauthenticated এবং failed-auth requests-এর জন্য আলাদা per-IP bucket: 60 requests / 60 s — bearer brute-force-কে partner quota খেয়ে ফেলা থেকে আটকায়।
  • Excess requests Retry-After header (কত seconds back off করতে হবে) সহ 429 rate_limited return করে।

Help দরকার?

এই ডকস সেই partners-দের জন্য লেখা যারা সত্যিই API ব্যবহার করেন। কিছু missing, confusing, বা stale হলে আপনার mintbot agent-কে বলুন — তারা feedback forward করবে এবং আমরা page update করব।