OneProvider
Reseller API

Reseller API orders

Build your own shop: the client pays you, you call POST /orders and get a key. Idempotency by external_order_id and top-ups of existing keys.

Build your own shop: the client pays you, you call POST /orders and get a key. Idempotency by external_order_id and top-ups of existing keys.

All models, capabilities, and prices Documentation index for AI agents: https://oneprovider.dev/docs/llms.txt

The sales flow

  1. Your client pays you on your site through your own checkout (OneProvider is not part of that payment).
  2. Your server gets the payment confirmation and calls POST /orders.
  3. OneProvider reserves the key limit on your reseller balance (the money is debited as it is spent) and creates an order with the status completed.
  4. You give the client the key from the response and, if you like, the dashboard_url.

An order either issues a new key (kind: "new_key") or tops up an existing one (kind: "topup" when key_id is passed).

Create an order

What to deliver is set by a plan (plan_id, see Codes & plans ) or directly by an amount: limit_usd and expires_days or expires_hours. The customer can be passed as customer_id or customer_external_id (a customer created earlier). The fields charged_amount and charged_currency record what the client paid you; they feed GET /stats and do not affect the charge.

bash
curl -s -X POST https://app.oneprovider.dev/partner/v1/orders \
-H "Authorization: Bearer $OP_PARTNER_TOKEN" \
-H "Idempotency-Key: shop-1042" \
-H "Content-Type: application/json" \
-d '{
"external_order_id": "shop-1042",
"limit_usd": "10.00",
"expires_days": 30,
"customer_external_id": "user-77",
"name": "anna-main",
"charged_amount": "890.00",
"charged_currency": "RUB"
}'
json
{
"id": "<order id>",
"external_order_id": "shop-1042",
"status": "completed",
"kind": "new_key",
"key_id": "<key id>",
"amount_usd": "10.00",
"charged_amount": "890.00",
"charged_currency": "RUB",
"created_at": "2026-10-08T12:00:00Z",
"key": "sk-..."
}

The key secret comes only for a new key and only in the first response. Store it in the same transaction in which you record the order.

Idempotency by external_order_id

external_order_id is the order number in your system. Repeating a request with the same number and the same parameters does not issue a second key or charge twice: you get the same order back (without the key secret this time). The same number with different parameters gives 409 external_order_id_conflict. That makes it safe to retry after a timeout or a dropped connection. You can find an order with GET /orders?external_order_id=shop-1042.

Top up an existing key

Pass key_id and an amount (limit_usd or a plan):

bash
curl -s -X POST https://app.oneprovider.dev/partner/v1/orders \
-H "Authorization: Bearer $OP_PARTNER_TOKEN" \
-H "Idempotency-Key: shop-1043" \
-H "Content-Type: application/json" \
-d '{"external_order_id":"shop-1043","key_id":"<key id>","limit_usd":"10.00","charged_amount":"890.00","charged_currency":"RUB"}'

In the response kind is topup and there is no secret. The amount is added to the key's total limit and, like everything, has to fit into Free (it is reserved and debited as it is spent).

Payment handler example (Python)

python
import os
import requests
BASE = "https://app.oneprovider.dev/partner/v1"
HEADERS = {"Authorization": "Bearer " + os.environ["OP_PARTNER_TOKEN"]}
def fulfil_paid_order(order_no: str, user_id: str, plan_id, paid: str, currency: str) -> dict:
"""Call it after YOUR payment provider confirmed the payment (it may be called twice)."""
r = requests.post(
BASE + "/orders",
headers={**HEADERS, "Idempotency-Key": "order-" + order_no},
json={
"external_order_id": order_no,
"plan_id": plan_id,
"customer_external_id": user_id,
"charged_amount": paid,
"charged_currency": currency,
},
timeout=30,
)
if r.status_code == 409 and r.json()["error"]["code"] == "insufficient_balance":
raise RuntimeError("Top up the reseller balance, then retry the same call")
r.raise_for_status()
order = r.json()
# order["key"] is present only on the first response of a new_key order
return order

Watch available_usd and subscribe to the balance.low webhook so that you top up before an order hits 409 insufficient_balance. See Webhooks .

Last updated: 2026-10-21 Found a bug? @Oneproviderhelpbot