Create a reseller

Create a new account inside the reseller tree. The behavior depends on the calling key. An admin key can create a top-level reseller in either billing mode with any starting balance. A reseller key can only create a sub-reseller under its own account, in the same billing mode as the parent, with a zero starting balance.

The endpoint runs the check and the insert inside a single transaction with a SELECT ... FOR UPDATE on the caller's own row, so two concurrent creates can never over-allocate slots or double-spend credits. Retries covered by the idempotency key never provision a duplicate account.

Endpoint

POST https://<your-panel-domain>/panel-api/v1/resellers

Authentication

Send the API key in the Authorization: Bearer <your-api-key> header. Both admin and reseller keys can call this endpoint. Which parameters they can send differs (see below).

Required scope

subresellers:write

Admin keys also carry this scope by default. It is called subresellers:write (not resellers:write) so a reseller key can hold the write half of the reseller graph without being able to touch anyone else's account.

Idempotency

Every POST must include an Idempotency-Key header. Reusing the same key with the same body replays the cached response; reusing it with a different body returns 409 idempotency_conflict. Use a stable value such as the invoice ID or CRM record ID that triggered the provision, so a network retry never creates a second reseller with a suffixed username.

Request body

Field Type Required Default Description
username string yes Login name. Minimum 3 characters. Cannot contain % & ? # / \ = + @ : ;.
password string yes Login password. Minimum 8 characters, same character restrictions as username.
email string yes Validated with FILTER_VALIDATE_EMAIL.
member_group_id int admin only Which member group the new reseller belongs to. Ignored on reseller keys (the target group is fixed by the panel admin's sub-reseller setup).
credits float admin only 0 Starting credit balance. Forced to 0.0 for reseller-key callers; top up later with POST /resellers/{id}/billing/adjust.
billing_mode string admin only "credits" Either "credits" or "users". Any other value falls back to "credits". Reseller-key callers inherit the parent's mode; the field is ignored.
max_users int conditional 0 Required when billing_mode is "users", and must be positive.
billing_expires int conditional Unix timestamp in seconds. Required when a reseller-key caller in users mode creates a sub-reseller. Optional for admin-key calls.
owner_id int admin only panel admin Parent account for the new reseller. Reseller-key callers must either omit this field or send their own ID; any other value returns 403 owner_must_be_self.
notes string no "" Free-form label kept alongside the reseller record.
{
  "username": "reseller_new",
  "password": "s3cret-p4ssword",
  "email": "reseller_new@example.com",
  "member_group_id": 4,
  "credits": 10.0,
  "billing_mode": "credits",
  "notes": "docs batch fixture"
}

Response

On success the endpoint returns 201 Created with the new ID, the billing snapshot the account starts with, and credits_charged, which reflects how many credits were deducted from the caller. For admin-key calls that field is always 0. For reseller-key calls in credits mode it matches the per-creation price configured on the caller's group.

{
  "id": 262260,
  "username": "reseller_new",
  "email": "reseller_new@example.com",
  "member_group_id": 4,
  "owner_id": 260897,
  "credits_charged": 0,
  "billing": {
    "mode": "credits",
    "credits": 10,
    "max_users": null,
    "active_users": null,
    "billing_expires": null
  }
}

Examples

cURL

curl -X POST https://<your-panel-domain>/panel-api/v1/resellers \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: crm-signup-90142" \
  -d '{
        "username": "reseller_new",
        "password": "s3cret-p4ssword",
        "email": "reseller_new@example.com",
        "member_group_id": 4,
        "credits": 10.0,
        "billing_mode": "credits",
        "notes": "docs batch fixture"
      }'

PHP SDK

require __DIR__ . '/api-panel-php-sdk-1.0.0/autoload.php';
use XtreamAI\PanelApi\PanelApiClient;

$client = new PanelApiClient(baseUrl: 'https://<your-panel-domain>', token: '<your-api-key>');
$reseller = $client->resellers->create(
    username:       'reseller_new',
    password:       's3cret-p4ssword',
    email:          'reseller_new@example.com',
    memberGroupId:  4,
    credits:        10.0,
    billingMode:    'credits',
    notes:          'docs batch fixture',
    idempotencyKey: 'crm-signup-90142',
);
echo $reseller->id, PHP_EOL;

Python SDK

from xtream_ai_panel_api import PanelApiClient

client = PanelApiClient(base_url="https://<your-panel-domain>", token="<your-api-key>")
reseller = client.resellers.create(
    username="reseller_new",
    password="s3cret-p4ssword",
    email="reseller_new@example.com",
    member_group_id=4,
    credits=10.0,
    billing_mode="credits",
    notes="docs batch fixture",
    idempotency_key="crm-signup-90142",
)
print(reseller.id)

Errors

HTTP Error slug When it happens How to fix
400 missing_idempotency_key The Idempotency-Key header was not sent. Add the header on every POST. See the Rate limits and Idempotency page.
401 invalid_key Missing, malformed, or unknown API key. Send a live key in Authorization: Bearer <token>.
402 insufficient_credits A reseller-key caller in credits mode does not have enough balance to pay the per-creation price. Top up the caller with POST /resellers/{id}/billing/adjust, then retry.
403 insufficient_scope The key does not carry subresellers:write. Rotate the key with the correct scopes.
403 owner_must_be_self A reseller-key caller passed an owner_id other than their own. Omit owner_id, or set it to the caller's own reg-user ID.
403 sub_reseller_creation_not_allowed The caller's group does not have create_sub_resellers = 1. The panel admin turns this on per group in the CMS.
409 idempotency_conflict The Idempotency-Key was reused with a different body. Generate a new key or resend the original body.
422 validation_error Username, password, or email fails the validators (length, forbidden characters, invalid email). The message carries the reason. This endpoint returns a human message, not a structured details.field. Fix the offending field and resend.
422 insufficient_slots A reseller-key caller in users mode asked for more max_users than they have available. Free slots on the caller, or lower max_users.
422 no_sub_reseller_setup The panel admin has not configured a sub-reseller package for the caller's group. The admin configures it in the CMS.
422 billing_expires_required A reseller-key caller in users mode did not pass billing_expires. Add a positive Unix timestamp.
429 rate_limited The per-key request budget for this minute is spent. Back off and retry after the minute rolls over.

See also