# RafikiSMS API Specification

Version: 1.0.0

Base URL: `https://api.rafikisms.com`

This document summarizes the RafikiSMS REST API for Postman collections, client integration notes, and human-readable reference material.

Authentication:

- API key endpoints require `X-API-Key: sk_your_api_key_here`.
- Dashboard-authenticated endpoints require `Authorization: Bearer YOUR_ACCESS_TOKEN`.
- `POST /v1/otp/verify` is public and does not require an API key.

Rate limits:

- API key and bearer-token endpoints: 60 requests per minute.
- OTP generate: 3 requests per phone number per 5 minutes.
- Rate limit responses use HTTP `429 Too Many Requests`.

## POST /v1/vendor/send-sms
**Send single SMS**
Queues one SMS message for asynchronous delivery. Phone numbers must be in international format without the plus sign, for example 255712345678. If sender_id, sender, or source_address is omitted, the account default sender is used.
Authentication: X-API-Key header
Request example:

```json
{
  "phone": "255712345678",
  "message": "Hello! This is a test message from RafikiSMS.",
  "sender_id": "MYBRAND"
}
```

Success response example:

```json
{
  "status": "success",
  "message": "SMS queued successfully",
  "data": {
    "message": "SMS has been queued for sending",
    "note": "SMS will be processed asynchronously. Check SMS logs for status updates."
  }
}
```

## POST /v1/vendor/send-bulk-sms
**Send bulk SMS**
Queues one message for multiple recipients. Use recipients as an array of phone numbers or phone as a comma-separated string. Multipart uploads can also pass recipients_file in the dashboard flow.
Authentication: X-API-Key header
Request example:

```json
{
  "message": "Your bulk message content (max 160 characters)",
  "phone": "255712345678,255621728109,255620656604",
  "sender_id": "MYBRAND"
}
```

Success response example:

```json
{
  "status": "success",
  "message": "Bulk SMS queued successfully",
  "data": {
    "message": "Bulk SMS has been queued for sending",
    "total_recipients": 3,
    "note": "SMS will be processed asynchronously."
  }
}
```

## GET /v1/sms-logs
**Get SMS logs**
Returns paginated SMS logs for the authenticated user.
Authentication: Bearer token
Parameters:

| Name | In | Required | Description |
| --- | --- | --- | --- |
| page | query | no | Page number. Defaults to 1. |
| per_page | query | no | Items per page. Defaults to 10, maximum 100. |

Success response example:

```json
{
  "status": "success",
  "message": "SMS logs retrieved successfully",
  "data": {
    "current_page": 1,
    "data": [
      {
        "id": 15,
        "user_id": 4,
        "recipient": "255712345678",
        "message": "Hello! This is a test message",
        "status": "success",
        "transaction_id": "19725260",
        "created_at": "2025-12-11T13:10:15.000000Z",
        "updated_at": "2025-12-11T13:10:17.000000Z"
      }
    ],
    "per_page": 10,
    "total": 15,
    "last_page": 2
  }
}
```

## POST /v1/otp/generate
**Generate OTP**
Sends a one-time password to a phone number. The OTP code is never returned in the API response. Use the returned reference_id when verifying the user-entered code. Rate limit: 3 generate calls per phone number per 5 minutes. If sender_id is omitted, the SMS will be sent using the RafikiSMS default company sender name instead of your brand.
Authentication: X-API-Key header
Request example:

```json
{
  "phone_number": "255712345678",
  "sender_id": "MYSHOP-OTP"
}
```

Success response example:

```json
{
  "success": true,
  "message": "OTP sent successfully.",
  "data": {
    "reference_id": "550e8400-e29b-41d4-a716-446655440000",
    "expires_in_seconds": 300
  }
}
```

## POST /v1/otp/verify
**Verify OTP**
Verifies the 6-digit code received by SMS. This public endpoint does not require an API key. Each reference_id allows a maximum of 5 wrong attempts before it is locked.
Authentication: None
Request example:

```json
{
  "phone_number": "255712345678",
  "otp_code": "482916",
  "reference_id": "550e8400-e29b-41d4-a716-446655440000"
}
```

Success response example:

```json
{
  "success": true,
  "message": "Verification successful.",
  "data": {
    "verified": true
  }
}
```

## GET /v1/vendor/sender-names
**Get sender names**
Retrieves sender names associated with the API key account.
Authentication: X-API-Key header
Parameters:

| Name | In | Required | Description |
| --- | --- | --- | --- |
| page | query | no | Page number. Defaults to 1. |
| per_page | query | no | Items per page. Defaults to 10, maximum 100. |
| status | query | no | Optional sender-name status filter, for example active or pending. |

Success response example:

```json
{
  "success": true,
  "message": "Sender names retrieved successfully",
  "data": {
    "sender_names": [
      {
        "id": "c893d701-e1d8-4b00-8634-8c464e56ba11",
        "senderid": "STARSHINE",
        "sample_content": "This sender name is used for order confirmations",
        "status": "active",
        "created": "2025-07-08T14:07:56.000Z"
      }
    ],
    "pagination": {
      "totalItems": 1,
      "currentPage": 1,
      "pageSize": 25,
      "totalPages": 1
    }
  }
}
```

## GET /v1/vendor/balance
**Check balance**
Returns the current SMS credit balance for the API key account.
Authentication: X-API-Key header
Success response example:

```json
{
  "status": "success",
  "message": "Balance retrieved successfully",
  "data": {
    "credit_balance": 1000
  }
}
```

## GET /v1/vendor/delivery-reports
**Get delivery report**
Checks delivery status for a sent SMS. Query at least 5 minutes after sending to allow for network delays. Status values include DELIVERED, PENDING, and UNDELIVERED.
Authentication: X-API-Key header
Parameters:

| Name | In | Required | Description |
| --- | --- | --- | --- |
| dest_addr | query | yes | Destination phone number in international format. |
| request_id | query | yes | SMS request or transaction ID returned by the send endpoint. |

Success response example:

```json
{
  "status": "success",
  "message": "Delivery report retrieved successfully",
  "data": {
    "delivery_reports": [
      {
        "dest_addr": "255712345678",
        "status": "DELIVERED",
        "request_id": "19725260"
      }
    ]
  }
}
```

## POST /v1/sender-names/request
**Request sender name**
Requests a new sender name. The sender ID must be 11 characters or fewer and can contain letters, numbers, spaces, hyphens, and dots.
Authentication: Bearer token
Request example:

```json
{
  "senderid": "STARSHINE",
  "sample_content": "This sender name will be used for sending order confirmations and delivery notifications to our customers"
}
```

Success response example:

```json
{
  "status": "success",
  "message": "Sender name requested successfully",
  "data": {
    "id": "24e1ffaf-e399-4b15-983a-53539e4970bd",
    "senderid": "STARSHINE",
    "sample_content": "This sender name will be used for sending order confirmations",
    "status": "pending"
  }
}
```

## PUT /v1/vendors/delivery-webhook
**Configure delivery webhook**
Sets or disables the HTTPS URL that receives SMS delivery status events. Only the parent vendor account can set this URL; sub-accounts inherit it. Pass null to disable.
Authentication: Bearer token
Request example:

```json
{
  "delivery_webhook_url": "https://yourapp.com/webhooks/sms"
}
```

Success response example:

```json
{
  "status": "success",
  "message": "Delivery webhook updated successfully",
  "data": {
    "delivery_webhook_url": "https://yourapp.com/webhooks/sms"
  }
}
```

## Delivery Webhook Payload

After you configure `PUT /v1/vendors/delivery-webhook`, RafikiSMS sends delivery status events to your HTTPS endpoint. Respond with any 2xx status within 8 seconds, then process the payload asynchronously.

```json
{
  "event": "sms.delivery_status",
  "event_time": "2025-07-08T14:08:02+00:00",
  "vendor": {
    "id": 42,
    "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "email": "vendor@example.com"
  },
  "data": {
    "sms_log_id": 19725260,
    "status": "delivered",
    "recipient": "255712345678",
    "sender_id": "MYBRAND",
    "transaction_id": "19725260",
    "message_id": "msg_abc123",
    "message": "Hello from RafikiSMS!",
    "delivered_at": "2025-07-08T14:08:02+00:00",
    "failure_reason": null,
    "source_addr": "MYBRAND",
    "dest_addr": "255712345678",
    "processing_time_ms": 1240,
    "created_at": "2025-07-08T14:07:56+00:00",
    "updated_at": "2025-07-08T14:08:02+00:00"
  }
}
```
