You can reply from the conversation. On a Colliedesk Cloud trial, a reply to a web form
conversation is refused (error trial_outbound_restricted), because the form cannot prove who owns
the address; a paid plan has no such rule. Self-hosted installs have no trial.
It works the same on self-hosted installs and on Colliedesk Cloud.
Turn it on
- Open Settings → Web form (admins only; agents see the state).
- Under Allowed origins list every site that hosts the form, one per line, for example
https://example.com. An origin is scheme, host and optional port, exactly as the browser shows it. No path, no trailing slash, no wildcard.https://example.comandhttps://www.example.comare two origins. At most 20. - Select Accept web form submissions and Save web form.
The form is off until you do this. Clear the checkbox and save to turn it off again; your
origins stay saved. While it is off, the form answers 404, the same as a workspace that does not
exist. A locked workspace (trial over, nothing paid) answers the same way.
Send a submission
The settings page shows the Submit URL: <your Colliedesk address>/api/v1/public/forms/<workspace slug>.
Post JSON from a page on an allowed origin:
await fetch('https://desk.example.com/api/v1/public/forms/acme', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, message, source: 'site:updates', website: '' }),
});
| Field | Rule |
|---|---|
email |
Required, a plain valid address, at most 254 characters. |
message |
Optional, at most 5000 characters. Empty shows as "(no message)". |
source |
Optional, at most 100 characters. Becomes the subject Web form: <source>. Without it the subject is Web form. |
website |
A hidden field that real visitors leave empty. If it holds text the request is treated as spam: it answers 202 like a success and stores nothing. |
Answers:
202 {"ok": true}: stored (or dropped as spam).404: unknown workspace, form off, or workspace locked.422: invalid input;error.fieldsnames each field, for example{"email": "Enter a valid email address."}.429: too many submissions (see Limits).Retry-Aftersays how long to wait.415: the body is notapplication/json.
Limits and safety
- A browser may call the form only from a listed origin. Other origins get no CORS permission.
Origin checks protect visitors' browsers; they do not authenticate the caller, because any script
can set an
Originheader. That is why the next limits exist. - 5 submissions per minute for each visitor address and workspace, and 30 requests per minute for each visitor address across all forms (this includes the browser's preflight). A workspace also accepts at most 50 form conversations in 10 minutes. That ceiling is separate from email, so form spam never blocks incoming mail. The per-address counts live in the server process: a restart clears them.
- Behind a reverse proxy, Colliedesk must know the proxy to read the visitor's address from
X-Forwarded-For. The server trusts no proxy unlessTRUSTED_PROXIESnames one, whether the variable is unset or empty. The shippedcompose.yamland installer file set it to loopback and the Docker bridge range (127.0.0.0/8,::1/128,172.16.0.0/12) when you do not, which fits a proxy on the same host. For another setup, set it to your proxy's addresses or ranges, comma separated, for exampleTRUSTED_PROXIES=10.0.0.5,10.1.0.0/16(with the installer, put it in.env). With no trusted proxy the server logs a warning at startup, and behind a proxy every visitor counts as the proxy and shares one limit. - On Colliedesk Cloud, sign-up already refuses to start unless
TRUSTED_PROXIESis set to the proxy's address, so the web form uses that same value. - Warning: do not publish the server port on
0.0.0.0(or any public address) without a proxy in front while the compose default is active. A client inside a trusted range, or one that reaches the server directly through Docker's bridge, could then send a fakeX-Forwarded-Forand pick its own address for the limits. The shipped files publish on127.0.0.1only. If you expose the port directly, setTRUSTED_PROXIES=(empty). - Extra fields in the JSON body, such as
name, are ignored. - Answers to a request that is refused before the form is found (too many requests from one
address) carry no CORS permission on purpose (the origin list is not known yet and the server never echoes
an unchecked
Origin), so a browser reports a network error instead of the429. Wait a minute and retry. - Anyone can submit any email address. A submission proves nothing about who owns the address, so do not treat it as verified.
This page is rendered from the repository. Spot a mistake? Open an issue or a pull request.