# API Documentation v1.0

Modern, RESTful, and highly performant API designed for seamless integrations.
Base URL: /api/v1/

## Authentication
API requests require a Bearer Token. This can be passed in two ways:
1. HTTP Header (Recommended): `Authorization: Bearer YOUR_API_TOKEN`
2. Query Parameter: Append `?token=YOUR_API_TOKEN` to the URL.

## Profile
### GET /me
Retrieves the authenticated user and company profile.
Response Example:
```json
{
  "status": "success",
  "message": "Profile retrieved successfully",
  "data": { "id": 1, "name": "John Doe", "email": "admin@example.com", "company_id": 1 }
}
```

## Messages
### POST or GET /messages/text
Send a standard text or media message to a phone number.
Payload/Query parameters:
- phone (Required): Recipient's phone number with country code.
- message (Optional): Text content of the message.
- media_url (Optional): Public URL for sending an image/video/document.

### POST or GET /messages/template
Send a pre-approved WhatsApp template message with dynamic variables and rich media headers (Image, PDF / Document, or Video).

Payload/Query parameters:
- phone (Required): Recipient's phone number with country code (e.g. +919876543210).
- template_name (Required): The exact name of the Meta-approved template.
- template_language (Optional): Language code (e.g. en, hi). Default is en. (Alias: language)
- components (Optional): Standard WhatsApp Cloud API component array for HEADER, BODY, and BUTTONS.
  - Image Header: `[{"type": "header", "parameters": [{"type": "image", "image": {"link": "https://..."}}]}]`
  - Document / PDF Header: `[{"type": "header", "parameters": [{"type": "document", "document": {"link": "https://.../invoice.pdf", "filename": "Invoice_2026.pdf"}}]}]`
  - Video Header: `[{"type": "header", "parameters": [{"type": "video", "video": {"link": "https://.../demo.mp4"}}]}]`
  - Body Variables: `[{"type": "body", "parameters": [{"type": "text", "text": "Param"}]}]`

Simplified / Shorthand Parameters (Alternative to components):
- image (Optional): Direct public HTTPS URL to an image (JPG, PNG - max 5 MB).
- document (Optional): Direct public HTTPS URL to a document (PDF - max 100 MB).
- video (Optional): Direct public HTTPS URL to a video (MP4, 3GP - max 16 MB).
- variables (Optional): JSON Array of strings to replace {{1}}, {{2}} variables in body text. Example: ["John", "ORD-12345"]
- header_variables (Optional): JSON Array of strings for header text variables.
- scheduled_at (Optional): Schedule delivery timestamp (ISO timestamp or YYYY-MM-DD HH:MM:SS).
- timezone (Optional): Timezone for scheduled delivery (e.g. Asia/Kolkata).

Media Sources & Guidelines:
- Public URLs: Media links must be direct public HTTPS URLs (e.g. AWS S3, Cloudflare R2, Cloudinary).
- Firebase Storage URLs: Standard Firebase download URLs (with ?alt=media&token=...) work seamlessly out of the box as link.
- Direct Base64 Data URIs: WACM automatically auto-decodes data URIs (e.g. data:image/...;base64,... or data:application/pdf;base64,...), saves the binary to company storage, and passes the hosted HTTPS link to Meta!
- Meta Media IDs: If media was pre-uploaded using Meta's Graph API, pass {"id": "123456789"}.
- Documents support `filename` in Cloud API components or shorthand to control the friendly file name shown in chat.
- The template must be created and approved in Meta with the corresponding media header format.

### POST or GET /messages/list
Send an interactive list message.
Payload/Query parameters:
- phone (Required): Recipient's phone number.
- message (Required): Main body text.
- action (Required): List action definition.
- header (Optional): Header text.
- footer (Optional): Footer text.

## Media (Meta Cloud API Upload)
### POST /media
Upload an Image, PDF / Document, Video, or Audio file directly to Meta WhatsApp Cloud API (`POST /{phone-number-id}/media`).
Returns Meta's official `id` (Meta Media ID) and the hosted `url` in WACM storage.

Payload: `multipart/form-data`
- file (Required): Binary file (Images up to 5 MB, Documents up to 100 MB, Video up to 16 MB).

Response Example:
```json
{
  "status": "success",
  "message": "Media uploaded to Meta successfully",
  "data": {
    "id": "184920491823910",
    "url": "https://app.wacm.in/uploads/media/send/1/api_media_1234.pdf",
    "mime_type": "application/pdf",
    "file_name": "Invoice_9021.pdf",
    "file_size": 240582
  }
}
```

### GET /media/{id}
Retrieve media metadata and direct download URL from Meta servers.

### DELETE /media/{id}
Delete a previously uploaded media asset from Meta servers.

## Contacts
### GET /contacts
Retrieve a paginated list of contacts. Add ?update_from=YYYY-MM-DD HH:MM:SS to filter recently modified contacts.

### POST /contacts
Create or upsert a contact by phone number.
Payload parameters:
- phone (Required): Contact phone number.
- name (Optional): Full name.
- email (Optional): Email address.
- groups (Optional): Comma-separated string or array of group names.
- custom (Optional): Key-value object of custom fields.
- enabled_ai_bot (Optional): Enable (1) or disable (0) AI Bot.

### POST /contacts/bulk-sync
Create or match contacts in bulk and optionally assign them to a group or tag. Assignments are additive and repeated requests do not duplicate memberships.
Payload parameters:
- contacts (Required): Non-empty array of contacts.
- contacts.*.phone (Required): Phone number containing at least one digit.
- contacts.*.name (Optional): Contact name.
- country_code (Optional): Calling code applied to local phone numbers.
- group_id (Optional): Group ID owned by the authenticated company.
- tag_id (Optional): Tag ID owned by the authenticated company.

Response data includes synced_count, updated_count, created_count, and skipped_limit_count. Invalid input or a group/tag outside the authenticated company returns HTTP 422.

### PUT /contacts/{id}
Fully update an existing contact by its database ID. Uses the exact same payload structure as the POST route.

### DELETE /contacts/{id}
Delete an existing contact by its database ID.

### GET /contacts/{id}
Retrieve details of a specific contact by ID.

### GET /contacts/{id}/groups-and-fields
Retrieve all associated groups and custom fields for a specific contact.

### GET /contacts/{id}/notes
Retrieve all notes associated with a specific contact.

### POST /contacts/check-phone
Request an evidence-based WhatsApp reachability check. Send `refresh=true` to bypass the normal settled-result cache. Same-number refreshes have a cooldown and live Meta calls are limited per company. HTTP 202 means the result is pending; `is_valid` is null until a conclusive webhook arrives.
Response Example:
```json
{
  "status": "success",
  "data": {
    "phone": "919876543210",
    "is_valid": null,
    "exists_on_whatsapp": null,
    "check_status": "pending",
    "source": "live_pending"
  }
}
```

## Templates
### GET /templates
List all available templates. Use ?name=TEMPLATE_NAME to filter by exact name.

### GET /templates/{id}
Retrieve details of a specific template by ID.

## Campaigns
### GET /campaigns
List campaigns. Filter using ?type=bot|api|regular.

### POST /campaigns/send
Dispatch a campaign message to a contact dynamically.
Payload parameters:
- phone (Required): Contact's phone number.
- campaign_id (Required): ID of the campaign. (Alias: campaing_id)
- data (Optional): Dynamic variables mapping to the template.

## Conversations
### GET /conversations
Get a list of active chat conversations. Use ?lastmessagetime=YYYY-MM-DD HH:MM:SS to sync new conversations.

### GET /conversations/{id}/messages
Fetch the message timeline for a specific conversation ID. Supports ?lastmessagetime filter.

## Groups
### GET /groups
Retrieve contact groups. Use ?showContacts=yes to eagerly load all assigned contacts.

### POST /groups
Create a contact group. Requires name.

### PUT /groups/{id}
Rename a contact group owned by the authenticated company. Requires name.

### DELETE /groups/{id}
Delete a contact group and detach its contacts.