Reseller API
Order plans for your customers programmatically — with idempotency, clear errors and copy-ready examples.
Version 1 · https://autopiko.com/api/v1
Reseller API v1
A small JSON REST API for Reseller and Distributor accounts. Buy plans for your own customers programmatically: each order deducts credit from your balance at your group's price and activates the plan for the customer you name.
Your API URL, username and key are shown in your panel under API access. Administrator accounts have their own key too and are treated as Distributor-level with their own balance.
Authentication
Send your secret key as a Bearer token in the Authorization header. Keys look like pp_live_…. You can view and reset your key in your panel at any time; keep it on your server and never put it in a web page or mobile app. Blocked users, disabled API access and IPs outside your allow-list are refused.
Authorization: Bearer pp_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxRate limits
Each account has a per-minute request limit (default 60 per minute, set by the administrator). Exceeding it returns 429 rate_limited with a Retry-After header in seconds. Slow down and retry after that time.
Idempotency
Send an Idempotency-Key header (or idempotency_key in the body) on POST /orders and POST /orders/{id}/renew. Repeating a request with the same key and the same data returns the original order and never charges twice, even when requests arrive in parallel. Reusing a key with different data returns 409. Keys may be up to 80 characters.
/balance
Your current credit balance and group.
curl https://autopiko.com/api/v1/balance \
-H "Authorization: Bearer $PP_KEY"<?php
$ch = curl_init('https://autopiko.com/api/v1/balance');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('PP_KEY')],
]);
$data = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);const res = await fetch('https://autopiko.com/api/v1/balance', {
headers: { Authorization: `Bearer ${process.env.PP_KEY}` },
});
const data = await res.json();
if (!res.ok) throw new Error(data.error.code);Response 200
{
"balance": "125.50",
"currency": "USD",
"group": "reseller"
}/packages
Packages you can order, priced for your group, with the Monthly, Quarterly and Yearly price of each.
curl https://autopiko.com/api/v1/packages \
-H "Authorization: Bearer $PP_KEY"<?php
$ch = curl_init('https://autopiko.com/api/v1/packages');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('PP_KEY')],
]);
$data = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);const res = await fetch('https://autopiko.com/api/v1/packages', {
headers: { Authorization: `Bearer ${process.env.PP_KEY}` },
});
const data = await res.json();
if (!res.ok) throw new Error(data.error.code);Response 200
{
"group": "reseller",
"data": [{
"id": 3, "name": "Pro", "currency": "USD", "price": "8.00",
"prices": [
{ "months": 1, "period": "monthly", "price": "8.00", "saving_percent": 0 },
{ "months": 3, "period": "quarterly", "price": "21.59", "saving_percent": 10 },
{ "months": 12, "period": "yearly", "price": "76.79", "saving_percent": 20 }
],
"duration_days": 30,
"limits": { "accounts": 10, "posts_per_day": 20, "ai_images_per_month": 300 },
"features": ["..."]
}]
}/orders
Create an order: activates the package for a customer and deducts the price from your balance. The customer account is created if it does not exist.
Body parameters
| Field | Type | Required | Description |
|---|---|---|---|
package_id | integer | required | ID from GET /packages. The free trial cannot be ordered. |
customer | string | required | Customer email, or a username (letters, digits, . _ -). |
months | integer | optional | Billing period: 1 Monthly (default), 3 Quarterly or 12 Yearly. period (monthly, quarterly, yearly) is accepted too. |
customer_name | string | optional | Display name for a new customer. |
return_login | boolean | optional | true returns a single-use login link (login_url) for the customer. |
idempotency_key | string | optional | See Idempotency (or send the header). |
If the customer already has the same package active, the order extends it; a different package replaces it (unused time on a paid plan is refunded to your balance pro-rata).
Request
curl -X POST https://autopiko.com/api/v1/orders \
-H "Authorization: Bearer $PP_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1042" \
-d '{"package_id":3,"months":3,"customer":"[email protected]","customer_name":"Jane","return_login":true}'<?php
$ch = curl_init('https://autopiko.com/api/v1/orders');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('PP_KEY'), 'Content-Type: application/json', 'Idempotency-Key: order-1042'],
CURLOPT_POSTFIELDS => json_encode([ 'package_id' => 3,
'months' => 3,
'customer' => '[email protected]',
'customer_name' => 'Jane',
'return_login' => true,]),
]);
$data = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);const res = await fetch('https://autopiko.com/api/v1/orders', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.PP_KEY}`, 'Content-Type': 'application/json', 'Idempotency-Key': 'order-1042' },
body: JSON.stringify({"package_id":3,"months":3,"customer":"[email protected]","customer_name":"Jane","return_login":true}),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error.code);Response 201
{
"order": {
"id": 1042, "kind": "activate", "status": "completed",
"package": { "id": 3, "name": "Pro" }, "months": 3, "period": "quarterly",
"customer": { "id": 77, "reference": "[email protected]", "email": "[email protected]" },
"price": "21.59", "currency": "USD", "expires_at": "2027-01-07T10:15:00Z",
"created_at": "2026-10-09T10:15:00Z", "idempotency_key": "order-1042"
},
"balance": "103.91",
"login_url": "https://autopiko.com/magic/..."
}Response 402 (nothing is charged)
{ "error": { "code": "insufficient_credit", "message": "Your credit balance is too low for this order.",
"details": { "balance": "4.00", "required": "21.59", "currency": "USD" } } }/orders/{id}
One of your orders (same shape as the order object above). 404 for orders that are not yours.
curl https://autopiko.com/api/v1/orders/1042 \
-H "Authorization: Bearer $PP_KEY"<?php
$ch = curl_init('https://autopiko.com/api/v1/orders/1042');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('PP_KEY')],
]);
$data = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);const res = await fetch('https://autopiko.com/api/v1/orders/1042', {
headers: { Authorization: `Bearer ${process.env.PP_KEY}` },
});
const data = await res.json();
if (!res.ok) throw new Error(data.error.code);/orders
Your orders, newest first.
| Field | Type | Required | Description |
|---|---|---|---|
page | integer | optional | Page number, starting at 1. |
limit | integer | optional | Items per page, up to 100 (default 25). |
curl https://autopiko.com/api/v1/orders?page=1&limit=25 \
-H "Authorization: Bearer $PP_KEY"<?php
$ch = curl_init('https://autopiko.com/api/v1/orders?page=1&limit=25');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('PP_KEY')],
]);
$data = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);const res = await fetch('https://autopiko.com/api/v1/orders?page=1&limit=25', {
headers: { Authorization: `Bearer ${process.env.PP_KEY}` },
});
const data = await res.json();
if (!res.ok) throw new Error(data.error.code);Response 200
{ "data": [ { "id": 1042, "status": "completed", "...": "..." } ], "page": 1, "per_page": 25, "total": 3 }/orders/{id}/renew
Renew the package of an earlier order for the same customer: adds one period on top of the current expiry and charges your balance again at your group's price for that period. Supports Idempotency-Key.
| Field | Type | Required | Description |
|---|---|---|---|
months | integer | optional | 1, 3 or 12. Defaults to the period of the original order. |
curl -X POST https://autopiko.com/api/v1/orders/1042/renew \
-H "Authorization: Bearer $PP_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1042" \
-d '{"months":3}'<?php
$ch = curl_init('https://autopiko.com/api/v1/orders/1042/renew');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('PP_KEY'), 'Content-Type: application/json', 'Idempotency-Key: order-1042'],
CURLOPT_POSTFIELDS => json_encode([ 'months' => 3,]),
]);
$data = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);const res = await fetch('https://autopiko.com/api/v1/orders/1042/renew', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.PP_KEY}`, 'Content-Type': 'application/json', 'Idempotency-Key': 'order-1042' },
body: JSON.stringify({"months":3}),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error.code);/customers/{id}
Status of a customer you created. GET /customers lists them. Other people's customers return 404.
curl https://autopiko.com/api/v1/customers/77 \
-H "Authorization: Bearer $PP_KEY"<?php
$ch = curl_init('https://autopiko.com/api/v1/customers/77');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('PP_KEY')],
]);
$data = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);const res = await fetch('https://autopiko.com/api/v1/customers/77', {
headers: { Authorization: `Bearer ${process.env.PP_KEY}` },
});
const data = await res.json();
if (!res.ok) throw new Error(data.error.code);Response 200
{ "customer": { "id": 77, "name": "Jane", "email": "[email protected]", "status": "active",
"plan": { "package": "Pro", "active": true, "starts_at": "2026-10-09T10:15:00Z", "expires_at": "2027-01-07T10:15:00Z", "days_left": 90 },
"created_at": "2026-10-09T10:15:00Z" } }Errors & status codes
Errors use standard HTTP status codes and a JSON body with a stable machine-readable code:
{ "error": { "code": "invalid_package", "message": "package_id is missing or not an available package.", "details": {} } }| HTTP | Codes | Meaning |
|---|---|---|
| 200 / 201 | — | OK / order created |
| 400 / 413 / 422 | invalid_json payload_too_large invalid_package package_unavailable invalid_customer invalid_months invalid_idempotency_key order_failed | Invalid JSON, body too large or a validation problem |
| 401 | missing_api_key invalid_api_key revoked_api_key | Missing, unknown or revoked key |
| 402 | insufficient_credit | Your balance is too low; nothing was charged |
| 403 | account_blocked api_disabled ip_not_allowed | Account blocked, API turned off or IP outside your allow-list |
| 404 / 405 | not_found order_not_found customer_not_found method_not_allowed | Unknown endpoint, order or customer, or wrong HTTP method |
| 409 | customer_not_yours idempotency_conflict | The customer belongs to someone else, or a key was reused with different data |
| 429 | rate_limited | Too many requests; see Retry-After |