Workflow Step: Send a Web Request

Call another system's API from a workflow, like creating a contact in a CRM or posting to a chat app, with values from the run and secrets kept safe.

What Send a web request does

Send a web request calls another system's web address (its API) from a workflow run. For example, it can create a contact in a CRM, send an order to a delivery service, or post a message in a chat app. It waits for the server response, saves it, and moves on. Later steps can use the server response.

Set it up

Add a step and choose Send a web request under Does what. It has four boxes:

  • Method: GET (read something), POST (create something, the default), PUT or PATCH (change something), or DELETE (delete something). The other system's API documentation says which one to use.
  • Address: The full https://… address from the other system's documentation. Values from the run go in {{ }}, like https://api.example.com/people/{{ data.values.person_id }}.
  • Headers: A JSON object. This is usually where the API key goes, and sometimes a content type or version, like {"Authorization": "Bearer {{ secrets.CRM_KEY }}"}. Leave it empty if the API doesn't need any.
  • Body: The JSON to send. It isn't sent with GET.

The address, headers, and body can all use values from the run. See Values and templates.

Example: Create a contact in a CRM when a form is submitted

A new-hire form has the fields first_name, last_name, and email. The CRM's documentation says to send POST https://api.crm.example/v1/contacts with a bearer token.

  • Method: POST
  • Address: https://api.crm.example/v1/contacts
  • Headers:
{ "Authorization": "Bearer {{ secrets.CRM_KEY }}" }
  • Body:
{
  "first_name": "{{ data.values.first_name }}",
  "last_name": "{{ data.values.last_name }}",
  "email": "{{ $lowercase(data.values.email) }}",
  "source": "skidle",
  "tags": ["new-hire"]
}

Everything outside {{ }}, like "source": "skidle" and the tags, is sent exactly as written. First, save the key in Account under Secrets as CRM_KEY.

Use the server response in later steps

The step saves the server response under the step's ID:

  • data.<step id>.status: The HTTP status. 200 or 201 means it worked, 400s mean the request was wrong, and 500s mean the other system had a problem.
  • data.<step id>.body: The server response, read as JSON if it's JSON, and as text otherwise. In the CRM example, the new contact's ID might be data.card_create.body.id.
  • data.<step id>.ok: true for a 2xx status, and false otherwise.

To do something different when the request fails, give the step a When way out with the condition data.card_create.ok = false, and an Otherwise way out for success.

What counts as a failure

The step is marked as failed, and the run still moves on, when:

  • The status isn't 2xx. The server response is still saved, so you can read the other system's error message in body.
  • The server doesn't respond within 10 seconds.
  • The address isn't allowed (see below).
  • A template can't be filled in, or a secret it uses doesn't exist.

It only tries once. It doesn't retry on its own, because repeating a "create" request would create something twice.

Limits and safety

  • One attempt, a 10-second limit, and at most 1 MB of the server response is read.
  • Only https:// and http:// addresses are allowed. Redirects aren't followed.
  • Addresses on private networks aren't allowed, like localhost, 10.x.x.x, 192.168.x.x, 172.16–31.x.x, 169.254.x.x, and similar. This protects Skidle's own systems.
  • Credentials go in a header, never in the address. Addresses like https://user:password@… aren't allowed.
  • Secrets used with {{ secrets.NAME }} are never saved in the run or shown anywhere.

If something goes wrong

To learn what each error means, see Workflow troubleshooting.