workflow
Version:
Workflow DevKit - Build durable, resilient, and observable workflows
147 lines (110 loc) • 4.78 kB
text/mdx
---
title: fetch
description: Make HTTP requests from workflows with automatic serialization and retry semantics.
type: reference
summary: Use the workflow-aware fetch to make HTTP requests with automatic serialization and retry semantics.
prerequisites:
- /docs/foundations/workflows-and-steps
related:
- /docs/errors/fetch-in-workflow
---
Makes HTTP requests from within a workflow. This is a special step function that wraps the standard `fetch` API, automatically handling serialization and providing retry semantics.
This is useful when you need to call external APIs or services from within your workflow.
<Callout>
`fetch` is a *special* type of step function provided and should be called directly inside workflow functions.
</Callout>
```typescript lineNumbers
import { fetch } from "workflow"
async function apiWorkflow() {
"use workflow"
// Fetch data from an API
const response = await fetch("https://api.example.com/data") // [!code highlight]
return await response.json()
}
```
## API Signature
### Parameters
Accepts the same arguments as web [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch)
<TSDoc
definition={`
import { fetch } from "workflow";
export default fetch;`}
showSections={['parameters']}
/>
### Returns
Returns the same response as web [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch)
<TSDoc
definition={`
import { fetch } from "workflow";
export default fetch;`}
showSections={['returns']}
/>
## Examples
### Basic Usage
Here's a simple example of how you can use `fetch` inside your workflow.
```typescript lineNumbers
import { fetch } from "workflow"
async function apiWorkflow() {
"use workflow"
// Fetch data from an API
const response = await fetch("https://api.example.com/data") // [!code highlight]
const data = await response.json()
// Make a POST request
const postResponse = await fetch("https://api.example.com/create", { // [!code highlight]
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ name: "test" })
})
return data
}
```
We call `fetch()` with a URL and optional request options, just like the standard fetch API. The workflow runtime automatically handles the response serialization.
This API is provided as a convenience to easily use `fetch` in workflow, but often, you might want to extend and implement your own fetch for more powerful error handing and retry logic.
### Customizing Fetch Behavior
Here's an example of a custom fetch wrapper that provides more sophisticated error handling with custom retry logic:
```typescript lineNumbers
import { FatalError, RetryableError } from "workflow"
export async function customFetch(
url: string,
init?: RequestInit
) {
"use step"
const response = await fetch(url, init)
// Handle client errors (4xx) - don't retry
if (response.status >= 400 && response.status < 500) {
if (response.status === 429) {
// Rate limited - retry with backoff from Retry-After header
const retryAfter = response.headers.get("Retry-After")
if (retryAfter) {
// The Retry-After header is either a number (seconds) or an RFC 7231 date string
const retryAfterValue = /^\d+$/.test(retryAfter)
? parseInt(retryAfter) * 1000 // Convert seconds to milliseconds
: new Date(retryAfter); // Parse RFC 7231 date format
// Use `RetryableError` to customize the retry
throw new RetryableError( // [!code highlight]
`Rate limited by ${url}`, // [!code highlight]
{ retryAfter: retryAfterValue } // [!code highlight]
) // [!code highlight]
}
}
// Other client errors are fatal (400, 401, 403, 404, etc.)
throw new FatalError( // [!code highlight]
`Client error ${response.status}: ${response.statusText}` // [!code highlight]
) // [!code highlight]
}
// Handle server errors (5xx) - will retry automatically
if (!response.ok) {
throw new Error(
`Server error ${response.status}: ${response.statusText}`
)
}
return response
}
```
This example demonstrates:
- Setting custom `maxRetries` to 5 retries (6 total attempts including the initial attempt).
- Throwing [`FatalError`](/docs/api-reference/workflow/fatal-error) for client errors (400-499) to prevent retries.
- Handling 429 rate limiting by reading the `Retry-After` header and using [`RetryableError`](/docs/api-reference/workflow/retryable-error).
- Allowing automatic retries for server errors (5xx).