Skip to content

Send a message ​

Delivers one customer message into the pipeline, with its attachments in the same request.

POST {receiver}/web-chat/message
Authorization: Basic base64(client_id:client_secret)

This goes to the receiver, not the API

The host is the messages_webhook value shown on the channel in the Genudo Console — not {api}.

Returns as soon as the message is queued. The AI reply arrives asynchronously on your callback URL, not in this response.

Text fields plus the binary files, in one request:

bash
curl -X POST "https://receiver.genudo.ai/web-chat/message" \
  -u "wc_YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
  -F "contact_id=user-abc-123" \
  -F "message=Here are the files you asked for" \
  -F "files=@./photo.png" \
  -F "files=@./invoice.pdf"
js
const form = new FormData()
form.append('contact_id', 'user-abc-123')
form.append('message', 'Here are the files you asked for')
form.append('files', new Blob([fs.readFileSync('./photo.png')]), 'photo.png')

await fetch('https://receiver.genudo.ai/web-chat/message', {
  method: 'POST',
  headers: {
    Authorization: 'Basic ' + Buffer.from(`${clientId}:${clientSecret}`).toString('base64'),
    // Do NOT set Content-Type — fetch sets the multipart boundary for you.
  },
  body: form,
})

application/json ​

Text-only messages, or files you already pushed to files_upload_url:

bash
curl -X POST "https://receiver.genudo.ai/web-chat/message" \
  -u "wc_YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{ "contact_id": "user-abc-123", "message": "Do you ship to Cairo?" }'

Request fields ​

FieldTypeRules
contact_idstringRequired, max 255 — the same value on every message in a conversation
messagestringRequired. May be "" when sending attachments only.
filesfile[]multipart only. Field name files or files[]. Max 10 files, 5 MB each.
attachmentsobject[]Optional — { type, url, name? } for files already hosted at a public URL. In multipart, send as a JSON string.

No contact identity here

This endpoint does not accept name, email or phone. Set those once with Initiate. Unknown fields are silently stripped rather than rejected, so sending them here fails quietly.

Any file part under another field name is ignored rather than rejected.

Response ​

json
{
  "status": true,
  "message": "Message received",
  "data": { "message_id": "6a9d596d9b739b3683fbe126" }
}

Different envelope

This is the receiver's own shape — it does not use the console's {status, code, validation, message, data} envelope.

message_id is the Mongo id of the stored inbound message. The reply's callback carries its own, different message_id.

What gets stored ​

Both content types produce identical files[] entries on the message:

json
"files": [
  {
    "path": "uploads/wc_YOUR_CLIENT_ID/01M1VAAK85ZQ61JNJQHMC7WKYF.png",
    "mimetype": "image/png",
    "type": "image",
    "size": 46,
    "name": "photo.png"
  }
]

type is derived from the MIME type: image, video, audio, document, or file. Files are stored privately under your own uploads/{client_id}/ prefix.

Errors ​

CodeCause
400Validation error, or Invalid file path on a JSON files[].path outside uploads/{client_id}/
401Invalid client credentials — bad Basic auth, or the connector is inactive
403Origin not allowed / IP not allowed — adjust the allowlists on the channel in the Console
413File too large — a part exceeded 5 MB