Skip to content

HTTP Client

Business rules can call external APIs using the fetch() function. This enables webhooks, data enrichment, third-party integrations, and more. The HTTP client is opt-in per application and governed by system-wide security limits.

const response = fetch('https://api.example.com/data', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({
customer_id: record.customer_id,
event: 'order_created'
})
});
if (response.ok) {
const data = response.json();
update('orders', record.id, {
external_id: data.id
});
}
OptionDescription
methodHTTP method (defaults to GET)
headersObject of request headers
bodyRequest body (string or JSON-serializable value)
timeoutPer-request timeout in milliseconds (clamped to the system maximum)
credentialName of a stored credential to inject (keeps secrets out of script code)
PropertyTypeDescription
statusnumberHTTP status code
statusTextstringHTTP status text
okbooleanTrue if the status is 200–299
headersobjectResponse headers (also headers.get(name))
json()functionParse the response as JSON
text()functionGet the response as text
// GET
fetch('https://api.example.com/users');
// POST with JSON body
fetch('https://api.example.com/webhooks', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ event: 'created' })
});
// PUT, PATCH, DELETE
fetch('https://api.example.com/resource/123', { method: 'DELETE' });

Inject a named secret without exposing it to the script:

fetch('https://api.stripe.com/v1/charges', {
method: 'POST',
credential: 'stripe_key'
});

By default the HTTP client blocks requests that resolve to private or internal addresses, including:

  • Private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
  • Loopback addresses (127.0.0.1, ::1)
  • Link-local and cloud metadata addresses (169.254.0.0/16, including 169.254.169.254)
  • Carrier-grade NAT and other reserved ranges

An operator can lift this restriction system-wide with allow_private_ips, but it is off by default.

Each application controls which domains its rules may reach. Operators can require an allowlist (block everything not explicitly allowed) and maintain per-application and system-wide blocklists.

# System configuration — applies to every application
http_client:
enabled: true
allow_private_ips: false
max_timeout: 60s
max_response_size: 5242880 # 5 MB
follow_redirects: true
max_redirects: 10
system_blocked_domains:
- "*.internal.corp"
# Per-application configuration
enabled: true
require_allowlist: true
allowed_domains:
- "api.stripe.com"
- "hooks.slack.com"
blocked_domains:
- "example.test"
SettingDefault
Default request timeout30 seconds (per-app, clamped to the system max)
Maximum request timeout60 seconds (system)
Maximum response size5 MB (system; per-app may be lower)
Redirect followingEnabled, up to 10 redirects (configurable)

When request logging is enabled, outbound HTTP requests are recorded for audit purposes, including the URL, method, status code, and response time.