# Washeej Legacy Cloud API (`/external-api`)

HTML UI: https://staging-mobile.washeej.com/external-api-documentation/getting-started

> Fully supported for existing integrations. Prefer API v1 for new work: https://staging-mobile.washeej.com/api-v1-documentation.md

- **Base URL:** `https://staging-mobile.washeej.com/external-api`

## Pages

- [Cloud Introduction](https://staging-mobile.washeej.com/external-api-documentation/getting-started)
- [Cloud Authentication](https://staging-mobile.washeej.com/external-api-documentation/authentication)
- [Cloud Contacts](https://staging-mobile.washeej.com/external-api-documentation/contacts)
- [Cloud Inbox](https://staging-mobile.washeej.com/external-api-documentation/inbox)
- [Cloud Messages](https://staging-mobile.washeej.com/external-api-documentation/messages)
- [Cloud Templates](https://staging-mobile.washeej.com/external-api-documentation/templates)
- [Migrate to v1](https://staging-mobile.washeej.com/external-api-documentation/migrate)

## Endpoints

### GET `/ping`

- **Key:** `ping`
- **URL:** `https://staging-mobile.washeej.com/external-api/ping`
- **Auth:** public / none
- **Summary:** Public connectivity check. Returns detected IP for whitelist debugging.

```bash
curl https://staging-mobile.washeej.com/external-api/ping
```

### GET `/contact/list`

- **Key:** `contacts.list`
- **URL:** `https://staging-mobile.washeej.com/external-api/contact/list`
- **Auth:** public / none
- **Summary:** List contacts for the authenticated account.

```bash
curl -H "client-id: YOUR_CLIENT_ID" \
     -H "client-secret: YOUR_CLIENT_SECRET" \
     https://staging-mobile.washeej.com/external-api/contact/list
```

API v1 equivalent: `GET /v1/contacts`

### POST `/contact/store`

- **Key:** `contacts.store`
- **URL:** `https://staging-mobile.washeej.com/external-api/contact/store`
- **Auth:** public / none
- **Summary:** Create a contact.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `firstname` | string | yes | First name. |
| `lastname` | string | no | Last name. |
| `mobile_code` | string | yes | Dial code without +. |
| `mobile` | string | yes | National number digits. |

```bash
curl -X POST https://staging-mobile.washeej.com/external-api/contact/store \
  -H "client-id: YOUR_CLIENT_ID" \
  -H "client-secret: YOUR_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"firstname":"Ahmed","mobile_code":"966","mobile":"500000000"}'
```

API v1 equivalent: `POST /v1/contacts`

### POST `/contact/update/{id}`

- **Key:** `contacts.update`
- **URL:** `https://staging-mobile.washeej.com/external-api/contact/update/{id}`
- **Auth:** public / none
- **Summary:** Update an existing contact.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | integer | yes | Contact ID. |
| `firstname` | string | no | First name. |
| `lastname` | string | no | Last name. |

```bash
curl -X POST https://staging-mobile.washeej.com/external-api/contact/update/4821 \
  -H "client-id: YOUR_CLIENT_ID" \
  -H "client-secret: YOUR_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"firstname":"Ahmed"}'
```

API v1 equivalent: `PATCH /v1/contacts/{id}`

### DELETE `/contact/delete/{id}`

- **Key:** `contacts.delete`
- **URL:** `https://staging-mobile.washeej.com/external-api/contact/delete/{id}`
- **Auth:** public / none
- **Summary:** Delete a contact.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | integer | yes | Contact ID. |

```bash
curl -X DELETE https://staging-mobile.washeej.com/external-api/contact/delete/4821 \
  -H "client-id: YOUR_CLIENT_ID" \
  -H "client-secret: YOUR_CLIENT_SECRET"
```

API v1 equivalent: `DELETE /v1/contacts/{id}`

### GET `/inbox/conversation-list`

- **Key:** `inbox.list`
- **URL:** `https://staging-mobile.washeej.com/external-api/inbox/conversation-list`
- **Auth:** public / none
- **Summary:** List conversations.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `whatsapp_account_id` | integer | no | Filter by Cloud account. |

```bash
curl -H "client-id: YOUR_CLIENT_ID" \
     -H "client-secret: YOUR_CLIENT_SECRET" \
     https://staging-mobile.washeej.com/external-api/inbox/conversation-list
```

API v1 equivalent: `GET /v1/conversations`

### GET `/inbox/conversation-details/{id}`

- **Key:** `inbox.details`
- **URL:** `https://staging-mobile.washeej.com/external-api/inbox/conversation-details/{id}`
- **Auth:** public / none
- **Summary:** Get conversation details and contact info.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | integer | yes | Conversation ID. |

```bash
curl -H "client-id: YOUR_CLIENT_ID" \
     -H "client-secret: YOUR_CLIENT_SECRET" \
     https://staging-mobile.washeej.com/external-api/inbox/conversation-details/20717
```

API v1 equivalent: `GET /v1/conversations (list) + messages endpoint`

### GET `/inbox/conversation-messages/{id}`

- **Key:** `inbox.messages`
- **URL:** `https://staging-mobile.washeej.com/external-api/inbox/conversation-messages/{id}`
- **Auth:** public / none
- **Summary:** Paginated messages for a conversation.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | integer | yes | Conversation ID. |

```bash
curl -H "client-id: YOUR_CLIENT_ID" \
     -H "client-secret: YOUR_CLIENT_SECRET" \
     https://staging-mobile.washeej.com/external-api/inbox/conversation-messages/20717
```

API v1 equivalent: `GET /v1/conversations/{id}/messages`

### POST `/inbox/change-conversation-status/{id}`

- **Key:** `inbox.status`
- **URL:** `https://staging-mobile.washeej.com/external-api/inbox/change-conversation-status/{id}`
- **Auth:** public / none
- **Summary:** Change conversation status / mark read typing indicators where supported.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | integer | yes | Conversation ID. |

```bash
curl -X POST https://staging-mobile.washeej.com/external-api/inbox/change-conversation-status/20717 \
  -H "client-id: YOUR_CLIENT_ID" \
  -H "client-secret: YOUR_CLIENT_SECRET"
```

### POST `/inbox/send-message`

- **Key:** `messages.send`
- **URL:** `https://staging-mobile.washeej.com/external-api/inbox/send-message`
- **Auth:** public / none
- **Summary:** Send a free-form Cloud session message (text, media, location, interactive, commerce).

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `mobile_code` | string | yes | Dial code without +. |
| `mobile` | string | yes | National number. |
| `message` | string | no | Text body or media caption (required unless media/interactive/location/product). |
| `whatsapp_account_id` | integer | no | Cloud account ID (preferred in multi-number accounts). |
| `from_number` | string | no | Alternative channel selector (digits only). |
| `image` | file | no | Image upload (multipart). |
| `document` | file | no | Document upload (multipart). |
| `video` | file | no | Video upload (multipart). |
| `audio` | file | no | Audio upload (multipart). |
| `latitude` | number | no | Location latitude (with longitude). |
| `longitude` | number | no | Location longitude (with latitude). |
| `name` | string | no | Optional location title. |
| `address` | string | no | Optional location address. |
| `cta_url_id` | integer | no | Dashboard CTA URL asset ID. |
| `interactive_list_id` | integer | no | Dashboard interactive list ID. |
| `product` | json | no | Commerce product payload. |
| `created_order_data` | json | no | Commerce order payload. |

Notes:

- Requires IP whitelist.
- Outside the 24h window use POST /inbox/send-template-message.
- Session media on Cloud External API: multipart file fields only. Session *_url fields are not implemented on this surface.
- For native PDF/image bubbles outside the session window use templates with header_media_url.
- CTA / lists / product require Cloud + open session.
- Prefer whatsapp_account_id or exact from_number (mismatched from_number returns sender_not_found).

```bash
curl -X POST https://staging-mobile.washeej.com/external-api/inbox/send-message \
  -H "client-id: YOUR_CLIENT_ID" \
  -H "client-secret: YOUR_CLIENT_SECRET" \
  -H "Content-Type: multipart/form-data" \
  -F "mobile_code=966" \
  -F "mobile=500000000" \
  -F "whatsapp_account_id=YOUR_CLOUD_ACCOUNT_ID" \
  -F "message=Your invoice is attached" \
  -F "document=@/path/to/INV-1001.pdf;type=application/pdf"
```

API v1 equivalent: `POST /v1/messages`

### GET `/inbox/template-list`

- **Key:** `templates.list`
- **URL:** `https://staging-mobile.washeej.com/external-api/inbox/template-list`
- **Auth:** public / none
- **Summary:** List approved Cloud templates (default). Pass ?status=all for the full inventory.

```bash
curl -H "client-id: YOUR_CLIENT_ID" \
     -H "client-secret: YOUR_CLIENT_SECRET" \
     https://staging-mobile.washeej.com/external-api/inbox/template-list
```

API v1 equivalent: `GET /v1/templates`

### POST `/inbox/send-template-message`

- **Key:** `templates.send`
- **URL:** `https://staging-mobile.washeej.com/external-api/inbox/send-template-message`
- **Auth:** public / none
- **Summary:** Send an approved Cloud template (text variables and/or DOCUMENT/IMAGE/VIDEO header media).

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `template_id` | string | yes | Washeej template ID or Meta whatsapp_template_id. |
| `mobile_code` | string | yes | Dial code. |
| `mobile` | string | yes | National number. |
| `body_variables` | string[] | no | Ordered body variable values (omit if body has no placeholders). |
| `header_variables` | string[] | no | TEXT header variable values. |
| `header_media_url` | url | no | Public HTTPS media URL when header_format is DOCUMENT/IMAGE/VIDEO (native file bubble). |
| `header_media_file` | file | no | Multipart upload alternative to header_media_url (also accepts media_file). |
| `whatsapp_account_id` | integer | no | Cloud account ID. |
| `from_number` | string | no | Alternative channel selector (digits only). |

Notes:

- DOCUMENT/IMAGE/VIDEO headers: pass header_media_url or header_media_file — Graph receives filename for DOCUMENT automatically (basename or header_media_filename). Oversized/failed media returns a clear error (not a silent skip).
- Text URL inside body: use body_variables — see Dynamic Invoice Link guide.
- AUTHENTICATION OTP: exactly one 4–8 digit code in body_variables; Washeej attaches the copy-code button parameter when required.
- template_id accepts local templates.id or Meta whatsapp_template_id.
- Cloud API channels only. Prefer whatsapp_account_id or exact from_number (mismatched from_number → sender_not_found).
- MARKETING templates may return marketing_suppressed for opted-out contacts.

```bash
curl -X POST https://staging-mobile.washeej.com/external-api/inbox/send-template-message \
  -H "client-id: YOUR_CLIENT_ID" \
  -H "client-secret: YOUR_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "template_id": "YOUR_TEMPLATE_ID",
    "mobile_code": "966",
    "mobile": "500000000",
    "whatsapp_account_id": YOUR_CLOUD_ACCOUNT_ID,
    "header_media_url": "https://files.example.com/docs/INV-1001.pdf",
    "body_variables": ["Ahmed", "INV-1001"]
  }'
```

API v1 equivalent: `POST /v1/templates/send`

## Scenario map (legacy paths)

| Need | Endpoint | Key fields |
| --- | --- | --- |
| Session text | `POST /inbox/send-message` | `message`, `whatsapp_account_id` |
| Session PDF/media | `POST /inbox/send-message` | `document_url` / multipart `document`, `image_url`, … |
| CTA / list / location | `POST /inbox/send-message` | `cta_url_id`, `interactive_list_id`, `latitude`/`longitude` |
| Outside 24h / templates | `POST /inbox/send-template-message` | `template_id`, `body_variables` |
| Native PDF template | `POST /inbox/send-template-message` | `header_media_url` or `header_media_file` |
| OTP | `POST /inbox/send-template-message` | AUTHENTICATION + one 4–8 digit code |

Deep guides (same product rules; swap to `/external-api` paths above): https://staging-mobile.washeej.com/api-v1-documentation/guides/integration-playbook

