HTTP Requests
Use context.http when a Studio script needs to call a third-party API. It is the documented HTTP entry point for server-side Studio scripts and provides request logs, timeout, retry, trace IDs, and consistent error behavior.
Common Parameters
| Parameter | Description |
|---|---|
url | Full request URL, such as https://example.com/api/orders |
method | HTTP method. Common values are GET, POST, PUT, PATCH, and DELETE. Defaults to GET |
query | Query parameters appended to the URL. Values are converted to strings. Arrays append the same key multiple times |
headers | Request headers. Use this for authorization, API keys, content type, tenant codes, or custom signing headers |
json | JSON request body. The runtime serializes it and sets content-type: application/json; charset=utf-8 when needed |
body | Raw request body. Use this for text, URLSearchParams, FormData, Blob, ArrayBuffer, or typed arrays |
expect | Response parsing mode. Use json for JSON responses and text for text responses |
timeoutMs | Request timeout in milliseconds. Defaults to 10000 |
retry | Retry policy. Use maxAttempts and retryableStatusCodes for unstable external APIs |
throwOnHttpError | Defaults to throwing on non-2xx responses. Set false to handle error responses yourself |
idempotency | Adds an idempotency key for safe retry of create/update requests when the third-party API supports it |
GET
Use GET for reading data. Put filter values in query; do not send a body.
export default async function main(payload: StudioScriptRuntimeContextPayload, context: StudioScriptContext) {
const response = await context.http.requestJson({
url: 'https://example.com/api/orders',
method: 'GET',
query: {
status: 'paid',
page: 1,
},
timeoutMs: 10000,
});
return {
data: response.data,
};
}
POST
Use POST for creating records, submitting events, or calling action-style APIs.
const response = await context.http.requestJson({
url: 'https://example.com/api/orders',
method: 'POST',
json: {
orderNo: 'SO-1001',
amount: 1200,
},
idempotency: 'order-create-SO-1001',
});
PUT
Use PUT when the external API expects a full replacement update.
const response = await context.http.requestJson({
url: 'https://example.com/api/orders/SO-1001',
method: 'PUT',
json: {
orderNo: 'SO-1001',
amount: 1200,
status: 'paid',
},
});
PATCH
Use PATCH when the external API expects a partial update.
const response = await context.http.requestJson({
url: 'https://example.com/api/orders/SO-1001',
method: 'PATCH',
json: {
status: 'paid',
},
});
DELETE
Use DELETE when the external API deletes or cancels a resource. Most DELETE APIs do not need a body.
const response = await context.http.requestJson({
url: 'https://example.com/api/orders/SO-1001',
method: 'DELETE',
throwOnHttpError: false,
});
if (!response.ok) {
context.logger.warn('delete failed', response.status, response.bodyText);
}
Body: None
Use no body for GET and most DELETE requests.
await context.http.requestJson({
url: 'https://example.com/api/orders',
method: 'GET',
query: {
status: 'paid',
},
});
Body: JSON
Use json for normal JSON APIs. Do not manually stringify the body.
await context.http.requestJson({
url: 'https://example.com/api/orders',
method: 'POST',
json: {
orderNo: 'SO-1001',
amount: 1200,
},
});
Body: Form URL Encoded
Use URLSearchParams for application/x-www-form-urlencoded, commonly used by token APIs.
const body = new URLSearchParams();
body.set('grant_type', 'client_credentials');
body.set('client_id', 'your-client-id');
body.set('client_secret', 'your-client-secret');
await context.http.requestJson({
url: 'https://example.com/oauth/token',
method: 'POST',
headers: {
'content-type': 'application/x-www-form-urlencoded',
},
body,
});
Body: Multipart Form Data
Use FormData for multipart/form-data, commonly used by upload APIs. Do not set content-type manually; the runtime needs to include the boundary.
const form = new FormData();
form.set('name', 'orders.csv');
form.set('file', new Blob(['orderNo,amount\nSO-1001,1200\n'], {
type: 'text/csv',
}), 'orders.csv');
await context.http.requestJson({
url: 'https://example.com/api/uploads',
method: 'POST',
body: form,
});
Body: Text
Use a string body for plain text, CSV, XML, or signed raw payloads.
const xml = '<order><orderNo>SO-1001</orderNo></order>';
await context.http.request({
url: 'https://example.com/api/orders',
method: 'POST',
headers: {
'content-type': 'application/xml; charset=utf-8',
},
body: xml,
expect: 'text',
});
Body: Binary
Use Blob, ArrayBuffer, or a typed array when the API expects binary content.
import { Buffer } from 'node:buffer';
const bytes = Buffer.from('file content', 'utf8');
await context.http.requestJson({
url: 'https://example.com/api/files',
method: 'POST',
headers: {
'content-type': 'application/octet-stream',
},
body: bytes,
});
Headers
Use headers for authorization and custom integration requirements.
await context.http.requestJson({
url: 'https://example.com/api/orders',
method: 'GET',
headers: {
authorization: 'Bearer your-token',
'x-api-key': 'your-api-key',
},
});
Handle HTTP Errors Yourself
By default, context.http throws on non-2xx responses. Set throwOnHttpError: false when the script should handle the response itself.
const response = await context.http.requestJson({
url: 'https://example.com/api/orders',
method: 'POST',
json: payload,
throwOnHttpError: false,
});
if (!response.ok) {
context.logger.warn('third-party request failed', {
status: response.status,
code: response.code,
requestId: response.requestId,
bodyText: response.bodyText,
});
return {
ok: false,
status: response.status,
};
}
Notes
Use context.http.requestJson for JSON APIs and context.http.request for text responses or custom parsing. Prefer context.http over direct fetch so requests use the Studio runtime's logging, retry, trace, and outbound policy behavior.