توسعهدهندگان / مستندات
LOCA Developer Docs
شروع سریع API لوکا
برای اولین ارسال فقط به یک API Key، یک سرویس فعال و یک درخواست نیاز دارید.
شروع سریع
برای اولین ارسال به سه چیز نیاز دارید: API Key، یک سرویس فعال، و یک درخواست. ساختار درخواست برای همه کانالها یکسان است — فقط channel و در صورت نیاز service_id را عوض کنید.
- ۱ — ثبتنام کنید و وارد پنل LOCA شوید.
- ۲ — از بخش توسعهدهندگان یک API Key بسازید. مقدار کلید فقط همان لحظه نمایش داده میشود؛ حتماً ذخیرهاش کنید.
- ۳ — اولین درخواست را با هدر X-API-Key ارسال کنید.
/api/v1/messages/sendاولین ارسال
درخواست پذیرفته میشود و پیام در صف قرار میگیرد (۲۰۲).
POST /api/v1/messages/send
X-API-Key: <API_KEY>
Content-Type: application/json
{
"channel": "sms",
"service_id": "YOUR_SERVICE_ID",
"message_list": [
{
"phone": "09123456789",
"text": "سلام از LOCA"
}
]
}{
"campaign_id": "…",
"batch_id": "…",
"approval_queue_id": null,
"total_received": 1,
"accepted": 1,
"rejected": 0,
"status": "queued",
"cost": {
"total": 1.0,
"per_message": 1.0,
"currency": "unit"
},
"wallet": {
"balance": 999,
"reserved": 1
},
"api_version": "v2"
}احراز هویت
هر درخواست به API باید API Key شما را در هدر X-API-Key داشته باشد.
میتوانید چند API Key برای یک حساب بسازید. مقدار کلید فقط یکبار — هنگام ساخت — نمایش داده میشود؛ حتماً آن را ذخیره کنید. برای تعویض کلید، یک کلید جدید بسازید و کلید قبلی را غیرفعال یا حذف کنید.
/api/v1/api-keysلیست کلیدها
لیست API Keyهای حساب شما. مقدار کلید در پاسخ برنمیگردد.
GET /api/v1/api-keys
X-API-Key: <API_KEY>/api/v1/api-keysایجاد کلید
کلید جدید میسازد (۲۰۱). فیلد api_key فقط در همین پاسخ نمایش داده میشود.
POST /api/v1/api-keys
X-API-Key: <API_KEY>
Content-Type: application/json
{
"name": "Production",
"rate_limit_per_min": 600
}- rate_limit_per_min پیشفرض: ۶۰۰ درخواست در دقیقه.
- مشاهده: GET /api/v1/api-keys/{id} · ویرایش: PATCH · حذف: DELETE (۲۰۴)
ارسال پیام
ارسال پیام از طریق POST /api/v1/messages/send انجام میشود. برای هر کانال همان endpoint را استفاده کنید — فقط channel و service_id را عوض کنید.
- کانالهای پشتیبانیشده: sms, voice, rubika, bale, eitaa, soroush_plus
- whatsapp در صورت داشتن سرویس فعال در دسترس است.
- یکی از channel یا routing_strategy_id الزامی است — هر دو را با هم نفرستید.
- پاسخ ارسال ۲۰۲ است. وضعیت فوری: queued، queued_with_rejections، queued_for_approval.
/api/v1/messages/sendارسال پیام
حداکثر ۱۰۰٬۰۰۰ گیرنده در هر درخواست.
| فیلد | نوع | توضیح |
|---|---|---|
channel | string | نام کانال — اگر routing_strategy_id نفرستید، اجباری است |
routing_strategy_id | uuid | شناسه مسیر هوشمند — جایگزین channel |
service_id | string | شناسه سرویس کانال (external_service_id از GET /api/v1/channel-services/me) |
channel_service_ids | object | service_id جدا برای هر کانال — فقط در ارسال با مسیر هوشمند |
campaign_name | string | نام کمپین — اختیاری |
message_listلازم | array | لیست گیرندهها: phone, text, file_id؛ اختیاری: channel_texts, channel_file_ids |
phonebook_selection | object | انتخاب از دفترچه تلفن: group_ids / contact_ids / exclude_contact_ids |
link_type | string | نوع لینک کوتاه: unique_per_recipient | single_for_campaign |
original_url | string | آدرس مقصد برای لینک کوتاه |
smart_link_id | uuid | شناسه لینک هوشمند — اولویت بالاتر از original_url |
voice_max_attempts | int | تعداد تلاش — ۱ تا ۳، فقط برای channel=voice |
voice_retry_interval_seconds | int | فاصله بین تلاشها — ۶۰ تا ۲۵۹۲۰۰ ثانیه |
POST /api/v1/messages/send
X-API-Key: <API_KEY>
Content-Type: application/json
{
"channel": "sms",
"service_id": "YOUR_SERVICE_ID",
"campaign_name": "welcome",
"message_list": [
{ "phone": "09123456789", "text": "سلام از LOCA" }
]
}{
"campaign_id": "…",
"batch_id": "…",
"approval_queue_id": null,
"total_received": 1,
"accepted": 1,
"rejected": 0,
"status": "queued",
"cost": {
"total": 1.0,
"per_message": 1.0,
"currency": "unit"
},
"wallet": {
"balance": 999,
"reserved": 1
},
"api_version": "v2"
}/api/v1/messages/sendBulkMessagesارسال نظیر به نظیر
برای ارسال متن متفاوت به هر گیرنده. ساختار بدنه همان ارسال پیام است.
POST /api/v1/messages/sendBulkMessages
X-API-Key: <API_KEY>
Content-Type: application/json
{
"channel": "bale",
"service_id": "YOUR_SERVICE_ID",
"message_list": [
{ "phone": "09137234754", "text": "سلام علی" },
{ "phone": "09137552590", "text": "سلام سارا" }
]
}{
"campaign_id": "…",
"batch_id": "…",
"approval_queue_id": null,
"total_received": 1,
"accepted": 1,
"rejected": 0,
"status": "queued",
"cost": {
"total": 1.0,
"per_message": 1.0,
"currency": "unit"
},
"wallet": {
"balance": 999,
"reserved": 1
},
"api_version": "v2"
}ارسال ثابت
یک متن یا فایل ثابت برای همه گیرندهها. یکی از این سه روش گیرنده را مشخص کنید: receptors، draft_id، یا phonebook_selection.
/api/v1/messages/sendBulkStaticMessagesارسال ثابت
حداکثر ۱۰۰٬۰۰۰ گیرنده. SMS فایل ندارد. در بله، ارسال فقط با فایل و بدون متن مجاز نیست.
| فیلد | نوع | توضیح |
|---|---|---|
channel | string | نام کانال — یا routing_strategy_id |
routing_strategy_id | uuid | شناسه مسیر هوشمند — بهجای channel |
service_id | string | شناسه سرویس کانال |
message | string | متن ثابت — حداکثر ۴۰۰۰ کاراکتر |
file_id | string | شناسه فایل — حداقل یکی از message یا file_id لازم است |
receptors | array | لیست گیرندهها: [{ receptor }] |
draft_id | uuid | شناسه پیشنویس از precheck-file |
phonebook_selection | object | انتخاب از دفترچه: group_ids, contact_ids, exclude_contact_ids |
idempotency_key | string | کلید یکتا برای جلوگیری از ارسال تکراری |
link_type / original_url / smart_link_id | — | تنظیمات لینک کوتاه |
POST /api/v1/messages/sendBulkStaticMessages
X-API-Key: <API_KEY>
Content-Type: application/json
{
"channel": "sms",
"service_id": "YOUR_SERVICE_ID",
"campaign_name": "static-test",
"message": "سلام، این پیام برای همه است",
"receptors": [
{ "receptor": "09123456789" },
{ "receptor": "09120000000" }
]
}{
"campaign_id": "…",
"batch_id": "…",
"approval_queue_id": null,
"total_received": 1,
"accepted": 1,
"rejected": 0,
"status": "queued",
"cost": {
"total": 1.0,
"per_message": 1.0,
"currency": "unit"
},
"wallet": {
"balance": 999,
"reserved": 1
},
"api_version": "v2"
}- پاسخ ممکن است شامل skipped_invalid_input_lines و skipped_duplicate_input_lines باشد.
ارسال پویا
متن هر گیرنده از ستونهای فایل Excel یا CSV ساخته میشود. بعد از آپلود، ردیفها روی سرور ذخیره میمانند — در مرحله ارسال فایل را دوباره نفرستید.
- ۱ — فایل را آپلود کنید: POST /api/v1/messages/parse-dynamic-file (فرمت: xlsx, xls, csv). ردیف اول هدر است؛ ستون اول شماره موبایل.
- ۲ — (اختیاری) هزینه دقیق را محاسبه کنید: POST /api/v1/messages/prepare-dynamic-send
- ۳ — منتظر آماده شدن بمانید: GET /api/v1/messages/prepare-dynamic-send/{job_id}
- ۴ — ارسال کنید: POST /api/v1/messages/sendBulkDynamicMessages با draft_id و message_template (مثلاً «سلام {{name}}»)
/api/v1/messages/parse-dynamic-fileآپلود فایل پویا
فایل را میخواند و draft_id برمیگرداند. هدر ستونها و نمونه ردیفها در پاسخ است.
POST /api/v1/messages/parse-dynamic-file
X-API-Key: <API_KEY>/api/v1/messages/sendBulkDynamicMessagesارسال پویا
با draft_id از مرحله قبل، پیامها را ارسال میکند (۲۰۲).
POST /api/v1/messages/sendBulkDynamicMessages
X-API-Key: <API_KEY>
Content-Type: application/json
{
"draft_id": "DRAFT_UUID",
"channel": "sms",
"service_id": "YOUR_SERVICE_ID",
"campaign_name": "dynamic-test",
"message_template": "سلام {{name}}، کد شما {{code}} است"
}{
"campaign_id": "…",
"batch_id": "…",
"approval_queue_id": null,
"total_received": 1,
"accepted": 1,
"rejected": 0,
"status": "queued",
"cost": {
"total": 1.0,
"per_message": 1.0,
"currency": "unit"
},
"wallet": {
"balance": 999,
"reserved": 1
},
"api_version": "v2"
}ارسال از فایل
برای ارسال به لیست شماره از فایل txt یا csv. میتوانید اول فایل را بررسی کنید و با draft_id در ارسال ثابت استفاده کنید، یا مستقیم ارسال کنید.
/api/v1/messages/precheck-fileبررسی فایل شماره
فایل را میخواند و draft_id به همراه آمار شمارههای معتبر و نامعتبر برمیگرداند.
POST /api/v1/messages/precheck-file
X-API-Key: <API_KEY>/api/v1/messages/sendBulkFromFileارسال مستقیم از فایل
فایل شماره را آپلود و مستقیم ارسال میکند. اگر channel نفرستید، rubika پیشفرض است.
| فیلد | نوع | توضیح |
|---|---|---|
fileلازم | file | فایل txt یا csv |
channel | string | نام کانال |
service_id | string | شناسه سرویس کانال |
routing_strategy_id | string | شناسه مسیر هوشمند — اختیاری |
default_text | string | متن پیشفرض پیام |
default_file_id | string | شناسه فایل پیشفرض |
campaign_name | string | نام کمپین |
POST /api/v1/messages/sendBulkFromFile
X-API-Key: <API_KEY>Template
الگوها متن ازپیشتعریفشده با متغیر هستند — مثل {code} برای OTP. هر الگو میتواند برای چند کانال تعریف شود. فقط الگوی تأییدشده (approved) قابل ارسال است.
- GET /api/v1/message-templates — لیست الگوها
- POST /api/v1/message-templates — ساخت الگو (با ?submit=true برای ارسال به تأیید)
- GET /api/v1/message-templates/{id} — جزئیات
- PUT /api/v1/message-templates/{id} — ویرایش
- POST /api/v1/message-templates/{id}/submit — ارسال برای تأیید
- DELETE /api/v1/message-templates/{id} — حذف (۲۰۴)
/api/v1/message-templatesایجاد الگو
الگوی جدید میسازد. حداقل یک کانال لازم است. sms و eitaa از مدیا پشتیبانی نمیکنند.
POST /api/v1/message-templates
X-API-Key: <API_KEY>
Content-Type: application/json
{
"name": "ورود",
"template_type": "otp",
"channels": [
{ "channel": "sms", "body": "کد تأیید شما: {code}" }
]
}/api/v1/messages/sendBulkTemplateMessagesارسال با الگو
حداکثر ۱۰۰٬۰۰۰ گیرنده. مدیا از الگوی تأییدشده استفاده میشود — file_id روی گیرنده قبول نمیشود.
POST /api/v1/messages/sendBulkTemplateMessages
X-API-Key: <API_KEY>
Content-Type: application/json
{
"template_code": "otp_login",
"channel": "sms",
"service_id": "YOUR_SERVICE_ID",
"receptors": [
{
"phone": "09123456789",
"parameters": { "code": "438291" }
}
]
}{
"campaign_id": "…",
"batch_id": "…",
"approval_queue_id": null,
"total_received": 1,
"accepted": 1,
"rejected": 0,
"status": "queued",
"cost": {
"total": 1.0,
"per_message": 1.0,
"currency": "unit"
},
"wallet": {
"balance": 999,
"reserved": 1
},
"api_version": "v2"
}OTP
OTP از همان endpoint ارسال با الگو است — فقط الگویی با template_type=otp و وضعیت approved استفاده کنید.
- کد OTP را سیستم شما تولید میکند و در parameters میفرستید — LOCA کد را generate یا verify نمیکند.
- الگوی otp نمیتواند مدیا داشته باشد.
- Voice OTP: متن الگو فقط یک متغیر مثل {code} یا عدد ۳ تا ۸ رقمی باشد.
- file_id روی گیرنده نفرستید.
/api/v1/messages/sendBulkTemplateMessagesارسال OTP
الگوی otp باید تأییدشده (approved) باشد.
POST /api/v1/messages/sendBulkTemplateMessages
X-API-Key: <API_KEY>
Content-Type: application/json
{
"template_code": "otp_login",
"channel": "sms",
"service_id": "YOUR_SERVICE_ID",
"campaign_name": "OTP Login",
"receptors": [
{
"phone": "09123456789",
"parameters": { "code": "438291" }
}
]
}{
"campaign_id": "…",
"batch_id": "…",
"approval_queue_id": null,
"total_received": 1,
"accepted": 1,
"rejected": 0,
"status": "queued",
"cost": {
"total": 1.0,
"per_message": 1.0,
"currency": "unit"
},
"wallet": {
"balance": 999,
"reserved": 1
},
"api_version": "v2"
}مسیر هوشمند
بهجای انتخاب یک کانال، میتوانید routing_strategy_id بفرستید تا LOCA کانالها را به ترتیب اولویت امتحان کند. channel و routing_strategy_id را با هم نفرستید.
/api/v1/routing-strategiesایجاد مسیر هوشمند
استراتژی جدید میسازد. همچنین: GET لیست · GET/PUT/DELETE /{id} · حذف: ۲۰۴
POST /api/v1/routing-strategies
X-API-Key: <API_KEY>
Content-Type: application/json
{
"name": "OTP fallback",
"strategy_type": "priority_fallback",
"channel_priorities": [
{ "channel": "sms", "priority_order": 1, "is_active": true },
{ "channel": "voice", "priority_order": 2, "is_active": true }
]
}/api/v1/routing-strategies/{id}/sendارسال با مسیر هوشمند
پیام را با استراتژی مشخصشده ارسال میکند (۲۰۲).
POST /api/v1/routing-strategies/{id}/send
X-API-Key: <API_KEY>
Content-Type: application/json
{
"message_list": [
{ "phone": "09123456789", "text": "کد تأیید: 438291" }
],
"campaign_name": "otp-route"
}لینک هوشمند
لینک هوشمند آدرس مقصد شما را کوتاه میکند. در متن پیام از {{short_link}} استفاده کنید تا لینک کوتاه جایگزین شود.
- POST /api/v1/smart-links — ساخت
- GET /api/v1/smart-links — لیست
- GET /api/v1/smart-links/{id} — جزئیات
- GET /api/v1/smart-links/{id}/analytics — آمار کلیک
- PATCH /api/v1/smart-links/{id} — ویرایش
- DELETE /api/v1/smart-links/{id} — حذف (۲۰۴)
/api/v1/smart-linksایجاد لینک هوشمند
لینک جدید میسازد (۲۰۱).
POST /api/v1/smart-links
X-API-Key: <API_KEY>
Content-Type: application/json
{
"title": "فروشگاه",
"destination_url": "https://example.com/offer",
"is_active": true
}- در ارسال: smart_link_id، یا link_type + original_url.
- link_type: unique_per_recipient (لینک جدا برای هر گیرنده) | single_for_campaign (یک لینک برای همه)
وضعیت پیام
هر پیام دو وضعیت دارد: status وضعیت کلی در LOCA و provider_status وضعیت گزارششده از سمت کانال. برای فیلتر از status_filter و provider_status_filter استفاده کنید.
| status | معنی |
|---|---|
| queued | در صف ارسال |
| pending | منتظر ارسال به کانال |
pending_confirmation | ارسال شده — منتظر تأیید نهایی |
| sending | در حال ارسال |
| sent | ارسال موفق |
| delivered | تحویل داده شده (SMS / WhatsApp) |
| seen | خوانده شده (Rubika / Bale / WhatsApp) |
| failed | ناموفق |
| expired | منقضی شده |
/api/v1/messagesلیست پیامها
فیلتر: campaign_id, batch_id, phone, status. صفحهبندی: page, page_size (حداکثر ۲۰۰).
GET /api/v1/messages
X-API-Key: <API_KEY>کمپینها
- GET /api/v1/campaigns — لیست کمپینها (page, page_size≤۲۰۰, status, search, date_from, date_to)
- GET /api/v1/campaigns/{id}/stats — آمار کمپین
- GET /api/v1/campaigns/{id}/messages — پیامهای کمپین (page_size حداکثر ۲۰۰)
- GET /api/v1/campaigns/{id}/recipients — گیرندهها (فقط کمپینهای مسیر هوشمند)
- POST /api/v1/campaigns/{id}/sync-messages — همگامسازی وضعیت با کانال (۲۰۲)
- GET /api/v1/campaigns/{id}/sync-status/{request_id} — پیگیری همگامسازی
- GET /api/v1/campaigns/export — خروجی Excel همه کمپینها
- GET /api/v1/campaigns/{id}/messages/export — خروجی Excel پیامهای یک کمپین
وضعیت کمپین: pending (در انتظار)، running (در حال اجرا)، completed (تمامشده)، paused (متوقف)، failed (ناموفق).
خطاها
خطاها با HTTP status code و یک body ساختاریافته برمیگردند:
/api/v1/…شکل پاسخ خطا
در خطاهای اعتبارسنجی، detail ممکن است آرایهای از جزئیات فیلدها باشد و error.code برابر VALIDATION_ERROR شود.
GET /api/v1/…
X-API-Key: <API_KEY>{
"detail": {
"error": {
"code": "INVALID_API_KEY",
"message": "…"
}
}
}| HTTP | code | معنی |
|---|---|---|
| 401 | MISSING_AUTH | API Key ارسال نشده |
| 403 | INVALID_API_KEY | کلید نامعتبر یا غیرفعال |
| 429 | API_KEY_RATE_LIMIT_EXCEEDED | بیش از حد مجاز درخواست |
| 400 | INVALID_JSON | بدنه JSON معتبر نیست |
| 400 | INVALID_PAYLOAD | ساختار بدنه نادرست |
| 422 | VALIDATION_ERROR | خطا در اعتبارسنجی فیلدها |
| 402 | INSUFFICIENT_BALANCE | موجودی کافی نیست |
| 400 | WALLET_NOT_FOUND | کیف پول یافت نشد |
| 403 | WALLET_NOT_ACTIVE | کیف پول غیرفعال است |
| 400 | TEMPLATE_NOT_FOUND | الگو یافت نشد |
| 400 | TEMPLATE_CHANNEL_NOT_APPROVED | الگو برای این کانال تأیید نشده |
| 400 | CHANNEL_OR_STRATEGY_REQUIRED | channel یا routing_strategy_id لازم است |
| 400 | CHANNEL_AND_STRATEGY_CONFLICT | channel و routing_strategy_id با هم مجاز نیست |
| 400 | TOO_MANY_RECEPTORS | تعداد گیرنده بیش از حد مجاز |
| 429 | RATE_LIMIT_EXCEEDED | سقف سرعت ارسال |
| 429 | TOO_MANY_CONCURRENT_BATCHES | تعداد batch همزمان بیش از حد |
| 413 | FILE_TOO_LARGE | حجم فایل بیش از حد مجاز |
| 404 | CAMPAIGN_NOT_FOUND | کمپین یافت نشد |
محدودیتها
| مورد | مقدار |
|---|---|
| گیرنده در هر درخواست | حداکثر ۱۰۰٬۰۰۰ |
page_size لیست کمپین / پیام / messages | حداکثر ۲۰۰ |
page_size لیست مدیا | حداکثر ۱۰۰ (پیشفرض ۲۴) |
| حجم فایل مدیا | ۱۰ مگابایت |
| batch در دقیقه | ۱۵۰ (پیشفرض) |
| پیام در ساعت | ۵۰٬۰۰۰ (پیشفرض) |
| batch همزمان | ۱۰ (پیشفرض) |
| درخواست در دقیقه (API Key) | ۶۰۰ (پیشفرض) |
| تلاش مجدد voice | ۱ تا ۳ |
کیف پول
هزینه ارسال و موجودی کیف پول به واحد اعتبار محاسبه میشود. فیلدهای *_rial معادل ریالی برای نمایش هستند.
/api/v1/wallet/meموجودی
موجودی فعلی، اعتبار رزروشده و مجموع مصرف.
GET /api/v1/wallet/me
X-API-Key: <API_KEY>/api/v1/wallet/transactionsتراکنشها
تاریخچه تراکنشها. page پیشفرض ۵۰، حداکثر ۱۰۰. نوعها: charge (شارژ)، reserve (رزرو ارسال)، adjust، refund.
GET /api/v1/wallet/transactions
X-API-Key: <API_KEY>سرویسها
قبل از ارسال، سرویسهای فعال کانالهای خود را ببینید. در درخواست ارسال، فیلد service_id همان external_service_id است.
/api/v1/channel-services/meسرویسهای من
لیست سرویسهای فعال هر کانال: id, channel, external_service_id, display_name, status.
GET /api/v1/channel-services/me
X-API-Key: <API_KEY>مدیا
- POST /api/v1/media/upload — آپلود فایل (file_type اختیاری: File | Image | Video | Voice | Music)
- GET /api/v1/media — لیست فایلها
- GET /api/v1/media/{id} — جزئیات
- GET /api/v1/media/{id}/download — دانلود فایل
حداکثر حجم: ۱۰ مگابایت. Voice فقط فرمت wav. شناسه file_id برگشتی را در ارسال استفاده کنید.
قیمت
/api/v1/pricing/ratesتعرفه
تعرفه پلن فعال. فیلتر اختیاری: channel, sub_type, category, only_active.
GET /api/v1/pricing/rates
X-API-Key: <API_KEY>/api/v1/pricing/calculate-costبرآورد هزینه
قبل از ارسال، هزینه تقریبی را محاسبه میکند.
POST /api/v1/pricing/calculate-cost
X-API-Key: <API_KEY>برای شروع، از بخش «شروع سریع» و «احراز هویت» بالای همین صفحه استفاده کنید. بازگشت به معرفی API
