---
title: "action=user_info"
description: "Return the identity of the calling API key: admin or reseller, scopes, and (for reseller keys) member group, billing shape, and permissions."
---

# action=user_info

Returns the identity of the API key that made the call. Admin keys get a small identity block (type, key metadata, scopes). Reseller keys additionally get their `reg_user_id`, `member_group_id`, `member_group_name`, the current `billing` snapshot (mode, credits or slots), and the effective `permissions` object.

This is the safest first request to make against a freshly issued key. It exercises the full auth pipeline (token lookup, IP allow-list, scope filter, rate limit), it has no side effects, and it echoes back exactly the information the panel has about the key.

## Endpoint

`GET https://<your-panel-domain>/panel-api/xc/{accesscode}/admin/index.php?action=user_info`

`POST https://<your-panel-domain>/panel-api/xc/{accesscode}/admin/index.php` (with `action=user_info` in the body)

The `{accesscode}` segment is decorative. Both `/admin/index.php` and `/reseller/index.php` accept the same key types; the caller identity is inferred from the API key, not from the sub-path.

## Authentication

Send the API key one of three ways.

- `?api_key=<token>` query parameter.
- `api_key=<token>` in the POST body.
- `Authorization: Bearer <token>` header.

## Required scope

None. Every valid API key can call `user_info` regardless of its scope set.

## Query parameters

| Name | Type | Required | Default | Description |
| ---- | ---- | -------- | ------- | ----------- |
| `action` | string | Yes | | Must be `user_info`. |
| `api_key` | string | Yes (if not using Bearer) | | The API key. Alternative: `Authorization: Bearer`. |

## Response

The `data` object depends on the calling key type.

For an **admin key**, `type` is `"admin"` and the reseller-specific fields are `null`.

```json
{
  "status": "STATUS_SUCCESS",
  "data": {
    "type": "admin",
    "reg_user_id": null,
    "member_group_id": null,
    "member_group_name": null,
    "billing": null,
    "permissions": null,
    "key": {
      "id": 4211,
      "prefix": "pk_live_examplekey42",
      "scopes": [
        "lines:read",
        "lines:write",
        "packages:read",
        "bouquets:read",
        "streams:read",
        "vods:read",
        "resellers:read",
        "resellers:write",
        "subresellers:write"
      ]
    }
  }
}
```

For a **reseller key**, `type` is `"reseller"` and every reseller field is populated.

```json
{
  "status": "STATUS_SUCCESS",
  "data": {
    "type": "reseller",
    "reg_user_id": 512,
    "member_group_id": 4,
    "member_group_name": "Silver reseller",
    "billing": {
      "mode": "credits",
      "credits": 187,
      "max_users": null,
      "active_users": 42,
      "billing_expires": null
    },
    "permissions": {
      "create_sub_resellers": true,
      "create_trials": true,
      "create_lines": true
    },
    "key": {
      "id": 4287,
      "prefix": "pk_live_examplekey87",
      "scopes": ["lines:read", "lines:write", "packages:read"]
    }
  }
}
```

The full identity shape is described on the [Panel API Authentication page](/docs/?page=panel-api-authentication#the-me-endpoint). This action maps to the native `GET /panel-api/v1/me` endpoint, and the payload above is the native `data` returned unchanged inside the XC envelope.

## Examples

### cURL

```bash
curl "https://<your-panel-domain>/panel-api/xc/panel_api/admin/index.php?api_key=<your-api-key>&action=user_info"
```

### PHP raw

```php
$url = 'https://<your-panel-domain>/panel-api/xc/panel_api/admin/index.php'
     . '?' . http_build_query([
         'api_key' => '<your-api-key>',
         'action'  => 'user_info',
       ]);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$raw = curl_exec($ch);
curl_close($ch);
$body = json_decode($raw, true);
if (!is_array($body) || ($body['status'] ?? '') !== 'STATUS_SUCCESS') {
    throw new RuntimeException('user_info failed: ' . ($body['data']['message'] ?? 'unknown'));
}
$identity = $body['data'];
echo $identity['type'], "\n";                    // 'admin' or 'reseller'
echo implode(',', $identity['key']['scopes']);   // scope list
```

### Python raw

```python
import requests

r = requests.get(
    "https://<your-panel-domain>/panel-api/xc/panel_api/admin/index.php",
    params={"api_key": "<your-api-key>", "action": "user_info"},
    timeout=30,
)
r.raise_for_status()
body = r.json()
if body["status"] != "STATUS_SUCCESS":
    raise RuntimeError(f"user_info failed: {body['data'].get('message')}")
identity = body["data"]
print(identity["type"], identity["key"]["prefix"], identity["key"]["scopes"])
```

## Errors

Every response is HTTP 200. The `status` field carries the outcome.

| `status` | `error` slug | When it happens | How to fix |
| -------- | ----------- | --------------- | ---------- |
| `STATUS_INVALID_DATA` | `validation_error` | The `action` parameter is missing. | Include `action=user_info` in the query or body. |
| `STATUS_FAILURE` | `invalid_key` | The API key was not sent, is not recognized, has been revoked, or is malformed. | Verify the key value and that it was not rotated in the panel. |
| `STATUS_FAILURE` | `caller_disabled` | The reseller behind the key is banned or their license expired. | Contact the panel admin. |
| `STATUS_FAILURE` | `rate_limited` | The key exceeded its per-minute request budget. | Slow down and read the `X-RateLimit-*` response headers. See [Rate limits & Idempotency](/docs/?page=panel-api-rate-limits-idempotency). |
| `STATUS_FAILURE` | `api_disabled` | The panel operator flipped the Panel API kill switch. | Wait for the API to be re-enabled by the admin. |

## See also

- [XC and XUI API Reference](/docs/?page=xc-ref-overview). Envelope, authentication, and the full action list.
- [Panel API Authentication](/docs/?page=panel-api-authentication). Full identity shape and scope reference.
- [Panel API Errors](/docs/?page=panel-api-errors). The catalog of native error slugs.
