English
HTTP request
Calls an external API and puts the response into the working data. A write may be retried after an outage: prefer idempotent endpoints.
Calls an external API and puts the response into the working data. Use it to push a case into a CRM, look up a customer in your own back office, or upload the email's invoice to an OCR or document tool. For a simple message to Slack, Teams or a webhook, Notify is shorter: it builds the payload for you.
The request goes through the server's guarded HTTP client, never directly from the workflow. Authentication comes from a stored connection (see API key (HTTP)), so secrets never appear in the node, the step data or the logs.
At a glance
- Type:
http.request· version 1 - Category: Data
- Kind: Step — one stage of a run
- Effect: Writes outside (
external_write) — writes outside Mankomail; described instead of performed during a test run - Needs a carrier email: No
- Connection: API key (HTTP)
- Inputs:
main - Outputs:
main
Connection
This node needs a API key (HTTP) connection.
Parameters
method
Method
- Type: One choice (
options) - Required: Yes
- Default:
GET - Options:
GET— GETPOST— POSTPUT— PUTPATCH— PATCHDELETE— DELETE
url
URL
- Type: Text (
string) - Required: Yes
- Default:
""(empty) - 2000 characters at most
- Example:
https://api.example.com/v1/tickets - Expressions:
{{ }}accepted
credential
Authentication — Optional. The connection to apply (API key, Bearer, Basic, query parameter). The server adds it to the request — its value appears nowhere.
- Type: Connection (
credential) - Required: No
- Default:
""(empty)
headers
Headers — Connections (API key, Bearer…) are picked above and never typed here.
- Type: Key / value pairs (
keyValue) - Required: No
- Default:
[] - Expressions:
{{ }}accepted
bodyMode
Payload
- Type: One choice (
options) - Required: Yes
- Default:
text - Options:
none— Nothing: A request with no body.text— Text: The body you write. Accepts{{ }}expressions. Set the matchingContent-Typeheader.json— JSON: The same body, withContent-Type: application/jsonset for you.multipart— Form with files: Uploads the email attachments to the API (multipart/form-data) — the "drop the invoice into our tool" case.
- Shown when:
methodis one ofPOST,PUT,PATCH,DELETE
body
Body — Text body. Accepts {{ }} expressions. For JSON, write the JSON and set the Content-Type header.
- Type: Long text (
text) - Required: No
- Default:
""(empty) - 100000 characters at most
- Shown when:
methodis one ofPOST,PUT,PATCH,DELETEandbodyModeis one oftext,json - Expressions:
{{ }}accepted
multipartFields
Form fields — The text parts of the upload: {{ email.subject }}, a case id…
- Type: List of items (
collection) - Required: No
- Default:
[] - At most 20 items
- Each item has:
name— Field name- Type: Text (
string) - Required: Yes
- Default:
""(empty) - 200 characters at most
- Expressions:
{{ }}not accepted
- Type: Text (
value— Value- Type: Text (
string) - Required: No
- Default:
""(empty) - 10000 characters at most
- Type: Text (
- Shown when:
methodis one ofPOST,PUT,PATCH,DELETEandbodyModeismultipart
multipartFiles
Files to upload — One row = one form field fed by the matching attachments. Several matches = several parts sharing the field name.
- Type: List of items (
collection) - Required: No
- Default:
[] - At most 10 items
- Each item has:
name— Field name- Type: Text (
string) - Required: Yes
- Default:
file - 200 characters at most
- Example:
file - Expressions:
{{ }}not accepted
- Type: Text (
selection— Attachments to use- Type: One choice (
options) - Required: Yes
- Default:
all - Options:
all— All attachments: Those of the triggering email, then the files added by earlier steps (a fetched deed, a signed PDF), in that order.first— The first one only: The first attachment, when only one matters.byMime— By file type: By MIME type:application/pdf, or a whole family withimage/*.byName— By file name: By name pattern:*.pdf,invoice-*.
- Type: One choice (
mime— File type. Exact MIME type (application/pdf) or a whole family (image/*). Left empty, no attachment is kept.- Type: Text (
string) - Required: No
- Default:
""(empty) - 200 characters at most
- Example:
application/pdf - Shown when:
selectionisbyMime
- Type: Text (
namePattern— File name. Simple pattern:*matches anything,?one character (*.pdf,invoice-*). Case is ignored.- Type: Text (
string) - Required: No
- Default:
""(empty) - 200 characters at most
- Example:
*.pdf - Shown when:
selectionisbyName
- Type: Text (
- Shown when:
methodis one ofPOST,PUT,PATCH,DELETEandbodyModeismultipart
timeoutMs
Timeout — Past this, the request is abandoned and the step fails.
- Type: Duration (
duration) - Required: No
- Default: 10 seconds (
10000) - Stored in milliseconds, typed in seconds or minutes
- From 1 second to 2 minutes
- Shown under “Advanced” in the editor
failOn4xx5xx
Fail on error response — On: a status ≥ 400 fails the step — retries and “If the failure persists” then apply (Settings tab). Off: the response flows into the working data.
- Type: Yes / no (
boolean) - Required: No
- Default:
true - Shown under “Advanced” in the editor
Outputs
main— Taken once the response is received. With Fail on error response on, a status of 400 or more fails the step instead.
Data produced
What this node adds to the run data, and how to read it in an expression. <step> stands for the step key: the node name turned into an identifier (see Data and expressions).
{{ data.<step>.status }}—number. The HTTP status of the response (200, 201, 404…).{{ data.<step>.ok }}—boolean. true when the status is below 400.{{ data.<step>.headers }}—object. The response headers, names in lower case ({{ data.<step>.headers.content-type }}). A repeated header is joined with a comma.{{ data.<step>.bodyText }}—string. The response body as text, cut at 20,000 characters.{{ data.<step>.bodyTruncated }}—boolean. true when bodyText was cut at 20,000 characters.{{ data.<step>.bodyJson }}—object. The parsed body, only when the response declares a JSON Content-Type and parses. Read a field with{{ data.<step>.bodyJson.id }}.{{ data.<step>.simulated }}—boolean. true in a test run: no request left the server.{{ data.<step>.bodyMode }}—string. The payload mode actually used: none, text, json or multipart (always none for GET).{{ data.<step>.multipart.fields }}—number. Multipart only: the number of text fields sent.{{ data.<step>.multipart.files }}—array of { name, position, filename, mime, size }. Multipart only: the file parts sent, one entry per attachment.{{ data.<step>.multipart.unmatched }}—array. Multipart only: the names of the file fields that matched no attachment and were left out.{{ data.<step>.summary }}—string. A one-line summary of the step, for examplePOST 201.
Example
A workflow creates a ticket in a support tool for each new customer request. The node is named "Create ticket", so its data lives under create_ticket.
text
method POST
url https://api.example.com/v1/tickets
credential Support tool API key
bodyMode json
body {"subject": "{{ email.subject }}", "from": "{{ email.from.email }}"}
failOn4xx5xx onWith JSON as the payload, the Content-Type: application/json header is added for you. If the API answers 201 with {"id": "T-4812"}, the next nodes read:
text
{{ data.create_ticket.status }} → 201
{{ data.create_ticket.bodyJson.id }} → T-4812To upload attachments instead, choose Form with files as the payload. Each row of Files to upload is one form field (for example file) fed by the attachments that match its filter (all, the first one, by file type or by file name); several matches produce several parts with the same field name. Form fields add the text parts, such as a case number.
Tips
- Methods and body. GET sends no body, whatever the payload setting. POST, PUT, PATCH and DELETE send the body chosen in Payload. With Text, set the
Content-Typeheader yourself. - Authentication. Pick the connection in Authentication; never type an
Authorizationheader by hand. The connection replaces anyAuthorizationheader with the same name. It must be active and belong to you or to your organisation, otherwise the step fails. - Blocked addresses. Only
httpandhttpson ports 80 and 443 are allowed. Private, loopback, link-local, multicast and reserved addresses (including cloud metadata addresses) are refused, as are user names or passwords inside the URL. The check applies to the address actually connected and to every redirect. - Redirects. Up to 5 redirects are followed. On a change of host,
Authorization,CookieandProxy-Authorizationheaders are dropped. A 303, or a 301/302 after a POST, continues as a GET without a body. - Size and time limits. A response larger than 2 MiB fails the step. Only the first 20,000 characters are kept in
bodyText. The Timeout (ms) applies per request and is capped at 60 seconds by the server, even if the field accepts more. - Files. A file field that matches no attachment is skipped and listed in
multipart.unmatched. If no part at all remains, the step fails withnode_nothing_to_do. An attachment that is selected but can no longer be read, or that exceeds 10 MiB, makes the request fail: the API never receives an incomplete upload. - Error responses. With Fail on error response on (the default), a status of 400 or more fails the step with
http_error_status. 429 and 5xx are retried automatically; other 4xx are final. Turn it off to handle the status yourself, for example with a Condition (If) node on{{ data.<step>.ok }}. - Replays. After an incident the engine may run the step again. Each request carries an
Idempotency-Keyheader; if the API ignores it, a POST, PUT, PATCH or DELETE can be executed twice. Prefer idempotent endpoints (upsert by business key) for writes. - Test runs. Every request is simulated, GET included: nothing leaves the server, not even a DNS lookup. The step returns status 200, an empty JSON object
{}as the body andsimulated: true. Nodes that depend on a real response body will see empty values in a test. See Test runs.