TaskSultan Docs tasksultan.com

Capabilities

HTTP APIs

Call HTTP endpoints through ctx.api, with vault-by-name auth and a clear rule for which failures retry and which stop.

ctx.api calls an HTTP endpoint from an automation. The engine is Node's global fetch and nothing else: no extra HTTP client, no cookie jar and no browser impersonation. When a task needs a real browser, ctx.page is still the surface (framework/api-types.ts).

#The verbs

ctx.api is an ApiFacade with six methods:

  • request(method, url, opts?) for any method.
  • get(url, opts?).
  • post(url, body?, opts?), put(url, body?, opts?) and patch(url, body?, opts?).
  • delete(url, opts?).

ApiRequestOptions carries an optional body, a query map, extra headers, a vault credential name in auth and a per-call timeoutMs. A body that is not a string is serialised as JSON and the content-type header is set to application/json unless you set one. query values are URL-encoded.

The call answers with an ApiResult: status, ok, headers and either json (parsed when the response content-type is JSON) or text. A 2xx or 3xx returns this result and never throws.

#How a status becomes an outcome

The mapping follows the platform's exception lanes, so the runner's retry policy already knows what to do:

  • 2xx and 3xx come back as a result.
  • 4xx throws a BusinessException with code API_HTTP_<status>, such as API_HTTP_404. It is not retried.
  • 5xx throws a SystemException with code API_HTTP_<status>, such as API_HTTP_503. It is retried.
  • A timeout throws API_TIMEOUT, retryable.
  • A DNS failure, a reset or any other network error throws API_NETWORK, retryable.

401 and 403 stay in the business lane on purpose. A wrong token is a business failure and retrying it would loop against a wall instead of ending the transaction. The default timeout is 15 seconds, overridable with TS_API_TIMEOUT_MS or a per-call timeoutMs.

#Auth comes from the vault by name

An automation never carries a token. It sets auth to a credential name and the engine resolves the record before the request leaves:

const res = await ctx.api.get(`${base}/api/customers`, { auth: 'crm-api' });
const payload = (res.json ?? { customers: [] }) as { customers?: { id?: string }[] };
ctx.log.info(`Fetched ${(payload.customers ?? []).length} customers`);

The record can carry a header (default Authorization), a valuePrefix such as Bearer and a value, or a headers map applied as it stands. A missing record refuses with API_CREDENTIAL_MISSING before any network call, so a bad name cannot reach the wire.

#What state it is in

The capability audit measured api as WORKING: loopback requests returning 200, 404 and 503, each arriving as the service's typed outcome, with no external endpoint touched. The capability has its own spec and acceptance in the clean-required gate.

#Things that catch people out

A 4xx or 5xx throws, so you do not get to inspect the failing response body through the return value. The status travels in the exception code (API_HTTP_401, API_HTTP_503).

json is set only when the response content-type is JSON. For anything else the body is in text.

Declare 'api'. The runner refuses an undeclared call with API_NOT_DECLARED and a declared call with no provider with API_UNAVAILABLE.

Redirects are followed, which is fetch's own default. This facade offers no option to turn that off.