# Numbers API — Cursor agent contract Public. No login. No API key required to read this file. - HTML: `https://onlygirls.click/docs` - Markdown (this file): `https://onlygirls.click/docs.md` - JSON (same contract, structured): `https://onlygirls.click/docs.json` - Plain-text alias: `https://onlygirls.click/llms.txt` This document is the contract. Follow it exactly. Do not invent extra endpoints, parameters, or keys. ``` AUDIENCE: another Cursor agent ORIGIN: https://onlygirls.click READ: this file, /docs.json, or /docs — all public WRITE/SMS: requires a human-provided key nk_... NEVER invent or guess an API key NEVER buy a real number while testing (use country=ger) NEVER call partner hosts; only this origin ``` ## What this service is HTTPS monitor + SMS number API. Two auth worlds: | Surface | Auth | Use | |---|---|---| | SMS number API (`handler_api.php` / `getNumberSelected`) | API key `nk_...` | Get numbers, poll SMS code, cancel | | Browser monitor (`/`, `/api/state`, `/admin`) | login cookie | Humans only. API keys do **not** work here | SMS methods always return HTTP **200**, even for errors. Invalid key → plaintext `BAD_KEY`, not JSON 401. ## Rules for agents 1. Fetch this file or `/docs.json` before calling SMS methods. 2. Never invent or guess an API key. The human must provide `nk_...`. 3. Do **not** buy real numbers while testing. Use `country=ger` on `getNumber` (returns `NO_NUMBERS`). Use unknown 24-hex ids for `getStatus` / `setStatus`. 4. If you accidentally receive `ACCESS_NUMBER`, cancel immediately with `setStatus` `status=-1`. 5. After `getNumber` / `getNumberSelected`, store the **local** 24-hex `activation_id`. Never send a partner/upstream id; this API rewrites ids. 6. `getNumberSelected` success is **JSON**. Every other SMS success/error is **text/plain**. 7. `country` is ISO 3166-1 alpha-2, lowercase (`it`, `gb`, `tj`). `ger` is a safe no-number probe. 8. `operator` is the operator **display name** from the monitor table (example: `TIM - Telecom Italia S.p.A.`). Empty/`any` means any operator. 9. Do not call partner hosts directly. Only this origin. 10. Do not use `Authorization: Bearer`. Only `x-api-key` or `api_key`. 11. FastAPI Swagger is disabled. `/docs` is this contract, not `/openapi.json`. ## Base URLs (GET and POST are equivalent) SMS entrypoints (API key required): - `https://onlygirls.click/stubs/handler_api.php` - `https://onlygirls.click/handler_api.php` - `https://onlygirls.click/api/handler` - `https://onlygirls.click/api/getNumberSelected` — `getNumberSelected` only; no `action` needed Query, `x-api-key` header, `application/x-www-form-urlencoded`, `multipart/form-data`, and JSON body are merged. Non-empty query wins over body. ## API key Pass **one** of (first match wins): ``` x-api-key: nk_... ?api_key=nk_... POST body api_key=nk_... ``` Keys are created in `/admin` by a logged-in admin. This docs page never returns keys. Missing, empty, or unknown key → HTTP 200, `text/plain`, body `BAD_KEY`. ## Methods Four SMS methods. Unknown `action` → `BAD_ACTION`. ### getNumber Issue a phone number for a service + country + operator. | param | required | notes | |---|---|---| | `action` | yes | `getNumber` | | `service` | yes | service code, e.g. `ig` | | `country` | yes | ISO2 lowercase | | `operator` | no | forwarded to partner; empty becomes `any` | | `api_key` | yes unless header | `nk_...` | Response: HTTP 200, `text/plain` ``` ACCESS_NUMBER:: NO_NUMBERS BAD_KEY ``` `` is 24 lowercase hex. Use it as `id` in `getStatus` / `setStatus`. Safe probe (does not buy a number): ```bash curl 'https://onlygirls.click/stubs/handler_api.php?api_key=nk_...&action=getNumber&service=ig&operator=any&country=ger' # expected: NO_NUMBERS ``` ### getNumberSelected Pick one random **checked** operator from the monitor table (same pool as session-only `GET /api/selected`), then buy a number for that country with that operator name. This is the preferred method when the human already selected operators in the UI. | param | required | notes | |---|---|---| | `action` | yes on handler URLs | `getNumberSelected` | | `service` | no | limit to one service code; omit = all codes that have checked rows | | `api_key` | yes unless header | `nk_...` | Shortcut (no `action`): `GET/POST https://onlygirls.click/api/getNumberSelected` Unknown or unchecked `service` → `NO_NUMBERS`. Success: HTTP 200, `application/json` ```json { "issue_id": "6b3c0e2e-2c1a-4f0e-9d5a-1c2b3a4d5e6f", "issued_at": "2026-09-20T13:00:00+00:00", "service": "ig", "id": "86|TIM - Telecom Italia S.p.A.|0", "country_id": 86, "code": "IT", "country_name": "Italy", "operator": "TIM - Telecom Italia S.p.A.", "rate": 238, "activation_id": "6aafd036afdd2a1cdba26133", "phone": "393925063783" } ``` | field | type | meaning | |---|---|---| | `activation_id` | 24-hex string | local id for `getStatus` / `setStatus` | | `phone` | string | digits, no `+` | | `issue_id` | UUID | monitor stats only; do not send it back | | `issued_at` | ISO-8601 UTC | when the number was issued | | `service` | string | service code actually used | | `id` | string | monitor row id (`country_id\|operator\|index`) | | `country_id` | number | partner country id | | `code` | string | ISO2 uppercase in this JSON (`IT`) | | `country_name` | string | English country name | | `operator` | string | display name sent to partner as `operator=` | | `rate` | number | partner rate at issue time | Use `activation_id` as `id`. `issue_id` is monitor stats only. Errors stay plaintext: `NO_NUMBERS` (nothing checked, unknown service, or partner has no number), `BAD_KEY`. ```bash curl 'https://onlygirls.click/api/getNumberSelected?api_key=nk_...&service=ig' ``` POST JSON is also valid: ```bash curl -X POST 'https://onlygirls.click/api/getNumberSelected' \ -H 'content-type: application/json' \ -H 'x-api-key: nk_...' \ -d '{"service":"ig"}' ``` ### getStatus Poll SMS / activation state by **local** id. | param | required | notes | |---|---|---| | `action` | yes | `getStatus` | | `id` | yes | `activation_id` from getNumber / getNumberSelected | | `api_key` | yes unless header | `nk_...` | Response: HTTP 200, `text/plain` (partner text is forwarded after id rewrite) ``` STATUS_WAIT_CODE STATUS_OK: ACCESS_CANCEL NO_ACTIVATION BAD_ACTION BAD_KEY ``` Unknown local id → `NO_ACTIVATION`. `STATUS_OK:852508` means the SMS code is `852508`. The monitor SMS table also tries to replace that bare code with the full SMS text when it arrives. ```bash curl 'https://onlygirls.click/stubs/handler_api.php?api_key=nk_...&action=getStatus&id=6aafd036afdd2a1cdba26133' ``` ### setStatus Change activation state. | param | required | notes | |---|---|---| | `action` | yes | `setStatus` | | `id` | yes | local `activation_id` | | `status` | yes | see table | | `api_key` | yes unless header | `nk_...` | Missing `status` → `BAD_STATUS`. Unknown local id → `NO_ACTIVATION`. | `status` | meaning | typical body | |---|---|---| | `1` | ready / confirm | `ACCESS_READY` | | `6` | activation sent | `ACCESS_ACTIVATION` | | `-1` | cancel | `ACCESS_CANCEL` | | `8` | cancel | `ACCESS_CANCEL` | | `10` | other fail | partner text, often `ACCESS_CANCEL` | Other: `NO_ACTIVATION`, `BAD_STATUS`, `BAD_KEY`. To cancel a test purchase: ```bash curl 'https://onlygirls.click/stubs/handler_api.php?api_key=nk_...&action=setStatus&id=ACTIVATION_ID&status=-1' ``` ## Stats (monitor table, not returned by SMS methods) Written **once** per `getNumberSelected` issue. Later `getStatus` / `setStatus` on the same id do not overwrite. | event | column | |---|---| | number issued | issued | | `getStatus` `STATUS_OK` | success | | `getStatus` `NO_ACTIVATION` / `ACCESS_CANCEL` / `STATUS_CANCEL` | fail | | `setStatus` `-1` or `8` | fail | | `setStatus` `10` | fail_other | | no terminal status for 10 minutes | fail_other | `getNumber` (not selected) does not write monitor issue stats unless it went through `getNumberSelected`. ## Suggested agent flow ``` 1. Confirm key with a safe call (does not buy a number): GET /stubs/handler_api.php?api_key=KEY&action=getNumber&service=ig&country=ger → NO_NUMBERS (key ok) or BAD_KEY 2. Production number (only if the human asked to buy): GET /api/getNumberSelected?api_key=KEY&service=ig → JSON {activation_id, phone, ...} or plaintext NO_NUMBERS 3. Poll every few seconds: GET ...&action=getStatus&id=activation_id → STATUS_WAIT_CODE | STATUS_OK:code | ACCESS_CANCEL | NO_ACTIVATION 4. When done or on failure: GET ...&action=setStatus&id=activation_id&status=-1 ``` ## Out of scope (login cookie, not API key) These return JSON `{"detail":"login required"}` with HTTP 401 if called with only an API key: `GET /api/state`, `GET /api/selected`, `POST /api/result`, `POST /api/refresh`, `GET /api/messages`, `POST /api/messages/settings`, `POST /api/codes`, `POST /api/selection`, `GET /api/admin/*`, `GET /api/health`, UI `/` `/admin`. Do not use them for SMS automation. `GET /api/selected` is the human-monitor twin of `getNumberSelected`; agents must call `getNumberSelected` instead. ## Public URLs (no auth) | URL | body | |---|---| | `GET /docs` | this spec as HTML | | `GET /docs.md` | this spec as Markdown | | `GET /docs.json` | this spec as JSON | | `GET /llms.txt` | same Markdown as `/docs.md` | | `GET /login` | login form | | `GET /static/*` | CSS/JS/assets | ## Origin Canonical HTTPS origin: `https://onlygirls.click` (port 443). HTTP/80 redirects to HTTPS.