REST API client
The primary REST API client for The Bridge.
The httpCall tool builds and executes an HTTP request from your wired input fields and returns the parsed JSON response. It intelligently routes your dynamic fields based on the HTTP method:
GETrequests convert fields into URL query parameters.POST/PUT/PATCHrequests automatically construct a JSON body.
Configuration Fields
Section titled “Configuration Fields”| Field | Default | Description |
|---|---|---|
baseUrl | "" | The base URL for the target API. |
path | "" | Appended to baseUrl to form the full URL. |
method | "GET" | The HTTP method (GET, POST, PUT, DELETE, etc.). |
headers | {} | Key-value pairs for HTTP headers. Nullish values are safely ignored. |
cache | "auto" | Caching behavior. See Response Caching below. |
Dynamic Fields (Payload & Query Parameters)
Section titled “Dynamic Fields (Payload & Query Parameters)”Any field wired to the httpCall tool that is not listed in the configuration table above is treated as dynamic request data. The tool automatically formats this data based on your chosen HTTP method:
GETrequests: Dynamic fields are appended to the URL as query string parameters.- Non-
GETrequests: Dynamic fields are assembled into a deeply nested JSON object and sent as the request body.
Example 1: A GET Request (Query Parameters)
Section titled “Example 1: A GET Request (Query Parameters)”When using GET, any unmatched fields (like q or format below) are automatically appended to the URL as query string parameters.
tool geo from std.httpCall { .baseUrl = "https://nominatim.openstreetmap.org" .method = "GET" .path = "/search" .headers.User-Agent = "MyApp/1.0" .cache = 60}
bridge Query.geocode { with geo as g with input as i with output as o
# These become ?q=...&format=json g.q <- i.city g.format = "json"
o.lat <- g[0].lat o.lon <- g[0].lon}Example 2: A POST Request (JSON Body)
Section titled “Example 2: A POST Request (JSON Body)”When using POST, unmatched fields are automatically assembled into a JSON payload. You can build deeply nested JSON bodies using standard dot notation.
tool createCustomer from std.httpCall { .baseUrl = "https://api.stripe.com/v1" .path = "/customers" .method = "POST" with context as c .headers.Authorization <- `Bearer ${c.STRIPE_KEY}`}
bridge Mutation.register { with createCustomer as api with input as i with output as o
# These are automatically stringified into the JSON body api.email <- i.email api.name <- i.fullName api.metadata.source = "bridge_gateway"
force api
o.customerId <- api.id}Response Caching
Section titled “Response Caching”You can add a .cache field to any httpCall tool to enable TTL-based response caching. The engine automatically creates a unique cache key based on the HTTP Method, Full URL, and Request Body.
Identical requests will instantly return the cached result without hitting the network.
Cache Modes
Section titled “Cache Modes”| Value | Behavior |
|---|---|
"auto" (default) | Respects the API’s native Cache-Control (e.g., max-age) or Expires headers. Bypasses cache if the API returns no-store or no-cache. |
0 | Disables caching entirely. |
<number> | Explicit TTL in seconds. Ignores the API’s headers and strictly caches the response for this duration. |
tool geo from httpCall { .baseUrl = "https://nominatim.openstreetmap.org" .path = "/search" .method = "GET"
# Strictly cache responses for 5 minutes, ignoring API headers .cache = 300}Custom Cache Store (Redis / Memcached)
Section titled “Custom Cache Store (Redis / Memcached)”By default, httpCall uses a fast, in-memory LRU cache (capped at 1024 entries). If you are deploying across a fleet of stateless workers or serverless edge functions, you should provide a distributed cache backend.
You can easily swap the storage engine by passing a custom CacheStore implementation to createHttpCall during engine initialization:
import { bridgeTransform, std, createHttpCall } from "@stackables/bridge";import type { CacheStore } from "@stackables/bridge";import { redis } from "./my-redis-client";
// 1. Wrap your Redis client in the CacheStore interfaceconst redisCache: CacheStore = { async get(key) { const v = await redis.get(key); return v ? JSON.parse(v) : undefined; }, async set(key, value, ttlSeconds) { await redis.set(key, JSON.stringify(value), "EX", ttlSeconds); },};
// 2. Inject it into the tools mapconst schema = bridgeTransform(graphqlSchema, bridgeAst, { tools: { std: { ...std, httpCall: createHttpCall(fetch, redisCache), }, },});