Call external services
Make public HTTPS API requests from a work using http.fetch().
Make a request
export default async ({ input, http, secrets }) => {
const response = await http.fetch("https://api.example.com/messages", {
method: "POST",
headers: {
Authorization: `Bearer ${await secrets.get("EMAIL_API_KEY")}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ message: input.message }),
});
if (!response.ok) {
throw new Error(`Message service returned ${response.status}`);
}
const result = await response.json();
return { id: result.id };
};The example URL is illustrative; use the documented endpoint of the merchant’s provider. All works can call public HTTPS hostnames without an allowlist or manifest permission. Use http.fetch, since direct fetch and other network transports remain blocked by the sandbox.
Fetch-style interface
http.fetch(url, options) accepts a URL string or URL object. Options are method, headers, body, redirect, and timeoutMs. Methods are GET, HEAD, POST, PUT, PATCH, DELETE, and OPTIONS. Headers accept a plain object, pairs, or Headers. Bodies accept strings or URLSearchParams; set Content-Type for JSON. GET and HEAD cannot include a body. Other options are rejected, including signal; use timeoutMs to set a shorter deadline.
The promise resolves to a buffered Response with status, ok, headers, url, redirected, .json(), .text(), and .arrayBuffer(). HTTP 4xx and 5xx responses do not throw. Network failures, timeouts, and policy limits do. No cookies are stored or set automatically. Set-Cookie and transport-only response headers are removed. Request streams, FormData, file uploads, and streaming responses are not supported.
Built-in limits
| Resource | Limit |
|---|---|
| Requests | 10 per run, including every redirect hop, shared across parallel calls |
| Request body | 64 KiB |
| Response body | 256 KiB after decompression |
| Headers | 16 KiB per request or response; at most 64 request headers |
| Deadline | 5 seconds per call including redirects and reading the response, within the 10-second run deadline |
| Redirects | Up to 3 same-origin redirects per call |
Each http.fetch also uses one of the 50 SDK calls per run. timeoutMs can shorten the deadline to 1–5000 ms. A timeout cannot undo an external operation that already happened. A failed request is never retried automatically. Use the service’s idempotency mechanism when available and inspect effects before retrying.
Destinations and redirects
Only HTTPS hostnames are accepted. Local/internal destinations, literal IP addresses, credentials embedded in URLs, and proxy/routing headers such as Host are rejected. The provider’s public-network transport blocks private addresses at connection time, including after DNS resolution. No Shopify tokens, inbound request headers, or platform credentials are attached to external requests.
Keep requests that contain a secret pointed at a fixed provider origin, or validate the destination against an allowlist owned by your build. A public caller must never choose the destination that receives a store credential. Validate caller identity and authorization before performing external actions.
The default redirect: "follow" follows same-origin redirects only. Cross-origin redirects fail rather than forwarding a credential or body to another service; use that service’s documented final URL directly. redirect: "manual" returns a redirect response; redirect: "error" rejects redirects. Every followed target must pass the destination checks.
Inspect a request
Run details and get_run include a separate external-request list with destination hostname, method, response status, duration, and error code. These records are kept for seven days. Request and response bodies, headers, and URL paths and query values are not recorded automatically. Never log credentials or full third-party response payloads.