Pāriet uz saturu

Brand Partner API

Mazs un paredzams REST API, ar ko izveidot mintbot pasūtījumus, sekot to statusam un saņemt dzīvescikla notikumus. JSON iekšā, JSON ārā. Bearer-token autentifikācija. Idempotenti rakstīšanas pieprasījumi. Parakstīti webhooki.

API piekļuves panelis Pāriet uz webhookiem


Īsumā

Bāzes URL https://mint.mintbot.ai/api/v1
Autentifikācija Authorization: Bearer mo_live_…
Idempotence Idempotency-Key: <uuid> katram POST, izņemot POST /dns/records
Satura tips application/json
Pieprasījumu limits 120 pieprasījumi / 60 s katram partnerim
Webhooki Parakstīti ar HMAC-SHA256, atkārtoti līdz 7 reizēm

Autentifikācija

Katrs pieprasījums Authorization galvenē nosūta partnera API atslēgu. Atslēgu ģenerē vai rotē vadības panelī.

Authorization: Bearer mo_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json

Rotācijai nav pārejas perioda

Atslēgas rotācija iepriekšējo atslēgu atsauc atomāri. Sagatavojies nomainīt vērtību savā konfigurācijā, pirms klikšķini Rotate.

Idempotence

Katram POST ir vajadzīga Idempotency-Key galvene — izņemot POST /dns/records, kas nodrošinātāja līmenī ir dabiski idempotents un pieņem atkārtotus mēģinājumus arī bez tās. Der jebkurš UUID, ja vien katram atsevišķam pieprasījumam tas ir savs.

  • Atbildi glabājam kešatmiņā 24 stundas. Atkārtots mēģinājums ar to pašu atslēgu atgriež sākotnējo atbildi ar Idempotent-Replay: true.
  • Tās pašas atslēgas izmantošana ar citu pieprasījuma saturu atgriež 409 idempotency_key_mismatch.

Pasūtījumi

Izveidot pasūtījumu

POST /orders

Izveido pasūtījumu un atgriež Stripe Checkout URL. Kad maksājums ir apstiprināts, mintbot sagatavo aģentu, un partnera daļas ieņēmumu notikums tiek ierakstīts automātiski.

Pieprasījums

{
  "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
Viens no trial, s1, s2, s4.
duration_months
Servera darbības laiks kalendārajos mēnešos. Jābūt 1, 3 vai 12.
credit_usd
Neobligāts. Pasūtījumā iekļautais iepriekš apmaksātais tērzēšanas kredīts.
language
Neobligāts. Nosaka Stripe Checkout valodu un sveiciena e-pasta valodu.
external_id
Neobligāts. Tiek atgriezts katrā webhookā un pasūtījuma atbildē — izmanto to, lai sasaistītu mintbot pasūtījumus ar ierakstiem savā sistēmā.
success_url · cancel_url
Stripe Checkout atgriešanās URL. {ORDER_ID} tiek aizstāts servera pusē.
webhook_url
Neobligāts. Pārraksta partnera līmeņa webhook URL tikai šim pasūtījumam.

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

Piemērs

curl -X POST https://mint.mintbot.ai/api/v1/orders \
  -H "Authorization: Bearer $MINTBOT_API_KEY" \
  -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"]

Iegūt pasūtījumu

GET /orders/{id}

Nolasa vienu pasūtījumu pēc tā mintbot id. Atgriež tādu pašu struktūru kā POST /orders.

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

Pasūtījumu saraksts

GET /orders

Ar kursoru lapots saraksts, jaunākie vispirms.

Vaicājuma parametri

status
Neobligāts. Filtrē pēc awaiting_payment, completed, deployed, deploy_failed vai expired.
cursor
Neobligāts. Padod next_cursor no iepriekšējās lapas, lai turpinātu.

Atbilde

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

next_cursor ir null, kad vairs nav nākamo lapu.


Pagarināt pasūtījumu

POST /orders/{id}/renew

Pagarina esošu aģentu vēl par duration_months. Tikai infrastruktūra — jauns tērzēšanas kredīts netiek iekļauts. Atgriež jaunu pasūtījuma id un jaunu Stripe Checkout URL.

Pieprasījums

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

Ieņēmumi

Nolasīt ieņēmumus

GET /revenue

Kopsummas un pēdējie 200 virsgrāmatas notikumi.

Vaicājuma parametri

include_paid
Neobligāts, noklusējums true. Iestati false, lai redzētu tikai vēl neizmaksātos notikumus.

Atbilde

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

Partnera profils

Iegūt profilu

GET /partner

Atgriež tavu partnera profilu kopā ar neizmaksāto atlikumu — ērti, lai rādītu ieņēmumus savā administrēšanas saskarnē, tos pašam neglabājot.

Atbilde

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

Iestatījumi

Iegūt iestatījumus

GET /settings

Atgriež visu tavu nesekrēto partnera konfigurāciju vienā atbildē — izvēlētos režīmus, apex domēnu, DNS nodrošinātāju, bota nodrošinātāju, pielāgojumu repozitoriju, apakšdomēnu šablonu (ar sagatavotu priekšskatījuma etiķeti), cenas katram līmenim, API atslēgas metadatus, webhooka metadatus un to pašu gatavības / sadaļu statusu, kas darbina MintOffice vadības paneļa baneri.

Paredzēts integrācijas aģentiem, kuriem jānoskaidro, kā partneris ir iestatīts, neskrāpējot vadības paneli un neiztaujājot operatoru. Tipisks izsaucējs ir kodēšanas aģents, kas uz jauna servera instalē tavu white-label iestatījumu — tas var nolasīt šo galapunktu, sazaroties pēc readiness.status un precīzi pateikt operatoram, kuras sadaļas vēl jāsakārto.

Neviens noslēpums netiek atgriezts

Viss, ko partneris ievadījis kā akreditācijas datus — Telegram bota tokens, Zone.ee API atslēga, webhooka parakstīšanas noslēpums, pati API atslēga atklātā tekstā — parādās tikai kā *_set būla vērtība. Webhooka noslēpumam papildus ir pieejams tas pats 8 rakstzīmju priedēklis, kas jau redzams vadības panelī, lai izsaucējs varētu pārliecināties, kurš noslēpums ir konfigurēts, nekad neredzot pašu vērtību.

Atbilde

{
  "id": 12,
  "email": "you@kliendifirma.com",
  "status": "live",
  "created_at": "2026-05-12 14:22:01",
  "onboarded_at": "2026-05-12 14:48:33",
  "activated_at": "2026-05-13 09:10:05",
  "last_login_at": "2026-05-20 00:51:18",
  "preferred_language": "en",
  "pricing_currency": "usd",
  "balance_unpaid_cents": 800,

  "domain": {
    "mode": "byo",
    "client_apex_domain": "agent99.cc",
    "dns_provider": "zone.ee",
    "zone_ee_username": "you@kliendifirma.com",
    "zone_ee_api_key_set": true,
    "subdomain_prefix": "agent",
    "subdomain_numbering": "natural",
    "subdomain_pad_width": 3,
    "subdomain_label_preview": "agent1"
  },

  "bot": {
    "mode": "own",
    "provider": "telegram",
    "telegram_bot_username": "agent99cc_bot",
    "telegram_bot_token_set": true
  },

  "template": {
    "mode": "default",
    "repo_url": null
  },

  "api": {
    "key_prefix": "mo_live_a12b",
    "key_created_at": "2026-05-13 09:11:42",
    "webhook_url": "https://your.app/mintbot-webhook",
    "webhook_secret_set": true,
    "webhook_secret_prefix": "ab12cd34"
  },

  "pricing": {
    "mode": "default",
    "currency": "usd",
    "tiers": {
      "trial": { "price_cents": 0,    "partner_cut_cents": 0,   "updated_at": null },
      "s1":    { "price_cents": 1200, "partner_cut_cents": 200, "updated_at": "2026-05-13 09:05:00" },
      "s2":    { "price_cents": 2400, "partner_cut_cents": 400, "updated_at": "2026-05-13 09:05:00" },
      "s4":    { "price_cents": 4800, "partner_cut_cents": 800, "updated_at": "2026-05-13 09:05:00" }
    }
  },

  "readiness": {
    "ready": true,
    "missing_fields": [],
    "dns_blocker": null,
    "status": "live"
  },

  "section_status": {
    "domain":   { "status": "ready", "mode": "byo",     "issue": null, "dns_blocker": null },
    "bot":      { "status": "ready", "mode": "own",     "issue": null, "dns_blocker": null },
    "template": { "status": "ready", "mode": "default", "issue": null, "dns_blocker": null },
    "api":      { "status": "ready", "mode": "live",    "issue": null, "dns_blocker": null },
    "all_ready": true
  }
}

Lauku apraksts

status
Partnera dzīvescikls. Viens no onboarding, live, paused. Kamēr statuss ir onboarding, Brand Partner API rakstīšanas pieprasījumus noraida.
domain.mode
byo (tu izmanto savu apex domēnu) vai hosted (mintbot piešķir *.mintbot.ai apakšdomēnu). Režīmā hosted DNS nodrošinātāja lauki apzināti ir tukši neatkarīgi no tā, ko partneris ievadījis iepriekš.
domain.subdomain_label_preview
Sagatavotā etiķete, ko saņemtu pirmais klienta aģents (agent1, 1, 001, …) ar pašreizējiem subdomain_prefix, subdomain_numbering un subdomain_pad_width. Izmanto to priekšskatījumam „lūk, ko redzēs tavi klienti“, nepārrakstot numerācijas noteikumus pats.
bot.mode
own (partnera Telegram bots), borrow (testēšanas laikā tiek izmantots mintbot bots) vai web (tikai panelis, bez Telegram).
template.mode
default (aģenta pielāgojumu repozitorija nav — aģents darbojas uz vienkāršās bāzes bez zīmola) vai custom (partnera aģenta pielāgojumu repozitorijs adresē repo_url). Režīmā custom aģenta paša VPS pēc standarta izvietošanas klonē šo repozitoriju un palaiž tā install.sh / update.sh, lai virs bāzes uzliktu tavu personu, paneļa tēmu un jebkurus papildu rīkus — centrālā sistēma repozitoriju nekad nepalaiž. Ja vēlies savu zīmolu, norādi repo_url uz sava aģenta pielāgojumu repozitorija GitHub HTTPS adresi.
api.webhook_secret_prefix
Webhooka parakstīšanas noslēpuma pirmās 8 rakstzīmes; atgriež tikai tad, ja noslēpums ir konfigurēts. Ļauj izsaucējam atšķirt, kurš noslēpums ir spēkā, neredzot pilno vērtību. Vadības panelis rāda to pašu priedēkli.
readiness.missing_fields
Vadības paneļa lauku nosaukumi, kas vēl jāaizpilda pirms Go Live. Tukšs, kad ready ir true. Pietiekami stabils, lai uz tā balstītu sadaļu „kas vēl trūkst“ savā administrēšanas saskarnē.
readiness.dns_blocker
Īss iemesla kods, kad DNS pārbaude neizdodas (piem., nameservers_not_pointing, glue_record_missing). Citādi null.
section_status.*.issue
Cilvēkam lasāms norādījums katrai sadaļai, kas bloķē Go Live. Atbilst vadības paneļa sadaļu statusa etiķetēm.

Piemērs

curl https://mint.mintbot.ai/api/v1/settings \
  -H "Authorization: Bearer $MINTBOT_API_KEY"
import os, requests

r = requests.get(
    "https://mint.mintbot.ai/api/v1/settings",
    headers={"Authorization": f"Bearer {os.environ['MINTBOT_API_KEY']}"},
    timeout=10,
)
r.raise_for_status()
settings = r.json()

if not settings["readiness"]["ready"]:
    print("Still missing:", settings["readiness"]["missing_fields"])

Katalogs

Pārdodamo pakešu saraksts tavam veikalam — publiskās paketes (trial / starter / pro) kopā ar tavām aprēķinātajām cenām tavā cenu valūtā. Veido plānu kartītes no šī saraksta, nevis iekodē līmeņu identifikatorus un cenas: izņemtās paketes pazūd pašas, un cenas vai valūtas maiņa, ko veic vadības panelī, sasniedz tavu veikalu kešatmiņas loga ietvaros — bez atkārtotas izvietošanas.

Tieši šis galapunkts neļauj veikalam reklamēt vakardienas paketes. Atsauces portāls to izsauc katrā sākumlapas / /buy / /extend attēlošanas reizē (ar kešatmiņu un noturīgu rezerves vērtību).

Attēlojamie teksti paliek tavi

display_name / description / featured ir kanoniskie mintbot pakešu metadati. Ja vēlies paketi pārsaukt vai pārrakstīt tās aprakstu savam zīmolam, pārraksti to savā veikalā (atsauces portālam tieši šim nolūkam ir PLAN_OVERRIDES karte) — katalogs ir patiesības avots tam, kuras paketes pastāv un cik tās maksā, nevis tavam mārketinga tekstam.

Iegūt katalogu

GET /api/v1/catalog

Bez parametriem. Tikai Bearer autentifikācija — aktivizācijas vārtu nav, tāpēc veikals var attēlot katalogu vēl pirms tava partnera konta pārslēgšanas uz live.

Atbilde

{
  "currency": "usd",
  "packages": [
    {
      "tier": "trial",
      "display_name": "Trial",
      "description": "One day to kick the tires.",
      "featured": false,
      "default_credit_usd": 5,
      "durations": [
        { "months": 1, "label": "24 hours", "price_cents": 0 }
      ],
      "subscription": { "available": false, "price_cents": null }
    },
    {
      "tier": "starter",
      "display_name": "Starter",
      "description": "A month of assistant time.",
      "featured": true,
      "default_credit_usd": 10,
      "durations": [
        { "months": 1,  "label": "1 month",   "price_cents": 1500 },
        { "months": 3,  "label": "3 months",  "price_cents": 4500 },
        { "months": 12, "label": "12 months", "price_cents": 18000 }
      ],
      "subscription": { "available": true, "price_cents": 1500 }
    }
  ]
}
Lauks Nozīme
currency Tava cenu valūta. Katrs price_cents zemāk ir izteikts tajā.
packages[] Viens ieraksts katrai publiskajai paketei piedāvājuma / attēlošanas secībā.
tier Identifikators, ko nodod POST /orders / POST /subscriptions.
display_name / description / featured Kanoniskie attēlojamie teksti (savā veikalā vari tos pārrakstīt).
default_credit_usd Paketē iekļautā LLM kredīta orientējošā vērtība (informatīva).
durations[] Iestatīšanas periodi, uz kādiem šo paketi var iegādāties. months ir vērtība, ko sūti kā duration_months; price_cents ir summa, ko pasūtījums iekasēs. Mēneša paketēm ir 1 / 3 / 12 mēnešu periodi; trial piedāvā vienu 24 stundu periodu.
subscription available ir true paketēm, ko var iegādāties kā ikmēneša automātiski atjaunojamu abonementu caur POST /subscriptions; price_cents ir mēneša summa. trial nekad nav pieejams kā abonements.

Cenas sakrīt ar to, kas tiks iekasēts

Katrs price_cents tiek aprēķināts ar to pašu cenu risinātāju, ko izmanto pasūtījumu galapunkts, tāpēc kartītes cena vienmēr ir vienāda ar galīgo Stripe Checkout kopsummu šim (tier, duration_months) pārim.

Piemērs

curl -s https://mint.mintbot.ai/api/v1/catalog \
  -H "Authorization: Bearer $MINTBOT_API_KEY" | jq
import os, requests

r = requests.get(
    "https://mint.mintbot.ai/api/v1/catalog",
    headers={"Authorization": f"Bearer {os.environ['MINTBOT_API_KEY']}"},
    timeout=10,
)
r.raise_for_status()
catalog = r.json()

for pkg in catalog["packages"]:
    month1 = next(d for d in pkg["durations"] if d["months"] == 1)
    print(pkg["display_name"], month1["price_cents"], catalog["currency"])

DNS ieraksti

Brand Partner integrācijām bieži jāizveido DNS ieraksti partnera apex domēnā — jānorāda @, www vai katra klienta apakšdomēns uz pareizo serveri. MintOffice piedāvā no nodrošinātāja neatkarīgu starpniekservisu, lai to varētu darīt, nekad neapstrādājot augšupējā nodrošinātāja API atslēgu savā infrastruktūrā. Akreditācijas dati, ko saglabāji ievadīšanas laikā (šobrīd zone.ee; cloudflare un route53 ir plānoti ar tādu pašu struktūru), paliek šifrēti MintOffice; tavs pieprasījums ienāk ar Bearer mo_live_…, un mēs tavā vārdā izsaucam augšupējo nodrošinātāju.

Tvērums ir partnera paša konfigurētais apex domēns (domain.client_apex_domain no GET /settings). Ierakstus zonā, kas tev nepieder, aiztikt nevar.

Šobrīd starpniekserviss atbalsta tās darbības, ko izmanto pati izvietošanas plūsma — A ierakstus (upsert / saraksts / dzēšana pēc id). CNAME / TXT / MX atbalsts sekos ar tādu pašu struktūru, tiklīdz pamatā esošā nodrošinātāju abstrakcija tos apgūs.

Idempotency-Key šeit nav vajadzīgs

Atšķirībā no pasūtījumu izveides galapunktiem DNS upsert ir dabiski idempotents nodrošinātāja līmenī (atkārtota izpilde ar to pašu (subdomain, ip) pāri neko nemaina, un novecojušie dublikāti tiek iztīrīti katrā izsaukumā). Idempotency-Key galvene nav jāsūta — atkārtoti mēģinājumi vienmēr noved pie viena A ieraksta katram FQDN.

A ieraksta upsert

POST /dns/records

Idempotenti norāda <subdomain>.<your-apex> uz IPv4 adresi. Pašam apex domēnam nodod "" (vai "@").

Pieprasījums

{
  "subdomain": "www",
  "ip": "203.0.113.10"
}

subdomain pieņem:

  • "" vai "@" — pats apex domēns (example.com).
  • Vienu DNS etiķeti — "www", "api" — adresei <label>.<apex>.
  • Etiķetes ar punktiem — "api.eu" — ligzdotiem apakšdomēniem (api.eu.example.com).

ip jābūt IPv4 adresei ar punktiem. Katra etiķete ir [a-z0-9_-], 1–63 rakstzīmes, bez - sākumā vai beigās.

Atbilde — 200

{
  "apex": "example.com",
  "provider": "zone_ee",
  "fqdn": "www.example.com",
  "records": [
    { "id": "9182734", "name": "www.example.com", "destination": "203.0.113.10" }
  ]
}

Saraksts records pēc ierakstīšanas vienmēr atspoguļo augšupējā nodrošinātāja pašreizējo skatu uz šo FQDN pēc dublikātu iztīrīšanas — tāpēc veiksmīga atbilde ar tieši vienu ierakstu ir signāls, ka nekas novecojis nav palicis.

Ierakstu saraksts

GET /dns/records

Atgriež visus A ierakstus konfigurētajā apex domēnā. Pievieno ?name=<label-or-fqdn>, lai filtrētu līdz vienam FQDN — vērtība var būt vienkārša etiķete ("www"), apakšdomēns ar punktiem ("api.eu") vai pilns FQDN ("www.example.com").

Atbilde — 200

{
  "apex": "example.com",
  "provider": "zone_ee",
  "items": [
    { "id": "9182734", "name": "example.com",     "destination": "203.0.113.10" },
    { "id": "9182735", "name": "www.example.com", "destination": "203.0.113.10" }
  ]
}

Dzēst ierakstu

DELETE /dns/records/{record_id}

record_id ir nodrošinātāja identifikators, ko atgriež GET /dns/records (zone.ee izsniedz veselus skaitļus, kas API robežā tiek pārvērsti virknēs). Vairs neesoša ieraksta dzēšana tiek uzskatīta par veiksmīgu — galapunkts klienta pusē ir idempotents.

Atbilde — 200

{ "deleted": true, "id": "9182734" }

Kļūdas

HTTP error.code Cēlonis
401 unauthenticated / invalid_api_key Trūkst Bearer tokena vai tas ir nederīgs.
422 validation_error Nederīgs apakšdomēns vai mērķis nav IPv4 adrese.
422 dns_not_configured Partnerim nav client_apex_domain vai trūkst konfigurētā nodrošinātāja akreditācijas datu. Labo sadaļā Settings → Domain.
422 dns_provider_unsupported Partnera DNS nodrošinātājs vēl nav pieslēgts MintOffice starpniekservisam (piem., cloudflare vietturis). Pagaidām pārslēdzies uz zone_ee.
502 dns_provider_error Augšupējais nodrošinātājs atgrieza 4xx/5xx vai neizdevās savienojums. Kļūdas message satur augšupējo statusu un īsu izvilkumu no atbildes ar aizklātiem noslēpumiem. Var droši mēģināt vēlreiz.

Piemērs

# Point apex + www at your server's IP.
curl https://mint.mintbot.ai/api/v1/dns/records \
  -H "Authorization: Bearer $MINTBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"subdomain": "",    "ip": "203.0.113.10"}'

curl https://mint.mintbot.ai/api/v1/dns/records \
  -H "Authorization: Bearer $MINTBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"subdomain": "www", "ip": "203.0.113.10"}'

# Verify.
curl "https://mint.mintbot.ai/api/v1/dns/records" \
  -H "Authorization: Bearer $MINTBOT_API_KEY"
import os, requests

URL = "https://mint.mintbot.ai/api/v1/dns/records"
H = {"Authorization": f"Bearer {os.environ['MINTBOT_API_KEY']}"}

for sub in ("", "www"):
    r = requests.post(URL, headers=H, json={"subdomain": sub, "ip": "203.0.113.10"})
    r.raise_for_status()
    print(sub or "@", r.json()["records"])

Webhooki

Kad ar pasūtījumu kaut kas notiek, mēs nosūtām (POST) parakstītu JSON notikumu uz tavu konfigurēto webhook URL.

Webhooki ir neobligāti

Webhook URL un webhooka parakstīšanas noslēpums sadaļā Settings → API access ir pilnībā neobligāti — ja saņēmēja vēl nav, ievadīšanas laikā atstāj tos tukšus. Vadības panelis un pārējais API bez webhookiem darbojas lieliski; dzīvesciklam vari sekot, aptaujājot GET /api/v1/orders/{id}. Pievieno URL (un ģenerē noslēpumu), kad esi gatavs — atkārtota aktivizācija nav vajadzīga.

Notikumu tipi

Notikums Kad tiek nosūtīts
order.created Stripe Checkout sesija izveidota, gaida maksājumu.
order.paid Stripe apstiprināja maksājumu. Ieņēmumu notikums ierakstīts.
order.cancelled Pasūtījumam iestājās noilgums vai tas tika skaidri atcelts.
agent.provisioning_started Šim pasūtījumam sākās izvietošanas plūsma.
agent.ready Izvietošana izdevās. Payload satur panel_url un expires_at.
agent.failed Izvietošanas plūsma beidzās ar kļūdu. Skati lauku error, lai redzētu, kurš solis neizdevās.
agent.expired Aģenta darbības laiks beidzies. Partneris var to pagarināt ar POST /orders/{id}/renew.
agent.resumed Iepriekš beidzies aģents tika pagarināts pārejas perioda laikā un atkal darbojas. Atjaunošanās pretstats notikumam agent.expired.

Piegāde un atkārtoti mēģinājumi

  • Līdz 7 mēģinājumiem ar eksponenciālu grafiku: 0s, 30s, 2m, 10m, 1h, 6h, 24h.
  • Pēc pēdējā mēģinājuma piegāde tiek atzīmēta kā exhausted, un mēģinājumi apstājas.
  • Apstiprini saņemšanu, atbildot ar 2xx statusu 10 sekunžu laikā.

Pieprasījuma galvenes

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

Payload paraugs — 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"
}

Paraksta pārbaude

Paraksts ir HMAC-SHA256(secret, "{timestamp}.{raw_body}"). Vienmēr pārbaudi neapstrādāto pieprasījuma saturu — ja parsēto JSON serializēsi no jauna, salīdzinājums vairs nesakritīs.

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

Idempotenti saņēmēji

Izmanto X-Mintbot-Event-Id kā deduplikācijas atslēgu — atkārtotie mēģinājumi izmanto to pašu id, tāpēc rindas līmeņa INSERT … ON CONFLICT DO NOTHING šajā kolonnā pasargā tavu apstrādātāju.

Atsauces portāls

Palaižams pilns atsauces piemērs atrodas repozitorijā mintbot-ai/partner-portal-example — FastAPI + SQLite, iepakots Docker konteinerā, ar piemēra zīmolu ExampleAI, ko forko un nomaini pret savu. Arhitektūras kopaina — kā veikals, šis API, izvietošanas process un pielāgojumu repozitorijs sader kopā — ir lapā MintOffice — tehniskā daļa. Portāls īsteno:

  • sākumlapu / plānu izvēli / pateicības un atcelšanas lapas,
  • POST /buyPOST /api/v1/orders → novirzīšanu uz Stripe,
  • POST /webhooks/mintoffice ar iepriekš minēto HMAC pārbaudi,
  • /admin notikumu pārlūku ar HTTP Basic autentifikāciju, kur apskatīt piegādes.

Forko to, failā .env iestati PARTNER_BRAND, MINTOFFICE_API_KEY un MINTOFFICE_WEBHOOK_SECRET, palaid docker compose up un norādi sava partnera ieraksta webhook URL uz https://<your-host>/webhooks/mintoffice. Pilnu pamācību skati lapā MintOffice → Atsauces portāls.


Kļūdas

Katra kļūdas atbilde satur stabilu kodu code, pēc kura vari sazaroties programmatiski. Lauks message ir cilvēkam lasāms skaidrojums un starp laidieniem var mainīties. request_id atkārto atbildes galveni X-Request-Id — iekļauj to atbalsta pieteikumos.

{
  "error": {
    "code": "invalid_api_key",
    "message": "API key is unknown or revoked.",
    "request_id": "f0c2d6c4-…"
  }
}
Kods Nozīme
unauthenticated Trūkst Authorization galvenes vai tā ir nepareizā formā.
invalid_api_key API atslēga nav zināma vai ir nomainīta rotācijā.
rate_limited Pārsniegts partnera vai IP pieprasījumu limits — skati Retry-After.
missing_idempotency_key POST pieprasījums bez Idempotency-Key.
idempotency_key_mismatch Tā pati atslēga izmantota atkārtoti ar citu pieprasījuma saturu.
validation_error Pieprasījuma saturs neizturēja shēmas validāciju.
not_found Resurss neeksistē vai nepieder tavam partnerim.
payment_gateway_error Stripe noraidīja Checkout sesijas izveidi.
dns_not_configured POST /dns/records partnerim bez apex domēna / DNS akreditācijas datiem. Labo sadaļā Settings → Domain.
dns_provider_unsupported Partnera dns_provider vērtība vēl nav pieslēgta MintOffice starpniekservisam.
dns_provider_error Augšupējais DNS nodrošinātājs atgrieza kļūdu — message satur izvilkumu ar aizklātiem noslēpumiem.
quota_exceeded Partneris ir izmantojis visas izvietošanas vietas (pēc noklusējuma 10). Sazinies ar mintbot atbalstu, lai palielinātu limitu. Atgriež POST /orders un POST /orders/{id}/renew. Atbilde satur deploys_used + deploy_quota.

Pieprasījumu limiti

  • 120 pieprasījumi / 60 s slīdošā logā katram partnerim. Pīķa un vienmērīgā slodze izmanto vienu kopīgu limitu.
  • 60 pieprasījumi / 60 s atsevišķs limits katrai IP adresei neautentificētiem un neveiksmīgas autentifikācijas pieprasījumiem — lai Bearer tokena minēšana neizsmeltu partnera kvotu.
  • Pārsniedzot limitu, atbilde ir 429 rate_limited ar galveni Retry-After (cik sekunžu jāpagaida).

Vajadzīga palīdzība?

Šī dokumentācija ir rakstīta partneriem, kuri API patiešām lieto. Ja kaut kā trūkst, kaut kas ir neskaidrs vai novecojis, pasaki to savam mintbot aģentam — tas pārsūtīs atsauksmi, un mēs atjaunināsim lapu.