مرجع الـ API
كل عمليات Tabla API 1.2.0، متولّدة وقت البناء من نفس العقد اللي الـ API شغّال بيه.
وصف العمليات والخانات جاي من العقد، وهو بالإنجليزي.
Tabla, the multi-tenant notification engine: send messages by template over push, SMS, e-mail, WhatsApp and an in-app inbox; manage recipients, devices and templates; read statuses and usage. Server to server only, with OAuth 2.0 client credentials. Status webhooks (message.sent, message.delivered, message.failed, message.expired) carry Tabla-Signature: t=<unix>,v1=<hex HMAC-SHA256 of "t.body" with the webhook secret>.
الدخول
post/oauth/token
Client credentials: a 10-minute access token for the tenant API
- الـ Scope
- مفيش: دي اللي بتاخد بيها التوكن
- operationId
token
الـ Parameters
| الاسم | مكانها | النوع | إجباري | الوصف |
|---|---|---|---|---|
Authorization | header | string | لأ |
جسم الطلب
نوع المحتوى: application/x-www-form-urlencoded
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
client_id | string | لأ | |
client_secret | string | لأ | |
grant_type | string | لأ | |
scope | string | لأ |
client_id=tc_your_client_id&client_secret=ts_your_client_secret&grant_type=client_credentials&scope=messages%3Asend%20messages%3Areadالردود
200 OK · */* · object
{}الرسايل والاستهلاك
webhooks الحالة (message.sent، message.delivered، message.failed، message.expired) طبلة هي اللي بتبعتها على العنوان اللي بتحطه في لوحة التحكم. صفحة ابدأ من هنا بتوريك شكلها وإزاي تتأكد من توقيعها.
post/v1/messages
Accepts a message for delivery (202); idempotent per key
- الـ Scope
messages:send- operationId
sendMessage
محتاجة هيدر Idempotency-Key
الـ Parameters
| الاسم | مكانها | النوع | إجباري | الوصف |
|---|---|---|---|---|
Idempotency-Key | header | string | لأ | 1 to 100 printable characters; the same key and body answer the same message |
جسم الطلب
نوع المحتوى: application/json · SendRequest
{
"data": {},
"options": {
"appId": "app.example.android",
"channels": [
"PUSH"
],
"fallback": [
"PUSH"
],
"link": "app://bookings/42",
"priority": "HIGH",
"pushData": {},
"ttlSeconds": 30
},
"recipient": {
"email": "mona@example.com",
"id": "user-42",
"locale": "ar",
"phone": "+201001234567"
},
"template": "booking.confirmed"
}الردود
200 OK · */* · AcceptedResponse
{
"id": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"status": "ACCEPTED"
}الأخطاء
Problem details (application/problem+json) ومعاها code ثابت. الأكواد المشهورة متشرحة في الأخطاء، بالعربي والإنجليزي.
| الحالة | الوصف | نوع المحتوى |
|---|---|---|
401 | Missing, expired or revoked access token | application/problem+jsonProblem |
402 | Billing refused it: BILLING_CAP_REACHED (the month's spending cap; OTP and transactional get a grace of 10% of it), CREDIT_EXHAUSTED (prepaid credit or the credit limit), or PLAN_VOLUME_EXHAUSTED (a plan without overage) | application/problem+jsonProblem |
403 | The token lacks the operation's scope | application/problem+jsonProblem |
429 | The tenant's request budget or quota is spent; see Retry-After | application/problem+jsonProblem |
503 | BILLING_UNAVAILABLE: bulk can't be checked right now; OTP and transactional still go. Retry shortly | application/problem+jsonProblem |
post/v1/messages/batch
Accepts up to 500 messages, all or none (202)
- الـ Scope
messages:send- operationId
sendMessages
محتاجة هيدر Idempotency-Key
الـ Parameters
| الاسم | مكانها | النوع | إجباري | الوصف |
|---|---|---|---|---|
Idempotency-Key | header | string | لأ | For the whole batch; each message takes <key>#<index> |
جسم الطلب
نوع المحتوى: application/json · BatchRequest
{
"messages": [
{
"data": {},
"options": {
"appId": "app.example.android",
"channels": [
"PUSH"
],
"fallback": [
"PUSH"
],
"link": "app://bookings/42",
"priority": "HIGH",
"pushData": {},
"ttlSeconds": 30
},
"recipient": {
"email": "mona@example.com",
"id": "user-42",
"locale": "ar",
"phone": "+201001234567"
},
"template": "booking.confirmed"
}
]
}الردود
200 OK · */* · BatchResponse
{
"messages": [
{
"id": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"status": "ACCEPTED"
}
]
}الأخطاء
Problem details (application/problem+json) ومعاها code ثابت. الأكواد المشهورة متشرحة في الأخطاء، بالعربي والإنجليزي.
| الحالة | الوصف | نوع المحتوى |
|---|---|---|
401 | Missing, expired or revoked access token | application/problem+jsonProblem |
402 | Billing refused it: BILLING_CAP_REACHED (the month's spending cap; OTP and transactional get a grace of 10% of it), CREDIT_EXHAUSTED (prepaid credit or the credit limit), or PLAN_VOLUME_EXHAUSTED (a plan without overage) | application/problem+jsonProblem |
403 | The token lacks the operation's scope | application/problem+jsonProblem |
429 | The tenant's request budget or quota is spent; see Retry-After | application/problem+jsonProblem |
503 | BILLING_UNAVAILABLE: bulk can't be checked right now; OTP and transactional still go. Retry shortly | application/problem+jsonProblem |
get/v1/messages/{messageId}
A message's status, per channel and attempt
- الـ Scope
messages:read- operationId
getMessage
الـ Parameters
| الاسم | مكانها | النوع | إجباري | الوصف |
|---|---|---|---|---|
messageId | path | string (uuid) | أيوه | Message id |
الردود
200 OK · */* · MessageResponse
{
"category": "OTP",
"channels": [
{
"channel": "PUSH",
"leg": 1,
"status": "string"
}
],
"createdAt": "2026-10-10T17:00:00Z",
"expiresAt": "2026-10-10T17:00:00Z",
"finishedAt": "2026-10-10T17:00:00Z",
"id": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"lane": "OTP",
"legs": [
{
"attempts": [
{
"address": "string",
"at": "2026-10-10T17:00:00Z",
"attempt": 1,
"channel": "string",
"error": "string",
"provider": "string",
"status": "string",
"willRetry": true
}
],
"channels": [
"PUSH"
],
"current": "PUSH",
"leg": 1,
"status": "PENDING"
}
],
"priority": "HIGH",
"recipientId": "user-42",
"status": "ACCEPTED",
"template": "booking.confirmed"
}الأخطاء
Problem details (application/problem+json) ومعاها code ثابت. الأكواد المشهورة متشرحة في الأخطاء، بالعربي والإنجليزي.
get/v1/usage
Messages providers accepted, per Cairo day and channel (92 days at most)
- الـ Scope
messages:read- operationId
getUsage
الـ Parameters
| الاسم | مكانها | النوع | إجباري | الوصف |
|---|---|---|---|---|
from | query | string (date) | أيوه | First day, yyyy-MM-dd |
to | query | string (date) | أيوه | Last day, yyyy-MM-dd |
الردود
200 OK · */* · UsageResponse
{
"days": [
{
"channel": "string",
"day": "string",
"sent": 1
}
],
"from": "string",
"to": "string"
}الأخطاء
Problem details (application/problem+json) ومعاها code ثابت. الأكواد المشهورة متشرحة في الأخطاء، بالعربي والإنجليزي.
المستلمين وأجهزتهم
get/v1/recipients/{recipientId}
- الـ Scope
recipients:read- operationId
getRecipient
الـ Parameters
| الاسم | مكانها | النوع | إجباري | الوصف |
|---|---|---|---|---|
recipientId | path | string | أيوه | The tenant's own user id |
الردود
200 OK · */* · RecipientResponse
{
"activeDevices": 1,
"createdAt": "2026-10-10T17:00:00Z",
"email": "mona@example.com",
"id": "user-42",
"locale": "ar",
"phone": "+201001234567",
"phoneVerified": true,
"preferences": {},
"quietHours": {
"end": "string",
"start": "string"
},
"timeZone": "string",
"updatedAt": "2026-10-10T17:00:00Z"
}الأخطاء
Problem details (application/problem+json) ومعاها code ثابت. الأكواد المشهورة متشرحة في الأخطاء، بالعربي والإنجليزي.
put/v1/recipients/{recipientId}
Creates or replaces a recipient
- الـ Scope
recipients:write- operationId
putRecipient
الـ Parameters
| الاسم | مكانها | النوع | إجباري | الوصف |
|---|---|---|---|---|
recipientId | path | string | أيوه | The tenant's own user id |
جسم الطلب
نوع المحتوى: application/json · RecipientRequest
{
"email": "mona@example.com",
"locale": "ar",
"phone": "+201001234567",
"phoneVerified": true,
"preferences": {},
"quietHours": {
"end": "string",
"start": "string"
},
"timeZone": "string"
}الردود
200 OK · */* · RecipientResponse
{
"activeDevices": 1,
"createdAt": "2026-10-10T17:00:00Z",
"email": "mona@example.com",
"id": "user-42",
"locale": "ar",
"phone": "+201001234567",
"phoneVerified": true,
"preferences": {},
"quietHours": {
"end": "string",
"start": "string"
},
"timeZone": "string",
"updatedAt": "2026-10-10T17:00:00Z"
}الأخطاء
Problem details (application/problem+json) ومعاها code ثابت. الأكواد المشهورة متشرحة في الأخطاء، بالعربي والإنجليزي.
post/v1/recipients/{recipientId}/devices
Registers a push token; a token already known for the app moves to this recipient
- الـ Scope
recipients:write- operationId
registerDevice
الـ Parameters
| الاسم | مكانها | النوع | إجباري | الوصف |
|---|---|---|---|---|
recipientId | path | string | أيوه | The tenant's own user id |
جسم الطلب
نوع المحتوى: application/json · DeviceRequest
{
"appId": "app.example.android",
"platform": "string",
"token": "fcm-device-token…"
}الردود
201 Created · */* · DeviceResponse
{
"id": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31"
}الأخطاء
Problem details (application/problem+json) ومعاها code ثابت. الأكواد المشهورة متشرحة في الأخطاء، بالعربي والإنجليزي.
post/v1/recipients/{recipientId}/devices/unregister
Forgets a push token; 204 whether or not it was known
- الـ Scope
recipients:write- operationId
unregisterDevice
الـ Parameters
| الاسم | مكانها | النوع | إجباري | الوصف |
|---|---|---|---|---|
recipientId | path | string | أيوه | The tenant's own user id |
جسم الطلب
نوع المحتوى: application/json · DeviceRemovalRequest
{
"appId": "app.example.android",
"token": "fcm-device-token…"
}الردود
204 No Content
الأخطاء
Problem details (application/problem+json) ومعاها code ثابت. الأكواد المشهورة متشرحة في الأخطاء، بالعربي والإنجليزي.
post/v1/recipients/{recipientId}/erasure
Deletes the recipient, devices and inbox now and redacts their messages (ADR 0008)
- الـ Scope
erasure:write- operationId
eraseRecipient
الـ Parameters
| الاسم | مكانها | النوع | إجباري | الوصف |
|---|---|---|---|---|
recipientId | path | string | أيوه | The tenant's own user id |
الردود
202 Accepted · */* · ErasureResponse
{
"erasedAt": "2026-10-10T17:00:00Z",
"id": "user-42"
}الأخطاء
Problem details (application/problem+json) ومعاها code ثابت. الأكواد المشهورة متشرحة في الأخطاء، بالعربي والإنجليزي.
صندوق الرسايل
get/v1/recipients/{recipientId}/inbox
Newest first, keyset-paged
Items are ordered by createdAt, then id, both descending. Page on with the opaque cursor (the previous page's next), or instead with before and beforeId set to the last item's createdAt and id: the next page is the items after it in that order. before alone gives the items strictly older than that instant. A cursor with before, or beforeId without before, is CURSOR_INVALID.
- الـ Scope
inbox:read- operationId
listInbox
الـ Parameters
| الاسم | مكانها | النوع | إجباري | الوصف |
|---|---|---|---|---|
recipientId | path | string | أيوه | The tenant's own user id |
cursor | query | string | لأ | From the previous page's nextmaxLength 200 |
before | query | string (date-time) | لأ | Instead of cursor: the last item's createdAt (ISO 8601, e.g. 2026-10-05T10:00:00.123Z) |
beforeId | query | string (uuid) | لأ | With before: the last item's id |
limit | query | integer (int32) | لأ | Page size, 1 to 100min 1 · max 100 · default 20 |
unreadOnly | query | boolean | لأ | Only unread itemsdefault false |
الردود
200 OK · */* · InboxPage
{
"items": [
{
"body": "See you at 6 PM, Mona.",
"category": "OTP",
"createdAt": "2026-10-10T17:00:00Z",
"id": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"link": "app://bookings/42",
"messageId": "3f6c1a52-8d4e-4b7a-9c2f-5e1d0a9b7c31",
"readAt": "2026-10-10T17:00:00Z",
"template": "booking.confirmed",
"title": "Booking confirmed"
}
],
"next": "string"
}الأخطاء
Problem details (application/problem+json) ومعاها code ثابت. الأكواد المشهورة متشرحة في الأخطاء، بالعربي والإنجليزي.
post/v1/recipients/{recipientId}/inbox/by-message/{messageId}/read
Marks read the item a message made
For a tapped push, which carries the messageId but not the item id. Idempotent: an item already read keeps its readAt. 404 INBOX_ITEM_NOT_FOUND when the recipient has no inbox item for that message.
- الـ Scope
inbox:write- operationId
markInboxItemReadByMessage
الـ Parameters
| الاسم | مكانها | النوع | إجباري | الوصف |
|---|---|---|---|---|
recipientId | path | string | أيوه | The tenant's own user id |
messageId | path | string (uuid) | أيوه | Message id, as in the push's messageId |
الردود
204 No Content
الأخطاء
Problem details (application/problem+json) ومعاها code ثابت. الأكواد المشهورة متشرحة في الأخطاء، بالعربي والإنجليزي.
post/v1/recipients/{recipientId}/inbox/read-all
Marks every unread item read
- الـ Scope
inbox:write- operationId
markInboxRead
الـ Parameters
| الاسم | مكانها | النوع | إجباري | الوصف |
|---|---|---|---|---|
recipientId | path | string | أيوه | The tenant's own user id |
الردود
200 OK · */* · MarkedRead
{
"marked": 1
}الأخطاء
Problem details (application/problem+json) ومعاها code ثابت. الأكواد المشهورة متشرحة في الأخطاء، بالعربي والإنجليزي.
get/v1/recipients/{recipientId}/inbox/unread-count
- الـ Scope
inbox:read- operationId
countUnreadInbox
الـ Parameters
| الاسم | مكانها | النوع | إجباري | الوصف |
|---|---|---|---|---|
recipientId | path | string | أيوه | The tenant's own user id |
الردود
200 OK · */* · UnreadCount
{
"unread": 1
}الأخطاء
Problem details (application/problem+json) ومعاها code ثابت. الأكواد المشهورة متشرحة في الأخطاء، بالعربي والإنجليزي.
post/v1/recipients/{recipientId}/inbox/{itemId}/read
- الـ Scope
inbox:write- operationId
markInboxItemRead
الـ Parameters
| الاسم | مكانها | النوع | إجباري | الوصف |
|---|---|---|---|---|
recipientId | path | string | أيوه | The tenant's own user id |
itemId | path | string (uuid) | أيوه | Inbox item id |
الردود
204 No Content
الأخطاء
Problem details (application/problem+json) ومعاها code ثابت. الأكواد المشهورة متشرحة في الأخطاء، بالعربي والإنجليزي.
القوالب
get/v1/templates
Templates by key, 50 a page by default
- الـ Scope
templates:read- operationId
listTemplates
الـ Parameters
| الاسم | مكانها | النوع | إجباري | الوصف |
|---|---|---|---|---|
after | query | string | لأ | The last key of the previous pagemaxLength 100 |
limit | query | integer (int32) | لأ | Page size, 1 to 200min 1 · max 200 · default 50 |
الردود
200 OK · */* · TemplatePage
{
"items": [
{
"category": "OTP",
"currentVersion": 1,
"key": "booking.confirmed",
"updatedAt": "2026-10-10T17:00:00Z"
}
],
"next": "string"
}الأخطاء
Problem details (application/problem+json) ومعاها code ثابت. الأكواد المشهورة متشرحة في الأخطاء، بالعربي والإنجليزي.
get/v1/templates/{key}
The current version
- الـ Scope
templates:read- operationId
getTemplate
الـ Parameters
| الاسم | مكانها | النوع | إجباري | الوصف |
|---|---|---|---|---|
key | path | string | أيوه | Template key |
الردود
200 OK · */* · TemplateResponse
{
"category": "OTP",
"content": {},
"createdAt": "2026-10-10T17:00:00Z",
"currentVersion": 1,
"key": "booking.confirmed",
"variables": [
"string"
],
"version": 1
}الأخطاء
Problem details (application/problem+json) ومعاها code ثابت. الأكواد المشهورة متشرحة في الأخطاء، بالعربي والإنجليزي.
put/v1/templates/{key}
Creates the template (201) or, when the content changed, its next version (200)
- الـ Scope
templates:write- operationId
putTemplate
الـ Parameters
| الاسم | مكانها | النوع | إجباري | الوصف |
|---|---|---|---|---|
key | path | string | أيوه | e.g. booking.confirmed |
جسم الطلب
نوع المحتوى: application/json · TemplateRequest
{
"category": "OTP",
"email": {
"ar": {
"html": "string",
"subject": "Your booking is confirmed",
"text": "Your code is 123456"
},
"en": {
"html": "string",
"subject": "Your booking is confirmed",
"text": "Your code is 123456"
}
},
"inbox": {
"ar": {
"body": "See you at 6 PM, Mona.",
"title": "Booking confirmed"
},
"en": {
"body": "See you at 6 PM, Mona.",
"title": "Booking confirmed"
}
},
"push": {
"ar": {
"body": "See you at 6 PM, Mona.",
"title": "Booking confirmed"
},
"en": {
"body": "See you at 6 PM, Mona.",
"title": "Booking confirmed"
}
},
"sms": {
"ar": {
"text": "Your code is 123456"
},
"en": {
"text": "Your code is 123456"
}
},
"whatsapp": {
"ar": {
"language": "ar",
"name": "booking_confirmed",
"params": [
"string"
]
},
"en": {
"language": "ar",
"name": "booking_confirmed",
"params": [
"string"
]
}
}
}الردود
200 OK · */* · TemplateResponse
{
"category": "OTP",
"content": {},
"createdAt": "2026-10-10T17:00:00Z",
"currentVersion": 1,
"key": "booking.confirmed",
"variables": [
"string"
],
"version": 1
}الأخطاء
Problem details (application/problem+json) ومعاها code ثابت. الأكواد المشهورة متشرحة في الأخطاء، بالعربي والإنجليزي.
get/v1/templates/{key}/versions/{version}
- الـ Scope
templates:read- operationId
getTemplateVersion
الـ Parameters
| الاسم | مكانها | النوع | إجباري | الوصف |
|---|---|---|---|---|
key | path | string | أيوه | Template key |
version | path | integer (int32) | أيوه | Version number |
الردود
200 OK · */* · TemplateResponse
{
"category": "OTP",
"content": {},
"createdAt": "2026-10-10T17:00:00Z",
"currentVersion": 1,
"key": "booking.confirmed",
"variables": [
"string"
],
"version": 1
}الأخطاء
Problem details (application/problem+json) ومعاها code ثابت. الأكواد المشهورة متشرحة في الأخطاء، بالعربي والإنجليزي.
الـ Schemas
AcceptedResponse
An accepted message
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
id | string (uuid) | لأ | Message id |
status | "ACCEPTED" | "QUEUED" | "SENT" | "DELIVERED" | "FAILED" | "EXPIRED" | لأ | ACCEPTED, or its current status when replayed |
AttemptResponse
One attempt on one channel
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
address | string | لأ | Masked address |
at | string (date-time) | لأ | Last change |
attempt | integer (int32) | لأ | Attempt number on that channel |
channel | string | لأ | Channel |
error | string | لأ | Why it failed or was skipped |
provider | string | لأ | Provider |
status | string | لأ | SENDING, SENT, DELIVERED, FAILED, SKIPPED or EXPIRED |
willRetry | boolean | لأ | Whether a retry is scheduled |
BatchRequest
Up to 500 messages, accepted all or none
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
messages | array of SendRequest | أيوه | The messagesminItems 1 · maxItems 500 |
BatchResponse
The accepted messages, in request order
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
messages | array of AcceptedResponse | لأ | One per message |
ChannelState
One channel of one leg
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
channel | "PUSH" | "SMS" | "EMAIL" | "WHATSAPP" | "INBOX" | لأ | Channel |
leg | integer (int32) | لأ | Leg |
status | string | لأ | QUEUED, SENT, DELIVERED, FAILED, SKIPPED or EXPIRED |
DeviceRemovalRequest
A push token to forget, e.g. on sign-out
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
appId | string | أيوه | The tenant app's idmaxLength 150 |
token | string | أيوه | The FCM registration tokenmaxLength 512 |
DeviceRequest
A push token the tenant's app reported for this user
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
appId | string | أيوه | The tenant app's id, as registered with Tabla for pushmaxLength 150 |
platform | string | أيوه | ANDROID, IOS or WEBminLength 1 |
token | string | أيوه | The FCM registration tokenmaxLength 512 |
DeviceResponse
The registered device
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
id | string (uuid) | لأ | Tabla's device id |
EmailBody
An e-mail: a subject, and HTML, plain text or both
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
html | string | لأ | HTML partmaxLength 12000 |
subject | string | أيوه | SubjectmaxLength 200 |
text | string | لأ | Plain-text partmaxLength 12000 |
EmailLocales
Arabic and English; at least one
ErasureResponse
The recipient is gone; their messages are redacted shortly after
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
erasedAt | string (date-time) | لأ | When it was erased |
id | string | لأ | The tenant's id |
InboxItemResponse
An inbox item, rendered in the recipient's language when it arrived
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
body | string | لأ | Body |
category | "OTP" | "TRANSACTIONAL" | "MARKETING" | لأ | Category |
createdAt | string (date-time) | لأ | When it arrived |
id | string (uuid) | لأ | Item id |
link | string | لأ | What it opens in the app, as the tenant sent it |
messageId | string (uuid) | لأ | The message it came from; its push carries the same messageId |
readAt | string (date-time) | لأ | When it was read; null while unread |
template | string | لأ | Template key |
title | string | لأ | Title |
InboxPage
A page of inbox items, newest first
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
items | array of InboxItemResponse | لأ | Items |
next | string | لأ | Cursor of the next page; null on the last |
LegResponse
A fallback chain and what happened on it
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
attempts | array of AttemptResponse | لأ | Every attempt |
channels | array of "PUSH" | "SMS" | "EMAIL" | "WHATSAPP" | "INBOX" | لأ | The chain |
current | "PUSH" | "SMS" | "EMAIL" | "WHATSAPP" | "INBOX" | لأ | Where the chain stands |
leg | integer (int32) | لأ | Leg |
status | "PENDING" | "SENT" | "DELIVERED" | "FAILED" | "SKIPPED" | "EXPIRED" | لأ | PENDING, SENT, DELIVERED, FAILED, SKIPPED or EXPIRED |
MarkedRead
How many items were marked read
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
marked | integer (int32) | لأ | Items marked read |
MessageResponse
A message's status, per channel and per attempt
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
category | "OTP" | "TRANSACTIONAL" | "MARKETING" | لأ | Category |
channels | array of ChannelState | لأ | Each channel's state |
createdAt | string (date-time) | لأ | Accepted at |
expiresAt | string (date-time) | لأ | Goes out until |
finishedAt | string (date-time) | لأ | Every leg final at; null until then |
id | string (uuid) | لأ | Message id |
lane | "OTP" | "TRANSACTIONAL" | "BULK" | لأ | Lane |
legs | array of LegResponse | لأ | Each leg with its attempts |
priority | "HIGH" | "NORMAL" | "LOW" | لأ | Priority |
recipientId | string | لأ | The tenant's recipient id; null for an inline OTP or an erased recipient |
status | "ACCEPTED" | "QUEUED" | "SENT" | "DELIVERED" | "FAILED" | "EXPIRED" | لأ | ACCEPTED, QUEUED, SENT, DELIVERED, FAILED or EXPIRED |
template | string | لأ | Template key |
Problem
RFC 9457 problem details with a stable code
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
code | object | لأ | Stable error code |
detail | object | لأ | Localized explanation |
status | object | لأ | HTTP status |
title | object | لأ | Short summary |
type | object | لأ | urn:tabla:problem:<code> |
QuietHoursBody
A wall-clock window, may cross midnight, e.g. 22:00 to 08:00
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
end | string | أيوه | HH:mmminLength 1 |
start | string | أيوه | HH:mmminLength 1 |
RecipientRef
A registered recipient by the tenant's id, or for OTP templates only an inline phone or e-mail
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
email | string | لأ | OTP only: an e-mail addressmaxLength 254 |
id | string | لأ | The tenant's own user idmaxLength 128 |
locale | string | لأ | OTP only: ar or en; the tenant's default when absent |
phone | string | لأ | OTP only: a mobile numbermaxLength 32 |
RecipientRequest
Everything Tabla keeps about one of the tenant's users; a PUT replaces every field
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
email | string | لأ | E-mail addressmaxLength 254 |
locale | string | أيوه | ar or en |
phone | string | لأ | Mobile number; read as Egyptian without a country codemaxLength 32 |
phoneVerified | boolean | لأ | Whether the tenant verified the phone; non-OTP SMS and WhatsApp need it |
preferences | object | لأ | Overrides per category (TRANSACTIONAL, MARKETING) and channel |
quietHours | QuietHoursBody | لأ | Daily quiet window; none when absent |
timeZone | string | لأ | IANA zone of the recipient's clock; Africa/Cairo when absentmaxLength 40 |
RecipientResponse
A recipient; contact data is masked
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
activeDevices | integer (int32) | لأ | Push devices still active |
createdAt | string (date-time) | لأ | First stored |
email | string | لأ | Masked e-mail |
id | string | لأ | The tenant's own id |
locale | string | لأ | ar or en |
phone | string | لأ | Masked phone |
phoneVerified | boolean | لأ | Whether the tenant verified the phone |
preferences | object | لأ | Effective preferences, defaults included |
quietHours | QuietHoursBody | لأ | Quiet window |
timeZone | string | لأ | IANA zone |
updatedAt | string (date-time) | لأ | Last replaced |
SendOptions
How to deliver. Neither channels nor fallback: auto (inbox plus push, e-mail, WhatsApp, SMS as a fallback chain, over the channels the template has content for)
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
appId | string | لأ | Limit push to one of the tenant's appsmaxLength 150 |
channels | array of "PUSH" | "SMS" | "EMAIL" | "WHATSAPP" | "INBOX" | لأ | Channels each delivered on its ownminItems 0 · maxItems 5 |
fallback | array of "PUSH" | "SMS" | "EMAIL" | "WHATSAPP" | "INBOX" | لأ | One fallback chain, tried in order until one takes itminItems 0 · maxItems 5 |
link | string | لأ | What the push and inbox item open in the appmaxLength 500 |
priority | "HIGH" | "NORMAL" | "LOW" | لأ | HIGH, NORMAL (default) or LOW; LOW transactional goes to the bulk lane |
pushData | object | لأ | The tenant's own keys for its app, sent in the push's data payload beside Tabla's messageId, template and link. Flat strings: at most 20 keys matching [a-zA-Z][a-zA-Z0-9_]{0,39}, values up to 256 characters, 2048 bytes (UTF-8) of keys and values in all. Reserved, in any case: messageId, template, link, from, collapse_key, message_type, notification, aps, and keys starting tabla, google or gcm (MESSAGE_PUSH_DATA_RESERVED). Kept with the message, so retries carry it, and redacted with the body after 30 days. Push only: ids and routing keys, never personal data, as it passes through Google and Apple |
ttlSeconds | integer (int32) | لأ | Seconds the message may still go out; OTP 30 to 1800, others 30 to 604800min 30 · max 604800 |
SendRequest
One message: who, which template, which data, and how
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
data | object | لأ | Template variables: strings, numbers (Arabic-Indic digits in Arabic) and booleans |
options | SendOptions | لأ | Channels, fallback, priority, TTL; all optional |
recipient | RecipientRef | أيوه | The recipient |
template | string | أيوه | Template key, e.g. booking.confirmedmaxLength 100 |
SmsBody
An SMS text
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
text | string | أيوه | TextmaxLength 1600 |
SmsLocales
Arabic and English; at least one
TemplatePage
A page of templates by key
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
items | array of TemplateSummary | لأ | Templates |
next | string | لأ | Pass as `after` for the next page; null on the last |
TemplateRequest
A template's content: per channel, per locale. Text may use {{variable}} placeholders only
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
category | "OTP" | "TRANSACTIONAL" | "MARKETING" | أيوه | OTP, TRANSACTIONAL or MARKETING; fixed after the first version |
email | EmailLocales | لأ | E-mail; html is HTML-escaped per value |
inbox | TitleBodyLocales | لأ | In-app inbox item |
push | TitleBodyLocales | لأ | Push notification |
sms | SmsLocales | لأ | SMS |
whatsapp | WhatsAppLocales | لأ | A WhatsApp template approved by Meta |
TemplateResponse
One version of a template
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
category | "OTP" | "TRANSACTIONAL" | "MARKETING" | لأ | Category |
content | object | لأ | Content per channel and locale |
createdAt | string (date-time) | لأ | When this version was written |
currentVersion | integer (int32) | لأ | The template's current version |
key | string | لأ | Key |
variables | array of string | لأ | Variables a message must supply |
version | integer (int32) | لأ | This version's number |
TemplateSummary
A template in a list
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
category | "OTP" | "TRANSACTIONAL" | "MARKETING" | لأ | Category |
currentVersion | integer (int32) | لأ | Current version |
key | string | لأ | Key |
updatedAt | string (date-time) | لأ | When the current version was written |
TitleBody
A title and a body
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
body | string | أيوه | BodymaxLength 2000 |
title | string | أيوه | TitlemaxLength 200 |
TitleBodyLocales
Arabic and English; at least one
UnreadCount
Unread items
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
unread | integer (int64) | لأ | How many items are unread |
UsageDay
One day and channel
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
channel | string | لأ | Channel |
day | string | لأ | Cairo day |
sent | integer (int64) | لأ | Accepted by the provider |
UsageResponse
Messages providers accepted, per Cairo day and channel
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
days | array of UsageDay | لأ | Rows |
from | string | لأ | First day |
to | string | لأ | Last day |
WhatsAppBody
A Meta-approved template: name, language, and the variables for its body parameters in order
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
language | string | أيوه | Language code at Meta, e.g. ar or en_USmaxLength 10 |
name | string | أيوه | Template name at MetamaxLength 512 |
params | array of string | لأ | Variable names, in parameter orderminItems 0 · maxItems 20 |
WhatsAppLocales
Arabic and English; at least one
| الاسم | النوع | إجباري | الوصف |
|---|---|---|---|
ar | WhatsAppBody | لأ | Arabic template |
en | WhatsAppBody | لأ | English template |