Web forms
The one endpoint your own site calls, and the only Wrap endpoint a browser can reach.
POST https://wrap.eel.software/api/inbound/web-form
Nearly all of Eel's API is server to server. This endpoint is the exception: it exists so your site's contact form can drop a conversation into the inbox.
It uses no API key. It identifies itself by the channel.
The body
{
"channelInstanceId": "…",
"email": "ana@example.com",
"message": "I'd like a quote for 200 units",
"name": "Ana Restrepo",
"phone": "+57 300 123 4567",
"formId": "home-contact",
"source": "black-friday-landing",
"consentMarketing": true
}
| Field | Required | Notes |
|---|---|---|
channelInstanceId |
Yes | Identifies the form. Comes from the channel's tab in Wrap |
email |
Yes | It is what makes a reply possible. Max 254 characters |
message |
Yes | Between 1 and 20,000 characters |
name |
No | Up to 120 |
phone |
No | Up to 40 |
formId |
No | To tell two forms on the same channel apart |
source |
No | Where the visit came from |
consentMarketing |
No | Only an explicit true grants permission |
On that last one: a missing field is not a refusal, and a false revokes
nothing. Revoking has its own paths, and none of them is omitting a checkbox.
Signing submissions
If the channel has a secret configured, every submission must be signed. Compute an HMAC-SHA256 of the raw request body and send it as:
X-Wrap-Signature: sha256=<hex>
Sign the exact bytes you send, before any re-serialization. Turning the object back into JSON to sign it is the most common way to produce a signature that does not match.
Unsigned, or signed wrong, is rejected.
Without a secret
The endpoint accepts anonymous submissions, capped at 20 per minute per IP and per form.
That is a minimal net, not a defence. If the form sits on a public page, put a captcha in front of it on your own site.
Calls from the browser
It is the only Wrap endpoint that accepts them: it answers the preflight and
sends Access-Control-Allow-Origin: *, so the form can be submitted from the
visitor's own browser.
The rest of Wrap's public API sends no CORS headers and is unreachable from a page. An API key in a site's JavaScript is a published API key.
The channel decides the workspace
The workspace is read from the channel channelInstanceId points at. There is no
workspace field in the body, so nobody can post an enquiry into somebody else's
workspace by changing a value in the JSON.