Hyppää sisältöön

Brand Partner API

Pieni ja ennustettava REST API mintbot-tilausten luontiin, niiden tilan kyselyyn ja elinkaaritapahtumien vastaanottoon. JSON sisään, JSON ulos. Bearer-token-autentikointi. Idempotentit kirjoitukset. Allekirjoitetut webhookit.

API-käytön dashboard Siirry webhooks-osioon


Yleiskuva

Base URL https://mint.mintbot.ai/api/v1
Auth `Authorization: Bearer ***
Idempotency Idempotency-Key: <uuid> jokaisessa POST-pyynnössä
Content type application/json
Rate limit 120 pyyntöä / 60 s per partneri
Webhooks Allekirjoitettu HMAC-SHA256:lla, yritetään uudelleen enintään 7 kertaa

Autentikointi

Jokainen pyyntö lähettää partnerin API-avaimen Authorization-headerissa. Luo tai kierrätä avain dashboardissa.

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

Kierrätyksessä ei ole armonaikaa

Avaimen kierrättäminen kumoaa edellisen avaimen atomisesti. Suunnittele arvon vaihtaminen konfiguraatioosi ennen kuin klikkaat Rotate.

Idempotenssi

Jokainen POST vaatii Idempotency-Key-headerin. Mikä tahansa UUID käy kullekin erilliselle pyynnölle.

  • Välimuistitamme vastauksen 24 tunniksi. Uusintayritys samalla avaimella toistaa alkuperäisen vastauksen headerilla Idempotent-Replay: true.
  • Saman avaimen uudelleenkäyttö eri rungolla palauttaa 409 idempotency_key_mismatch.

Tilaukset

Luo tilaus

POST /orders

Luo tilauksen ja palauttaa Stripe Checkout -URL:n. Kun maksu vahvistuu, mintbot provisioi agentin ja partnerin osuuden tulotapahtuma kirjataan automaattisesti.

Pyyntö

{
  "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
Yksi arvoista trial, s1, s2, s4.
duration_months
Palvelimen elinaika kalenterikuukausina. Sallitut arvot: 1, 3 tai 12.
credit_usd
Valinnainen. Tilaukseen sisällytetty ennakkoon rahoitettu chat-krediitti.
language
Valinnainen. Vaikuttaa Stripe Checkoutin kieliasetukseen ja tervetulosähköpostin kieleen.
external_id
Valinnainen. Kaikuu takaisin jokaisessa webhookissa ja tilausvastauksessa — käytä sitä yhdistämään mintbot-tilaukset oman järjestelmäsi riveihin.
success_url · cancel_url
Stripe Checkoutin paluu-URL:t. {ORDER_ID} korvataan palvelinpuolella.
webhook_url
Valinnainen. Tilauskohtainen ohitus partneritason webhook-URL:lle.

Vastaus — 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
}

Esimerkki

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

Hae tilaus

GET /orders/{id}

Hakee yhden tilauksen sen mintbot-id:n perusteella. Palauttaa saman muodon kuin POST /orders.

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

Listaa tilaukset

GET /orders

Kursorilla sivutettu lista, uusin ensin.

Kyselyparametrit

status
Valinnainen. Suodata arvoilla awaiting_payment, completed, deployed, deploy_failed tai expired.
cursor
Valinnainen. Jatka antamalla edellisen sivun next_cursor.

Vastaus

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

next_cursor on null, kun sivuja ei ole enää lisää.


Uusi tilaus

POST /orders/{id}/renew

Jatkaa olemassa olevaa agenttia toisen duration_months-jakson ajan. Vain infra — uutta chat-krediittiä ei sisällytetä. Palauttaa uuden tilaus-id:n ja uuden Stripe Checkout -URL:n.

Pyyntö

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

Tulot

Lue tulot

GET /revenue

Kokonaissummat sekä viimeisimmät 200 ledger-tapahtumaa.

Kyselyparametrit

include_paid
Valinnainen, oletus true. Aseta arvoon false, jos haluat nähdä vain tapahtumat, joita ei ole vielä maksettu ulos.

Vastaus

{
  "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-profiili

Hae profiili

GET /partner

Palauttaa partneriprofiilisi sekä maksamattoman saldon — kätevä, kun haluat näyttää ansiot omassa admin-käyttöliittymässäsi tallentamatta niitä itse.

Vastaus

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

Kun tilaukselle tapahtuu jotain, lähetämme POST-pyynnöllä allekirjoitetun JSON-tapahtuman määritettyyn webhook-URL:si.

Tapahtumatyypit

Event Milloin se laukeaa
order.created Stripe Checkout -istunto luotu, odottaa maksua.
order.paid Stripe vahvisti maksun. Tulotapahtuma kirjattu.
order.cancelled Tilaus aikakatkaistiin tai peruttiin erikseen.
agent.provisioning_started Deploy-putki käynnistyi tälle tilaukselle.
agent.ready Deploy onnistui. Payload sisältää panel_url ja expires_at.
agent.failed Deploy-putki virheili. Tarkista error-kentästä vaihe, joka rikkoutui.
agent.expired Agentin TTL päättyi. Partneri voi uusia komennolla POST /orders/{id}/renew.

Toimitus ja uudelleenyritykset

  • Enintään 7 yritystä eksponentiaalisella aikataululla: 0s, 30s, 2m, 10m, 1h, 6h, 24h.
  • Viimeisen yrityksen jälkeen toimitus merkitään tilaan exhausted ja uudelleenyritykset loppuvat.
  • Vastaa 2xx-statuksella 10 sekunnin sisällä kuittaukseksi.

Pyynnön headerit

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

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

Allekirjoituksen vahvistaminen

Allekirjoitus on HMAC-SHA256(secret, "{timestamp}.{raw_body}"). Vahvista aina raaka pyyntörunko — jäsennetyn JSONin uudelleensarjoittaminen rikkoo vertailun.

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

Idempotentit vastaanottajat

Käytä X-Mintbot-Event-Id-arvoa deduplikointiavaimena — uudelleenyritykset käyttävät samaa id:tä, joten rivitason INSERT … ON CONFLICT DO NOTHING kyseiseen sarakkeeseen pitää handlerisi turvallisena.


Virheet

Jokaisessa virhevastauksessa on vakaa code, jonka perusteella voit haarautua ohjelmallisesti. message-kenttä on ihmiselle luettava vihje ja voi muuttua julkaisujen välillä. request_id kaikuttaa X-Request-Id-vastausheaderin — lisää se tukipyyntöihin.

{
  "error": {
    "code": "invalid_api_key",
    "message": "API key is unknown or revoked.",
    "request_id": "f0c2d6c4-…"
  }
}
Code Merkitys
unauthenticated Puuttuva tai virheellinen Authorization-header.
invalid_api_key API-avain on tuntematon tai se on kierrätetty pois käytöstä.
rate_limited Partneri- tai IP-kohtainen nopeusraja ylittyi — katso Retry-After.
missing_idempotency_key POST-pyyntö ilman Idempotency-Key-headeria.
idempotency_key_mismatch Sama avain käytettiin uudelleen eri pyyntörungolla.
validation_error Pyyntörunko ei läpäissyt skeemavalidointia.
not_found Resurssia ei ole olemassa tai se ei kuulu partnerillesi.
payment_gateway_error Stripe hylkäsi Checkout-istunnon luonnin.

Nopeusrajat

  • 120 pyyntöä / 60 s liukuva ikkuna, per partneri. Purkausliikenne ja tasainen liikenne jakavat saman bucketin.
  • 60 pyyntöä / 60 s erillinen IP-kohtainen bucket autentikoimattomille ja epäonnistuneen autentikoinnin pyynnöille — estää bearer brute-forcen kuluttamasta partnerin kiintiötä.
  • Ylimääräiset pyynnöt palauttavat 429 rate_limited ja Retry-After-headerin (sekunteina odotettava aika).

Tarvitsetko apua?

Nämä dokumentit on kirjoitettu partnereille, jotka oikeasti käyttävät API:a. Jos jotain puuttuu, on epäselvää tai vanhentunutta, mainitse siitä mintbot-agentillesi — hän välittää palautteen eteenpäin ja päivitämme sivun.