http
The http step type performs an HTTP request from a workflow or custom command — call an API, notify a service, trigger a CI job, hit a deployment webhook, or poll a health endpoint. It supports any HTTP verb, query-string parameters, headers, and a request body (raw or form/JSON), with per-attempt timeouts and HTTP-aware retries that compose with the step's retry policy. No shelling out to curl.
webhook is an accepted alias for http — type: webhook behaves identically and reads naturally for the fire-a-notification use case.
steps:
- name: notify
type: http
url: "https://ci.example.com/hook/{{ .env.JOB_ID }}"
method: POST
query:
ref: "{{ .env.GIT_SHA }}"
headers:
Authorization: "Bearer {{ .env.TOKEN }}"
Content-Type: application/json
body: '{"status":"deployed"}'
expect:
status: [200, 201, 202, 204]
response:
- /"status"\s*:\s*"deployed"/
timeout: 30s
retry:
max_attempts: 5
backoff_strategy: exponential
initial_delay: 1s
max_delay: 30s
Send form parameters instead of a raw body with form (mutually exclusive with body). By default form is sent as application/x-www-form-urlencoded; set a JSON Content-Type header to send it as a JSON object instead:
steps:
- name: notify-slack
type: http
url: "{{ .env.SLACK_WEBHOOK_URL }}"
method: POST
headers:
Content-Type: application/json
form:
text: "Deployment of {{ .steps.plan.value }} complete"
Fields
url- Required. Request URL. Supports Go templates.
method- HTTP method/verb:
GET(default),POST,PUT,PATCH,DELETE,HEAD,OPTIONS. query- Query-string parameters as key-value pairs (supports templates).
headers- Request headers as key-value pairs (supports templates).
body- Raw request body (supports templates). Mutually exclusive with
form. form- Form/JSON body parameters as key-value pairs. Sent as
application/x-www-form-urlencodedunless theContent-Typeheader isapplication/json. Mutually exclusive withbody. expect.status- List of acceptable HTTP status codes. When set, the response status must be in this list. Defaults to any
2xx. expect.response- List of regular expressions; the response body must match at least one. Patterns may be written as
/.../literals (surrounding slashes are stripped) or bare regex strings. timeout- Per-attempt timeout (e.g.,
30s,1m). Defaults to30s. Each retry attempt gets its own deadline. Thehttpstep givestimeoutthis meaning of its own, so it is a limit on each request and not on the step as a whole. retry- Retry policy (see retry). Transport errors,
5xx, and429responses are retried by default; other4xxresponses fail fast. ForGET,HEAD, andOPTIONS, whenexpectis set, a retry policy also retries any response that fails the expectation (a status outsideexpect.status, or a body that matches none ofexpect.response) untilmax_attemptsruns out, which is what makes polling work.POST,PUT,PATCH, andDELETEare not automatically repeated solely because a status or body expectation fails: the request may already have completed a write. Useretry.conditions(regexes matched against"<status> <body>") to retry additional cases. These explicit conditions and the transport,5xx, and429retry rules apply to all methods; configure retries for write requests only when the endpoint safely handles repeated calls. The failure error names the last status received and the number of attempts.
Polling
Because http retries are HTTP-aware, the step doubles as a poller — GET an endpoint and retry until both the status and the body match the expectation:
steps:
- name: health
type: http
url: "{{ .env.HEALTH_URL }}"
expect:
status: [200]
response:
- /"status"\s*:\s*"(ok|healthy)"/
retry:
max_attempts: 10
backoff_strategy: constant
initial_delay: 2s
For HTTP validation after deployment, see the
advanced CloudFormation example. Its
after.aws/cloudformation.apply hook checks the deployed Lambda's status code
and response body, and fails the command if either is unexpected.
Result
The response body becomes the step's value, and useful details land in metadata (see outputs):
{{ .steps.<name>.value }}- The response body.
{{ .steps.<name>.metadata.status_code }}- The numeric HTTP status code (e.g.,
200). {{ .steps.<name>.metadata.status }}- The HTTP status text (e.g.,
200 OK). {{ .steps.<name>.metadata.response_headers }}- Response headers as a map.