Gå til indholdet

Brand Partner API

Et lille, forudsigeligt REST API til at oprette mintbot-ordrer, hente deres status og modtage lifecycle events. JSON ind, JSON ud. Bearer-token auth. Idempotente writes. Signerede webhooks.

API access dashboard Gå til webhooks


Kort overblik

Base URL https://mint.mintbot.ai/api/v1
Auth Authorization: Bearer ***
Idempotency Idempotency-Key: <uuid> på hver POST
Content type application/json
Rate limit 120 req / 60 s pr. partner
Webhooks Signeret med HMAC-SHA256, forsøges igen op til 7 gange

Autentificering

Hver request sender en partner API key i Authorization headeren. Generér eller rotér key'en i dashboardet.

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

Rotation har intet grace window

Når du roterer key'en, tilbagekaldes den tidligere atomisk. Planlæg at udskifte værdien i din config, før du klikker Rotate.

Idempotency

Hver POST kræver en Idempotency-Key header. En hvilken som helst UUID pr. unik request virker.

  • Vi cacher response i 24 timer. Et retry med samme key afspiller det oprindelige response med Idempotent-Replay: true.
  • Genbrug af samme key med en anden body returnerer 409 idempotency_key_mismatch.

Ordrer

Opret order

POST /orders

Opretter en order og returnerer en Stripe Checkout URL. Når betalingen er bekræftet, provisionerer mintbot agenten, og revenue event for partner-andelen registreres automatisk.

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
En af trial, s1, s2, s4.
duration_months
Kalendermåneder for serverens levetid. Skal være en af 1, 3 eller 12.
credit_usd
Valgfri. Forudfinansieret chat credit, der følger med ordren.
language
Valgfri. Påvirker Stripe Checkout locale og sproget i welcome-email.
external_id
Valgfri. Sendes tilbage i hver webhook og order response — brug den til at knytte mintbot-ordrer til rækker i dit eget system.
success_url · cancel_url
Stripe Checkout return URLs. {ORDER_ID} erstattes server-side.
webhook_url
Valgfri. Per-order override af webhook URL på partnerniveau.

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
}

Eksempel

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"]

Hent order

GET /orders/{id}

Henter en enkelt order via dens mintbot id. Returnerer samme form som POST /orders.

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

List orders

GET /orders

Cursor-pagineret liste, nyeste først.

Query parameters

status
Valgfri. Filtrér efter awaiting_payment, completed, deployed, deploy_failed eller expired.
cursor
Valgfri. Send next_cursor fra den forrige side for at fortsætte.

Response

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

next_cursor er null, når der ikke er flere sider.


Forny order

POST /orders/{id}/renew

Forlænger en eksisterende agent med yderligere duration_months. Kun infra — ingen ny chat credit følger med. Returnerer et nyt order id og en ny Stripe Checkout URL.

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

Læs revenue

GET /revenue

Totaler plus de seneste 200 ledger events.

Query parameters

include_paid
Valgfri, default true. Sæt til false for kun at se events, der endnu ikke er udbetalt.

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
    }
  ]
}

Partnerprofil

Hent profil

GET /partner

Sender din partnerprofil tilbage plus den ubetalte saldo — praktisk til at vise indtjening i dit eget admin UI uden selv at gemme den.

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

Når der sker noget med en order, POSTer vi en signeret JSON event til din konfigurerede webhook URL.

Event types

Event Hvornår den udløses
order.created Stripe Checkout session oprettet, afventer betaling.
order.paid Stripe bekræftede betaling. Revenue event registreret.
order.cancelled Order timed out eller blev eksplicit annulleret.
agent.provisioning_started Deploy pipeline startet for denne order.
agent.ready Deploy lykkedes. Payload indeholder panel_url og expires_at.
agent.failed Deploy pipeline fejlede. Tjek error feltet for det trin, der gik i stykker.
agent.expired Agent TTL udløb. Partneren kan forny via POST /orders/{id}/renew.

Delivery & retries

  • Op til 7 forsøg efter en eksponentiel plan: 0s, 30s, 2m, 10m, 1h, 6h, 24h.
  • Efter det sidste forsøg markeres leveringen som exhausted, og retries stopper.
  • Svar med en 2xx status inden for 10 sekunder for at kvittere.

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"
}

Verificering af signaturen

Signaturen er HMAC-SHA256(secret, "{timestamp}.{raw_body}"). Verificér altid den request body — hvis du serialiserer din parsede JSON igen, ødelægger det sammenligningen.

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"),
  );
}

Idempotente receivers

Brug X-Mintbot-Event-Id som din dedup key — retries genbruger samme id, så en row-level INSERT … ON CONFLICT DO NOTHING på den kolonne holder din handler sikker.


Errors

Hvert error response har en stabil code, som du kan branch'e på programmatisk. message feltet er et menneskelæsbart hint og kan ændre sig mellem releases. request_id gentager X-Request-Id response headeren — medtag det i support tickets.

{
  "error": {
    "code": "invalid_api_key",
    "message": "API key is unknown or revoked.",
    "request_id": "f0c2d6c4-…"
  }
}
Code Betydning
unauthenticated Manglende eller forkert formet Authorization header.
invalid_api_key API key er ukendt eller er roteret ud.
rate_limited Rate limit pr. partner eller pr. IP overskredet — se Retry-After.
missing_idempotency_key POST request uden Idempotency-Key.
idempotency_key_mismatch Samme key genbrugt med en anden request body.
validation_error Request body bestod ikke schema validation.
not_found Ressource findes ikke eller tilhører ikke din partner.
payment_gateway_error Stripe afviste oprettelsen af Checkout session.

Rate limits

  • 120 requests / 60 s rolling window, pr. partner. Burst og steady-state deler samme bucket.
  • 60 requests / 60 s separat per-IP bucket for unauthenticated og failed-auth requests — forhindrer bearer brute-force i at æde af partnerens kvote.
  • Overskydende requests returnerer 429 rate_limited med en Retry-After header (sekunder at vente).

Brug for hjælp?

Denne dokumentation er skrevet til de partnere, der faktisk bruger API'et. Hvis noget mangler, er forvirrende eller forældet, så nævn det for din mintbot agent — de videresender feedbacken, og vi opdaterer siden.