# Axiona API — machine-readable reference

Base URL: `https://axionna.org`

This is the canonical compact reference for AI assistants and integrations. The human-friendly guide is at `/api-docs`.

## Authentication

Partner endpoints require a connected bot API key in every request:

```http
Authorization: Bearer AXIONNA_API_KEY
Content-Type: application/json
```

Never send API keys in a query string. A blocked user is rejected with HTTP `403` on user-scoped endpoints.

## Integration flow

1. Call `POST /api/sponsors` for a verified bot audience member.
2. Display each returned `link` to the user and retain each returned `id`.
3. Call `POST /api/check` with those exact IDs after the user has completed the tasks.
4. Treat `credited: true` as the only indication that a reward was newly credited.

## POST /api/sponsors

Returns tasks for one Telegram user. The request is made with the publisher bot's API key.

Request body:

```json
{
  "user_id": 123456789,
  "chat_id": 123456789,
  "max_sponsors": 5,
  "username": "telegram_user",
  "first_name": "User",
  "language_code": "ru",
  "is_premium": false,
  "gender": "male",
  "age": 25
}
```

Required field: `user_id` (positive integer). `chat_id` is optional for private-bot requests and defaults to `user_id`; group and campaign integrations must pass the source chat ID explicitly. Other profile fields are advisory targeting data; do not fabricate them.

Successful response shape:

```json
{
  "status": "ok",
  "flow": "default",
  "campaign_id": null,
  "wave_id": 1,
  "access_granted": false,
  "already_joined": false,
  "sponsors": [{
    "id": "tgrass:example",
    "source": "tgrass",
    "link": "https://t.me/example",
    "title": "Sponsor 1",
    "button_text": "Sponsor 1",
    "price": null,
    "reward": "0.8",
    "external_id": "123",
    "target_url": "https://t.me/example",
    "target_kind": "chat",
    "verification_mode": "member",
    "redirected": false
  }],
  "errors": null
}
```

For an unregistered user the response has `registration_required: true` and contains only the registration task. For an empty task list, display no completion claim.

## POST /api/check

Checks the tasks previously returned by `/api/sponsors`.

```json
{
  "user_id": 123456789,
  "task_ids": ["tgrass:example", "piarflow:example"]
}
```

`task_ids` is the required integration format. `links` is a legacy fallback and must only contain links that Axiona previously issued to this user.

```json
{
  "status": "ok",
  "results": [{
    "id": "tgrass:example",
    "source": "tgrass",
    "link": "https://t.me/example",
    "status": "not_allowed",
    "subscribed": false,
    "reward": "0",
    "credited": false,
    "error": null
  }],
  "all_subscribed": false
}
```

If TGrass returns `status=offer_expired` or `is_fake=true`, Axionna closes the task without a payout and the publisher API returns `status=not_allowed`, `subscribed=false`, `reward=0`, and `credited=false`. Such a task is not returned again by `/api/sponsors`.

If `subscribed` is false, the task has not been confirmed or is not allowed. If `subscribed` is true but `credited` is false, it was already credited earlier.

## POST /api/views

Reports a view from a connected publisher bot. Use the endpoint only for a real user-visible impression and give each event a stable `impression_id` generated by your bot.

Authentication: partner bot API key. See `/api-docs` for the current view-placement parameters and response fields.

## POST /api/balance

Returns the connected bot owner's balance. Authentication: partner bot API key.

## Errors

| HTTP | Meaning |
|---|---|
| `400` | Invalid request data |
| `401` | Missing or invalid API key |
| `403` | Blocked user, stopped bot, or denied operation |
| `404` | Unknown resource or expired link |
| `429` | Rate limit exceeded; retry with backoff |
| `5xx` | Temporary server/provider failure; retry safely |

## Minimal Python example

```python
import requests

headers = {"Authorization": "Bearer AXIONNA_API_KEY"}
payload = {"user_id": 123456789, "chat_id": 123456789, "max_sponsors": 5}
offers = requests.post("https://axionna.org/api/sponsors", json=payload, headers=headers, timeout=15).json()
task_ids = [task["id"] for task in offers.get("sponsors", [])]
result = requests.post(
    "https://axionna.org/api/check",
    json={"user_id": payload["user_id"], "task_ids": task_ids},
    headers=headers,
    timeout=20,
).json()
```
