Автентифікація
Один заголовок у кожному запиті, крім індексу з описом API.
Authorization: Bearer <your api key>
Токени створюються на сторінці профілю - до
десяти на обліковий запис, кожен можна відкликати окремо, тож токен, що
потрапив до сторонніх, можна видалити, не зачіпаючи інших. Потрібен платний
тариф: без нього всі ендпоінти, крім / і /v1/account,
відповідають 403 plan_required.
Застосунок також може отримати токен для вас через OAuth 2.1: ви входите, бачите, що він запитує, і натискаєте «Дозволити». Його токен передається в тому самому заголовку й працює так само.
Чому не ?key=
Ключ у рядку запиту потрапляє туди, куди ви його не клали: у журнали
доступу вебсервера, історію браузера, журнали проксі та заголовок
Referer усього, на що посилається відповідь. Тому API його не
приймає й відповідає 401 missing_key з поясненням.
Старі URL з ?export= на основному сайті досі приймають
?key=, бо від цього залежать скрипти, написані багато років
тому, і прибрати його означало б їх зламати. Це єдине місце, де він
залишився, - див. старі URL експорту.
Як перевірити, що ключ працює
/v1/account - найдешевший виклик: він не витрачає денного ліміту
й працює навіть на обліковому записі без тарифу, тож відповідає і на
запитання «чи дійсний цей ключ», і на «що мені доступно».
curl -H "Authorization: Bearer $KEY" https://api.publicwww.com/v1/account
{
"plan": "enterprise",
"plan_until": 1819461840,
"full_access": true,
"quota": {
"searches": { "limit": 300, "used": 12, "resets_at": 1787961600 },
"snippets": { "limit": 100, "used": 3, "resets_at": 1787961600 }
},
"limits": {
"disclosed_positions": 4294967295,
"max_per_page": 1000000,
"max_per_page_snippets": 10000
}
}
Що може піти не так
| Статус | Код | Значення |
|---|---|---|
| 401 | missing_key | Немає заголовка Authorization: Bearer. Ключ у рядку запиту не рахується. |
| 401 | invalid_key | Ключ не належить жодному обліковому запису. Перевірте, чи не потрапив зайвий перенос рядка або лапка. |
| 403 | plan_required | Із ключем усе гаразд, але в облікового запису немає платного тарифу. |
Відповідь 401 також містить заголовок WWW-Authenticate: Bearer,
тож HTTP-клієнти, які обробляють автентифікацію універсально, поводяться
правильно.
OAuth 2.1 для застосунків
Застосунок, що працює від імені інших людей, - асистент, інтеграція,
хмарний сервіс, - не повинен просити кожного з них скопіювати токен.
Натомість він відправляє їх до PublicWWW: вони входять, схвалюють
застосунок, і той отримує власний токен. Цей токен передається як
Authorization: Bearer, як і будь-який інший, і відкриває все
API та MCP-сервер за адресою https://api.publicwww.com/mcp
у межах тарифу, денного ліміту й обмеження частоти облікового запису.
| Що | Де |
|---|---|
| Метадані сервера авторизації (RFC 8414) | https://publicwww.com/.well-known/oauth-authorization-server |
| Метадані захищеного ресурсу (RFC 9728) | https://api.publicwww.com/.well-known/oauth-protected-resource |
| Ендпоінт авторизації | https://publicwww.com/oauth/authorize |
| Ендпоінт токенів | https://publicwww.com/oauth/token |
| Ендпоінт відкликання (RFC 7009) | https://publicwww.com/oauth/revoke |
Ідентифікація застосунку
Реєстрації клієнтів немає. client_id - це https-URL
невеликого JSON-документа, який публікує застосунок, - документа метаданих
клієнта. PublicWWW читає його щоразу, коли хтось підключається, тож назва
й адреси повернення завжди актуальні, а людина, яка дає дозвіл, бачить, який
хост їх опублікував.
{
"client_id": "https://app.example.com/oauth/client.json",
"client_name": "Example App",
"redirect_uris": ["https://app.example.com/oauth/callback"],
"grant_types": ["authorization_code"],
"response_types": ["code"],
"token_endpoint_auth_method": "none"
}
-
client_idусередині документа має точно збігатися з URL, за яким документ віддається. Документ завантажується через https, з URL, що містить шлях, без переходу за перенаправленнями; він має відповісти протягом 5 секунд і бути меншим за 64 КБ. -
redirect_uris- це https-адреси або http на127.0.0.1,localhostчи[::1]для застосунку, що працює на власному комп’ютері користувача, - там підходить будь-який порт. Власні схеми на кшталтmyapp://не приймаються. -
Кожен застосунок - публічний клієнт: запит токена не містить секрету,
хоч би який
token_endpoint_auth_methodбув указаний у документі. Код авторизації натомість захищає PKCE.
Процес
Код авторизації з PKCE; єдиний метод - S256. Відправте
людину на ендпоінт авторизації:
https://publicwww.com/oauth/authorize
?response_type=code
&client_id=https%3A%2F%2Fapp.example.com%2Foauth%2Fclient.json
&redirect_uri=https%3A%2F%2Fapp.example.com%2Foauth%2Fcallback
&code_challenge=<BASE64URL(SHA-256(code_verifier))>
&code_challenge_method=S256
&state=<random>
Якщо людина ще не ввійшла, вона входить за одноразовим кодом, надісланим
на електронну пошту, бачить назву застосунку, хост його документа й адресу,
куди повернеться, і натискає «Дозволити» або «Скасувати». На
redirect_uri повертаються code, ваш
state і iss=https://publicwww.com (RFC 9207). Код
дійсний десять хвилин і спрацьовує один раз. Обміняйте його:
curl https://publicwww.com/oauth/token \
-d grant_type=authorization_code \
-d code="$CODE" \
-d code_verifier="$VERIFIER" \
-d client_id=https://app.example.com/oauth/client.json \
-d redirect_uri=https://app.example.com/oauth/callback
{ "access_token": "<token>", "token_type": "Bearer", "scope": "mcp" }
scope можна не вказувати: область доступу одна, mcp,
і вона охоплює все API. resource (RFC 8707) теж можна не
вказувати; якщо його передано, це https://api.publicwww.com/mcp
або https://api.publicwww.com.
Скільки живе токен
Доки його не відкличуть: строку дії немає, токена оновлення теж. Інтеграція, яка працює сьогодні, працюватиме й завтра, без жодного втручання. Токен відкликається лише навмисно: людина відключає застосунок на своїй сторінці профілю, застосунок сам відкликає токен або обліковий запис видаляють.
curl https://publicwww.com/oauth/revoke \
-d token="$TOKEN" \
-d client_id=https://app.example.com/oauth/client.json
Ендпоінт відкликання завжди відповідає 200 - незалежно від
того, чи існував токен.
Помилки OAuth
| Де | Код | Значення |
|---|---|---|
| Авторизація | сторінка помилки | Не вдалося прочитати документ client_id, або в ньому немає redirect_uri. Людину не повертають назад: за неперевіреною адресою перехід не виконується ніколи. |
| Авторизація | invalid_request | Немає code_challenge, або метод інший, ніж S256. |
| Авторизація | unsupported_response_type | Будь-що, крім response_type=code. |
| Авторизація, токен | invalid_target | resource, що не є цим API. |
| Авторизація | access_denied | Людина натиснула «Скасувати». |
| Токен | invalid_grant | Код невідомий, уже використаний, прострочений або виданий іншому client_id; або не збігається code_verifier чи redirect_uri. |
| Токен | unsupported_grant_type | Будь-що, крім authorization_code. |
Помилки авторизації, крім сторінки помилки, повертаються на
redirect_uri як error, error_description,
state та iss; помилки токена - це 400
з тими самими двома полями в JSON.