Brand Partner API¶
Ett litet, förutsägbart REST API för att skapa mintbot-ordrar, kontrollera deras status och ta emot livscykelhändelser. JSON in, JSON ut. Bearer-token-auth. Idempotenta skrivningar. Signerade webhooks.
Dashboard för API-åtkomst Hoppa till webhooks
Snabb översikt¶
| Bas-URL | https://mint.mintbot.ai/api/v1 |
| Auth | `Authorization: Bearer *** |
| Idempotens | Idempotency-Key: <uuid> på varje POST |
| Innehållstyp | application/json |
| Hastighetsgräns | 120 req / 60 s per partner |
| Webhooks | Signeras med HMAC-SHA256, försöks igen upp till 7 gånger |
Autentisering¶
Varje begäran skickar en partner-API-nyckel i headern Authorization. Generera eller rotera nyckeln i dashboarden.
Authorization: Bearer mo_liv...xxxx
Content-Type: application/json
Rotation har ingen respitperiod
När nyckeln roteras spärras den föregående atomärt. Planera att byta värdet i din config innan du klickar på Rotate.
Idempotens¶
Varje POST kräver headern Idempotency-Key. Vilken UUID som helst per unik begäran fungerar.
- Vi cachar svaret i 24 timmar. Ett nytt försök med samma nyckel spelar upp det ursprungliga svaret med
Idempotent-Replay: true. - Om samma nyckel återanvänds med en annan body returneras
409 idempotency_key_mismatch.
Ordrar¶
Skapa order¶
POST /orders
Skapar en order och returnerar en Stripe Checkout-URL. När betalningen bekräftas provisionerar mintbot agenten och intäktshändelsen för partnerandelen registreras automatiskt.
Begäran
{
"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- En av
trial,s1,s2,s4. duration_months- Kalendermånader för serverns livstid. Måste vara
1,3eller12. credit_usd- Valfritt. Förfinansierad chattkredit som paketeras med ordern.
language- Valfritt. Påverkar språket i Stripe Checkout och välkomstmejlet.
external_id- Valfritt. Ekas tillbaka i varje webhook och ordersvar — använd det för att koppla mintbot-ordrar till rader i ditt eget system.
success_url·cancel_url- Retur-URL:er för Stripe Checkout.
{ORDER_ID}ersätts på serversidan. webhook_url- Valfritt. Åsidosättning per order av webhook-URL:en på partnernivå.
Svar — 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
}
Exempel
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"]
Hämta order¶
GET /orders/{id}
Hämtar en enskild order via dess mintbot-id. Returnerar samma form som POST /orders.
curl https://mint.mintbot.ai/api/v1/orders/42 \
-H "Authorization: Bearer ***
Lista ordrar¶
GET /orders
Markörpaginering, nyast först.
Query-parametrar
status- Valfritt. Filtrera efter
awaiting_payment,completed,deployed,deploy_failedellerexpired. cursor- Valfritt. Skicka
next_cursorfrån föregående sida för att fortsätta.
Svar
{
"items": [ /* OrderResponse … */ ],
"next_cursor": "37"
}
next_cursor är null när det inte finns fler sidor.
Förnya order¶
POST /orders/{id}/renew
Förlänger en befintlig agent med ytterligare duration_months. Endast infra — ingen ny chattkredit ingår. Returnerar ett nytt order-id och en ny Stripe Checkout-URL.
Begäran
{
"duration_months": 1,
"external_id": "your-side-id",
"success_url": "https://your.app/thanks?id={ORDER_ID}",
"cancel_url": "https://your.app/account"
}
Intäkter¶
Läs intäkter¶
GET /revenue
Totalsummor plus de senaste 200 ledger-händelserna.
Query-parametrar
include_paid- Valfritt, standard
true. Sätt tillfalseför att bara se händelser som ännu inte har betalats ut.
Svar
{
"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
}
]
}
Partnerprofil¶
Hämta profil¶
GET /partner
Ekar din partnerprofil plus obetalt saldo — praktiskt för att visa intäkter i ditt eget admin-UI utan att lagra dem själv.
Svar
{
"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¶
När något händer med en order gör vi POST av en signerad JSON-händelse till din konfigurerade webhook-URL.
Händelsetyper¶
| Händelse | När den utlöses |
|---|---|
order.created |
Stripe Checkout-session skapad, inväntar betalning. |
order.paid |
Stripe bekräftade betalningen. Intäktshändelse registrerad. |
order.cancelled |
Ordern gick ut eller avbröts uttryckligen. |
agent.provisioning_started |
Deploy-pipelinen startade för den här ordern. |
agent.ready |
Deploy lyckades. Payload innehåller panel_url och expires_at. |
agent.failed |
Deploy-pipelinen fick fel. Kontrollera fältet error för steget som gick sönder. |
agent.expired |
Agentens TTL har löpt ut. Partnern kan förnya via POST /orders/{id}/renew. |
Leverans och nya försök¶
- Upp till 7 försök enligt ett exponentiellt schema:
0s, 30s, 2m, 10m, 1h, 6h, 24h. - Efter sista försöket markeras leveransen som
exhaustedoch slutar försöka igen. - Svara med en
2xx-status inom 10 sekunder för att bekräfta.
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
Exempelpayload — 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"
}
Verifiera signaturen¶
Signaturen är HMAC-SHA256(secret, "{timestamp}.{raw_body}"). Verifiera alltid den råa request-bodyn — att serialisera om din parsade JSON bryter jämförelsen.
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"),
);
}
Idempotenta mottagare
Använd X-Mintbot-Event-Id som dedupliceringsnyckel — nya försök återanvänder samma id, så en radnivå-INSERT … ON CONFLICT DO NOTHING på den kolumnen håller din handler säker.
Fel¶
Varje felsvar innehåller en stabil code som du kan förgrena på programmatiskt. Fältet message är en läsbar ledtråd och kan ändras mellan releaser. request_id ekar respons-headern X-Request-Id — ta med det i supportärenden.
{
"error": {
"code": "invalid_api_key",
"message": "API key is unknown or revoked.",
"request_id": "f0c2d6c4-…"
}
}
| Kod | Betydelse |
|---|---|
unauthenticated |
Saknad eller felformaterad Authorization-header. |
invalid_api_key |
API-nyckeln är okänd eller har roterats bort. |
rate_limited |
Rate limit per partner eller per IP har överskridits — se Retry-After. |
missing_idempotency_key |
POST-begäran utan Idempotency-Key. |
idempotency_key_mismatch |
Samma nyckel återanvändes med en annan request body. |
validation_error |
Request body klarade inte schemavalideringen. |
not_found |
Resursen finns inte eller tillhör inte din partner. |
payment_gateway_error |
Stripe avvisade skapandet av Checkout-sessionen. |
Rate limits¶
- 120 begäranden / 60 s rullande fönster, per partner. Burst och steady-state delar samma bucket.
- 60 begäranden / 60 s separat per-IP-bucket för oautentiserade och misslyckade auth-begäranden — hindrar bearer brute-force från att äta upp partnerkvoten.
- Överskjutande begäranden returnerar
429 rate_limitedmed headernRetry-After(sekunder att vänta).
Behöver du hjälp?¶
Den här dokumentationen är skriven för de partners som faktiskt använder API:t. Om något saknas, är förvirrande eller inaktuellt, nämn det för din mintbot-agent — så vidarebefordrar de feedbacken och vi uppdaterar sidan.