API آنپیچت
پیامهایت را از هر برنامه یا سروری، در کانال و گروه و کلاس و سانترالِ خودت منتشر کن.
فایلِ OpenAPI 3.1 است: در Postman و Insomnia مستقیم import میشود و از رویش برای زبانِ خودت SDK ساخته میشود.
curl https://api.onpchat.ir/v1/me \ -H "Authorization: Bearer $ONP_TOKEN"
const r = await fetch("https://api.onpchat.ir/v1/me", { headers: { "Authorization": `Bearer ${process.env.ONP_TOKEN}` }, }); const { ok, result } = await r.json();
import os, requests r = requests.get( "https://api.onpchat.ir/v1/me", headers={"Authorization": f"Bearer {os.environ['ONP_TOKEN']}"}, ) print(r.json())
$ch = curl_init("https://api.onpchat.ir/v1/me"); curl_setopt_array($ch, [ CURLOPT_HTTPHEADER => ["Authorization: Bearer " . getenv("ONP_TOKEN")], CURLOPT_RETURNTRANSFER => true, ]); $res = json_decode(curl_exec($ch), true);
شروع سریع
- توکن بگیر. با حسابی که مدیرِ آن فضاست وارد شو و این آدرس را باز کن:
شناسه با پیشوندش میآید و در URL باید encode شود — مثلاً کانالِ
#1786551855736میشود%231786551855736. اگر توکن نداشته باشی، همانجا ساخته میشود. - توکن را امتحان کن.
- پیام بفرست.
https://onpchat.ir/api/space/api-token?entity_id=<id>
curl -X POST https://api.onpchat.ir/v1/channels/%231786551855736/messages \ -H "Authorization: Bearer $ONP_TOKEN" \ -H "Content-Type: application/json" \ -d '{"text":"Hello from the API"}'
await fetch( "https://api.onpchat.ir/v1/channels/%231786551855736/messages", { method: "POST", headers: { "Authorization": `Bearer ${process.env.ONP_TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify({ text: "Hello from the API" }), }, );
import os, requests requests.post( "https://api.onpchat.ir/v1/channels/%231786551855736/messages", headers={"Authorization": f"Bearer {os.environ['ONP_TOKEN']}"}, json={"text": "Hello from the API"}, )
$url = "https://api.onpchat.ir/v1/channels/%231786551855736/messages"; $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer " . getenv("ONP_TOKEN"), "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode(["text" => "Hello from the API"]), CURLOPT_RETURNTRANSFER => true, ]); curl_exec($ch);
احراز هویت
هر فضا یک توکنِ مستقل دارد که فقط روی همان فضا کار میکند. توکن را در هدر بفرست:
?token= پذیرفته نمیشود. این API مخاطبش سرور است نه مرورگر، و هدرِ CORS هم ندارد. توکن را در جاوااسکریپتِ سمتِ کاربر نگذار — هر بازدیدکنندهای میتواند بردارَدش و از طرفِ فضای تو پیام بفرستد. اگر توکنی لو رفت، از همان پنل باطلش کن؛ توکنِ تازه فوراً جایگزین میشود.Authorization: Bearer onp_2e09e8f0bb35088c795e5f75dc...
شکل پاسخ
شرطهایت را روی error.code بگذار، نه روی message. متنِ پیام برای خواندنِ آدم است و ممکن است عوض شود؛ کد نه.
{ "ok": true, "result": { ... } }
{ "ok": false, "error": {
"code": "invalid_token",
"message": "..."
} }
فضاها
چهار نوع فضا هست و هر کدام پیشوندِ خودش را دارد. پیشوند بخشی از شناسه است و در URL باید encode شود.
| نوع | در مسیر | پیشوند | فرستنده دیده میشود؟ |
|---|---|---|---|
| کانال | channels | # → %23 | نه — پیام از طرفِ خودِ کانال |
| گروه | groups | @ → %40 | بله |
| کلاس | classes | % → %25 | بله |
| سانترال | santrals | & → %26 | بله |
اندپوینتها
| متد | مسیر | کار |
|---|---|---|
| GET | /v1/me | توکن مالِ کدام فضاست |
| GET | /v1/{type}/{id} | مشخصاتِ فضا |
| GET | /v1/{type}/{id}/messages | تاریخچه |
| POST | /v1/{type}/{id}/messages | انتشارِ پیام |
تاریخچه
جدیدترین اول. صفحهبندی با seq است نه با زمان — یک شمارندهٔ یکنواخت که ترتیبِ قطعی میدهد، حتی برای دو پیامِ همزمان. مقدارِ next_cursor را در before_seq صفحهٔ بعد بگذار؛ null یعنی به انتها رسیدهای.
GET /v1/channels/%231786551855736/messages ?limit=30&before_seq=42
{
"ok": true,
"result": {
"messages": [
{
"id": "a1b2c3",
"text": "...",
"seq": 42,
"timestamp": 1788301362311
}
],
"next_cursor": 41
}
}
کارت (پستِ تمیز)
بهجای متنِ خام میتوانی «کارت» بفرستی — همان چیزی که در اپ با «ساختِ کارت» میسازی: کاور، عنوان، متن و لینک، در یک قابِ تمیز.
بهجای text فیلدِ card را بفرست. این دو با هم نمیآیند؛ متنِ همراهِ کارت در caption میرود.
| فیلد | لازم؟ | توضیح |
|---|---|---|
url | بله | لینکی که کارت به آن میرود |
title | نه | عنوانِ کارت |
description | نه | متنِ داخلِ کارت |
image | نه | کاور — باید نشانیِ کاملِ http/https باشد |
caption | نه | متنِ بیرونِ کارت، بهعنوانِ حرفِ خودت |
عکس باید جایی میزبانی شده باشد که از اینترنت باز شود؛ آپلود در این نسخه نیست. نشانیِ نسبی رد میشود، چون کارت روی گوشیِ کاربر رندر میشود و آن آدرس آنجا به جایی نمیرسد.
curl -X POST https://api.onpchat.ir/v1/groups/%401786579451315/messages \ -H "Authorization: Bearer $ONP_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "card": { "url": "https://example.com/post", "title": "...", "description": "...", "image": "https://example.com/cover.jpg", "caption": "..." } }'
await fetch(url, { method: "POST", headers: { "Authorization": `Bearer ${token}`, "Content-Type": "application/json", }, body: JSON.stringify({ card: { url: "https://example.com/post", title: "...", description: "...", image: "https://example.com/cover.jpg", caption: "...", }, }), });
requests.post(
url,
headers={"Authorization": f"Bearer {token}"},
json={
"card": {
"url": "https://example.com/post",
"title": "...",
"description": "...",
"image": "https://example.com/cover.jpg",
"caption": "...",
}
},
)
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ "card" => [ "url" => "https://example.com/post", "title" => "...", "description" => "...", "image" => "https://example.com/cover.jpg", "caption" => "...", ], ]));
پیامِ تکراری نفرست
اگر درخواست تایماوت گرفت، نمیدانی پیام رسیده یا نه. هدرِ Idempotency-Key را بگذار تا تلاشِ دوباره پیامِ تکراری نسازد:
همان کلید، همان پیام. این کلید id پیام هم میشود.
Idempotency-Key: order-2026-09-02-001
سهمیه
بهازای هر توکن، در هر دقیقه:
| عملیات | سقف |
|---|---|
| انتشار | 20 |
| خواندن | 120 |
هر پاسخ هدرهای X-RateLimit-Limit، X-RateLimit-Remaining و X-RateLimit-Reset دارد. اگر سهمیه پر شود 429 میگیری بههمراهِ Retry-After — همانقدر صبر کن، نه کمتر.
HTTP/2 429 X-RateLimit-Limit: 20 X-RateLimit-Remaining: 0 Retry-After: 37
خطاها
| کد HTTP | error.code | یعنی |
|---|---|---|
| 400 | empty_message | text خالی است |
| 400 | bad_request | بدنه یا پارامتر نامعتبر |
| 401 | missing_token | هدرِ Authorization نیست |
| 401 | invalid_token | توکن شناخته نشد |
| 401 | revoked_token | توکن باطل شده |
| 403 | entity_mismatch | این توکن مالِ فضای دیگری است |
| 403 | wrong_entity_kind | نوعِ فضا در مسیر با توکن نمیخوانَد |
| 403 | missing_scope | توکن این مجوز را ندارد |
| 403 | sender_not_member | سازندهٔ توکن دیگر عضوِ فضا نیست |
| 403 | read_only | کانال فقط-خواندنی است |
| 404 | entity_not_found | فضا پیدا نشد |
| 413 | message_too_long | متن از ۸۰۰۰ کاراکتر بلندتر است |
| 429 | rate_limited | سهمیه پر شده |
sender_not_member گرفتی؟ توکن به مدیری گره خورده که ساختهاش. اگر آن شخص از فضا خارج شده باشد، انتشار متوقف میشود. راهحل: یکی از مدیرانِ فعلی از پنل توکن را دوباره بسازد.در این نسخه نیست
ارسالِ عکس و فایل، حذفِ پیام از API، و webhook (خبردار شدن از رویدادهای فضا) هنوز نیامدهاند. توکنها از همین حالا فیلدِ scopes دارند، پس وقتی webhook اضافه شود توکنِ تو باطل نمیشود.