Skip to main content

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​

ParameterDescription
urlFull request URL, such as https://example.com/api/orders
methodHTTP method. Common values are GET, POST, PUT, PATCH, and DELETE. Defaults to GET
queryQuery parameters appended to the URL. Values are converted to strings. Arrays append the same key multiple times
headersRequest headers. Use this for authorization, API keys, content type, tenant codes, or custom signing headers
jsonJSON request body. The runtime serializes it and sets content-type: application/json; charset=utf-8 when needed
bodyRaw request body. Use this for text, URLSearchParams, FormData, Blob, ArrayBuffer, or typed arrays
expectResponse parsing mode. Use json for JSON responses and text for text responses
timeoutMsRequest timeout in milliseconds. Defaults to 10000
retryRetry policy. Use maxAttempts and retryableStatusCodes for unstable external APIs
throwOnHttpErrorDefaults to throwing on non-2xx responses. Set false to handle error responses yourself
idempotencyAdds 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.