Skip to main content
Use the user billing endpoints to read your team’s credit balance and buy top-ups with a saved payment method. Both endpoints require authentication with your API key. Invalid keys return 402.

Check credit balance

GET /user/credits/info returns the authenticated team’s credit balance, a per-lot breakdown, active subscription details, and whether usage is allowed. Use this endpoint to power billing widgets, usage dashboards, or pre-flight checks before running large jobs. For API details see Get credit info.
import requests

response = requests.get(
    "https://api.olostep.com/user/credits/info",
    headers={"Authorization": "Bearer <API-TOKEN>"},
)
print(response.json())

Response

{
  "credits": 12500,
  "breakdown": [
    {
      "purchase_kind": "Subscription",
      "allocated_units": 10000,
      "remaining_units": 8500,
      "expiry_date": 1735689600
    },
    {
      "purchase_kind": "Top-up",
      "allocated_units": 5000,
      "remaining_units": 4000,
      "expiry_date": 1743465600
    }
  ],
  "active_subscription": {
    "id": "SUB_PRO",
    "display_name": "Pro",
    "credits": 10000,
    "created_at": 1704067200
  },
  "allow_usage": true
}
FieldDescription
creditsTotal remaining credits across all non-expired lots
breakdownPer-lot detail: type, allocated and remaining units, expiry
active_subscriptionCurrent plan (falls back to SUB_BASE if none is active)
allow_usageWhether the team can still consume credits
Each lot in breakdown has a purchase_kind of Subscription, Top-up, Manual, Setup, or Pending.

Purchase a top-up

POST /user/purchase-topup charges a saved card on Stripe and buys credits in one step. There is no Checkout redirect or embedded payment UI. Pass the credit amount in the request body:
{ "credits": 10000 }
FieldDescription
creditsNumber of credits to purchase
Supported values: 10,000, 20,000, 80,000, and 100,000. For API details see Purchase top-up.
import requests

response = requests.post(
    "https://api.olostep.com/user/purchase-topup",
    headers={
        "Authorization": "Bearer <API-TOKEN>",
        "Content-Type": "application/json",
    },
    json={"credits": 10000},
)
print(response.status_code)
print(response.json())

Requirements

  • The team must have a Stripe customer with at least one saved card.
  • Only one purchase attempt is allowed every 60 seconds per team. If you hit the cooldown, the response is 429 with a Retry-After header.

Responses

200 — payment succeeded:
{
  "success": true,
  "payment_intent_id": "pi_xxx",
  "credits": 10000
}
202 — payment is still processing. Credits are added once Stripe confirms the payment:
{
  "success": true,
  "status": "processing",
  "payment_intent_id": "pi_xxx",
  "message": "Payment is processing. Credits will be added once the payment is confirmed.",
  "credits": 10000
}
Credits are issued by the Stripe webhook after payment confirmation, not directly from the HTTP response. Treat 200 as payment success; poll GET /user/credits/info if you need to confirm the updated balance.

Common errors

StatusErrorWhen
400missing_topup_selectorcredits was not sent
400invalid_creditsCredit amount is not in the allowed list
400no_stripe_customerTeam has no Stripe customer
400no_payment_methodNo saved card on file
402payment_failedNo saved card completed the charge
429purchase_topup_cooldownAnother purchase was attempted within 60 seconds
503payment_status_unknownAmbiguous Stripe error; wait before retrying