Wāwā Assistant External Integration API — /api/v1/
Usage guide for external integrators.
https://<host>/api/v1/ (<host> is provided by the platform operator)Content-Type: application/json; all responses are JSON)Exchange a platform user's credentials for a long-lived access token:
POST /api/v1/token/
{
"username": "your-username",
"password": "your-password"
}
Successful response:
{
"access": "<jwt>"
}
Include a Bearer header on every subsequent request:
Authorization: Bearer <jwt>
Note: /api/v1/ accepts JWT only — browser sessions get 401. Conversely, this JWT is not valid for other namespaces (calling /api/ with it returns 403).
Every draft must be attached to an email account (config). Use these endpoints to find the available config ids.
GET /api/v1/email-config/
GET /api/v1/email-config/{id}/
Returns only configs owned by the token user that are not archived. The response is a fixed set of five fields and never includes credentials, OAuth data, or folder information:
| Field | Description |
|---|---|
id | Config id — the value for config when creating a draft |
email_address | The email address |
provider | Email provider; currently only OUTLOOK |
status | active / syncing / inactive / auth_failed |
created_at | Creation time |
The list is ordered by email_address; pagination is described in §4.
POST /api/v1/email-draft/
{
"config": 3,
"in_reply_to": null,
"to_recipients": ["alice@example.com"],
"cc_recipients": [],
"bcc_recipients": [],
"subject": "Quarterly report",
"content": "<p>Hello…</p>",
"content_type": "html"
}
| Field | Required | Description |
|---|---|---|
config | Yes | Id of the email account to attach to; must belong to the token user and not be archived, otherwise a 400 field error |
in_reply_to | No | Id of the email being replied to; must be visible to the user and belong to the same account as config, otherwise 400. Omit it to create a fresh (non-reply) draft |
to_recipients / cc_recipients / bcc_recipients | No | Arrays of email addresses |
subject | No | Subject line |
content | No | Body |
content_type | No | text or html |
On success the API returns 201 with the full draft object (including the read-only fields below). Once stored, the draft is automatically pushed to the provider's (Outlook's) drafts folder — no extra call needed. Non-Outlook accounts end up in sync_failed.
GET /api/v1/email-draft/
GET /api/v1/email-draft/{id}/
?config=<id>, ?status=<status>; pagination in §4.| Field | Description |
|---|---|
status | Draft status, see §3.4 |
last_error | Error message from the most recent failed sync |
provider_draft_id | Remote (Outlook) draft id; empty until sync succeeds |
sent_at | Send time (reserved for the future send path; currently always empty) |
created_at / updated_at | Creation / update time |
Syncing is asynchronous: after creating, poll status until it reaches synced or sync_failed (the API does not provide webhooks).
A draft cannot be changed after creation — there is no PUT/PATCH (both always return 405). To "edit" a draft:
DELETE /api/v1/email-draft/{id}/POST /api/v1/email-draft/ again with the new contentThe new draft is pushed to Outlook as usual; the old remote draft is cleaned up by the deletion flow.
draft ──► syncing ──► synced
└───► sync_failed
| Status | Meaning | Deletable |
|---|---|---|
draft | Stored, waiting to sync | ✅ |
syncing | Being pushed to Outlook | ❌ (409 — retry later) |
synced | Present in the Outlook drafts folder | ✅ |
sync_failed | Sync failed (retries exhausted or unsupported account); see last_error | ✅ |
sending / sent | Reserved for the send path | ❌ (409) |
DELETE /api/v1/email-draft/{id}/
draft / synced / sync_failed can be deleted; any other status returns 409.List endpoints use page-number pagination, fixed at 10 items per page, with ?page=N:
{
"count": 23,
"next": "https://<host>/api/v1/email-draft/?page=2",
"previous": null,
"results": [ … ]
}
| HTTP status | Scenario |
|---|---|
| 400 | Request body validation failed: malformed fields, or config / in_reply_to not owned by the user or violating the ownership rules (the body contains field-level errors) |
| 401 | Missing / invalid / expired token (response carries WWW-Authenticate: Bearer) — obtain a new token |
| 404 | Resource does not exist, or does not belong to the token user |
| 405 | Method not allowed (e.g. PUT/PATCH on a draft — drafts are immutable) |
| 409 | Draft status does not allow deletion (syncing / sending / sent) |
HOST="https://<host>"
# 1. Obtain a token
TOKEN=$(curl -s -X POST "$HOST/api/v1/token/" \
-H "Content-Type: application/json" \
-d '{"username": "me", "password": "secret"}' | jq -r .access)
# 2. Discover available email accounts
curl -s "$HOST/api/v1/email-config/" -H "Authorization: Bearer $TOKEN"
# 3. Create a draft
curl -s -X POST "$HOST/api/v1/email-draft/" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"config": 3,
"to_recipients": ["alice@example.com"],
"subject": "Quarterly report",
"content": "<p>Hello…</p>",
"content_type": "html"
}'
# 4. Poll sync status
curl -s "$HOST/api/v1/email-draft/42/" -H "Authorization: Bearer $TOKEN"
# 5. Delete the draft
curl -s -X DELETE "$HOST/api/v1/email-draft/42/" -H "Authorization: Bearer $TOKEN"
status instead)If you need any of the above, contact the platform operator.