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,3tai12. 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_failedtaiexpired. 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 arvoonfalse, 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
exhaustedja 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_limitedjaRetry-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.