DocsAPIAPI Studio

API Studio

Pro+ only

API Studio lives on the same page as exposed endpoints. It stores reusable outbound requests, encrypted connection references, saved example responses (fixtures) used to simulate runs, assertions, and durable run history. Exposed endpoints remain available from the page's endpoint view.

My API library

Save a local request or stack to My API library to reuse it across your own agents. A release is immutable and contains only portable request, workflow, connection-requirement, and selected fixture data. Credentials, run history, private outputs, and agent-specific assets are excluded.

Install a chosen release into an agent's API page, bind its connection slots, review the destination, effect, and budget, then activate it. Each agent keeps separate bindings, activation, budgets, history, and outputs. Draft edits do not update installed releases. Upgrades preserve the installation and stack identity but clear activation and require fresh bindings and review. Revocation blocks later dispatches; detaching makes the current version an editable local copy.

Connections and secrets

A connection pins a public HTTPS origin plus an optional credential reference. Secret values are stored only in the central encrypted credential store (AES-256-GCM); the connection record keeps a reference and non-secret auth metadata. Importers extract credential-bearing cURL headers into a connection instead of keeping them in the request definition.

OAuth 2 refresh-token connections

Instead of a static secret, a connection can use an OAuth 2 refresh token. Choose OAuth 2 refresh token, then enter the provider's token URL, the Authorization header name (default Authorization), the client authentication method, the client-id parameter name (body mode only), an optional scope, and the client id, client secret, and refresh token from the provider. You obtain the refresh token from the provider first; the studio does not run an interactive authorization flow.

On every live run the server exchanges the refresh token for an access token before the provider call and injects the result only into the Authorization header. The access token is never a query parameter and never reaches the browser, model, run history, or events. The token endpoint must be a credential-free public HTTPS URL; loopback, private, link-local, and metadata hosts are blocked. The exchange never follows redirects, is time- and size-bounded, and shares the live run's budget.

If the provider rotates the refresh token, the new value is stored with a compare-and-swap so a slower concurrent run can never overwrite a newer rotation; access tokens are never persisted. A refresh failure ends the run before the provider is called, and the client id, client secret, and refresh token are redacted from run errors and history. Static and OAuth settings are mutually exclusive: switching modes clears the other mode's fields, an incomplete secret rotation is rejected, and switching back to Static requires a new static secret.

Simulate, then live

New runs default to Simulate, which resolves path placeholders and uses the saved body template (or the reviewed input body when the template is empty), then validates assertions against a saved example response with zero external requests. A missing saved example response fails the simulation rather than falling back to a live call.

Live execution is an explicit action. Every call requires a fresh acknowledgement bound to the reviewed request, connection revisions, and input. A live result is labeled with its revision and mode, and provider pricing is never presented as free.

Each acknowledged live intent carries one client-generated request id. The UI reuses that id when the exact reviewed intent is submitted again after any error, because an action can fail after the backend already admitted and dispatched the run. A confirmed run, changed input or revision, or explicit uncheck and re-acknowledgement gets a new id. Reusing an id after a true pre-admission rejection is harmless. The UI blocks double clicks synchronously and never retries on its own.

Bounded outbound execution

Live calls run through one bounded executor shared with custom HTTP tools. It requires HTTPS, blocks loopback, private, link-local, and metadata targets, pins the allowed origin, never forwards credentials across origins on redirect, and enforces response byte and time bounds. Every redirect is re-validated and DNS-pinned. Explicit polling for async providers is part of the durable stack stage below.

Durable request stacks

A stack is an ordered list of steps that each reference an existing saved request. Stacks run durably: the backend drives each step, records a child run per step attempt, and survives a restart. A step may map bounded values from the reviewed stack input and from an earlier step's redacted response into a later step's path placeholder, query, header, or body input.

Mapping can never replace the destination. The connection origin is always the only outbound host, absolute URLs are rejected in path placeholders, and transport or credential targets such as Host, Authorization, and Cookie are refused. A step source selects the response body (the backward-compatible default), its HTTP status, or one safe, redacted response headers entry by case-insensitive name. An identity, trim, lowercase, uppercase, number, boolean, or json transform runs before the value size check; an invalid or non-finite conversion fails the run. Mapped values are size-bounded, and a value that looks like a credential literal fails the run instead of being sent. Sensitive header names such as authorization, cookie, set-cookie, and proxy-authorization are never retained or mappable, and retained headers are capped in count and size.

When a step's request is saved with bodyType: "json" and its template parses as a JSON object or array, the step can map typed values into individual fields of that body. JSON-looking text saved as a Text body is rejected. Target paths are strict dotted paths such as media_url, video.url, or items.0.url. Empty, duplicate, overlapping, and out-of-range paths are rejected, as are the prototype keys __proto__, prototype, and constructor. Values keep their native JSON type and are never stringified. The template is deep-cloned, patched, serialized, and checked against the 64 KiB body limit before the request is sent. Whole-body mapping is available only when the request has no saved body template, and the two body mapping modes are mutually exclusive.

Starting a stack requires one acknowledgement bound to the immutable reviewed stack revision, every referenced request revision and connection revision, and the server-computed worst-case total estimated cost. Editing a referenced request or connection makes the acknowledgement stale before the next provider call. Unknown cost stays explicit and is never presented as free. Cost and currency are advisory owner metadata: Higantic never derives, verifies, or converts provider pricing, preserves at least four decimal places, and rejects a stack whose known estimates use different currencies at save, activation, and run admission. Each step attempt dispatches through the same live-run admission, egress validation, credential handling, and private output storage as a single run, so no step bypasses the safety path. Per-attempt idempotency keys make a resumed or replayed run reuse the exact provider call instead of repeating it, and only a step whose run was never claimed may retry automatically.

A polling step re-runs its request until a configured JSON path matches (for example a fal queue status of COMPLETED) or until the bounded interval, attempt, and timeout limits are exhausted. It may also declare a terminal failure path and value; failure is checked before success, fails the run immediately without another provider call, and keeps the redacted status, body, and safe headers. Backoff is fixed, exponential, or retry_after; the retry-after strategy reads an integer-seconds or HTTP-date Retry-After header and otherwise falls back to exponential. Every delay is clamped to 60 seconds and the remaining run deadline, and the chosen delay and time are persisted so recovery keeps the same cadence. Stack runs can be cancelled, and cancellation takes effect as soon as no provider call is in flight. Limits bound steps (20), poll interval (1–60 s), polls (60), safe attempts (3), run lifetime (30 minutes), mapped value and body size, safe retained response headers (40 per step run, 8 KiB serialized, 1 KiB per value), JSON body field mappings (20 per step, paths at most 200 characters, 8 segments deep, array indices at most 1000), and worst-case total estimated spend (a polling step multiplies its estimate by its poll attempt bound). Owner-wide admission allows at most 3 active stack runs and bounds stack-run starts per rolling window, separately from the child live-call ceiling. Lifecycle events are monitoring only and do not trigger public automations.

Building and running stacks

The Stacks surface lets you create, rename, edit, and delete a stack; add, reorder, and remove steps; and pick an existing saved request for each step. A step runs once or polls its request until a success JSON path matches the success value, bounded by the interval, attempt, and timeout limits. A poll step can also declare an optional terminal failure path and value, a backoff strategy, and a maximum interval. The mapping editor resolves path placeholders, query, and header targets from the reviewed stack input or an earlier step's redacted response, and lets a step source pick a body, status, or headers scope plus an optional transform. The body editor offers whole-body mapping when the selected request has no saved body template, and typed JSON field mapping when the request is saved as JSON and its template parses as a JSON object or array; a text body, including JSON-looking text, or an invalid JSON template explains the limitation instead. Validation errors are shown before the stack can be saved.

Before a run, Review and run shows the immutable stack revision, the ordered steps, the server-recomputed worst-case estimated cost, unknown-cost disclosure, and the bounded limits. Starting requires one explicit acknowledgement bound to that revision and total. The UI generates one client request id per acknowledged intent and reuses it after a submission error, gets a fresh id for a confirmed or changed intent, blocks double clicks synchronously, and never retries on its own. Stack run history lists each run with its recorded step attempts and lets you cancel a run; cancellation takes effect as soon as no provider call is in flight.

A one-click fal H3 Max Turbo starter creates one connection and three saved requests over the current minimax/h3-max-turbo/text-to-video model — submit a 5-second, 9:16, 480P job, poll status until COMPLETED, then fetch the result and extract video.url as a private file — and one stack over them. fal preserves the full endpoint id for submit and drops the endpoint subpath for poll and result, addressing the queue app base. The submit request uses /minimax/h3-max-turbo/text-to-video, while polling and results use /minimax/h3-max-turbo/requests/{request_id}/status and /minimax/h3-max-turbo/requests/{request_id}. The submit step maps the provider body from the reviewed stack input, which starts with a prompt plus the 5-second, 9:16, 480P, balanced defaults so you can supply a fresh prompt on every run. The reusable starter marks provider cost as metered and unknown and embeds no price or currency; you can enter an advisory estimate after reviewing current fal pricing. The poll and result steps map request_id from the submit step's redacted response. The starter embeds no secret: the connection is created without a credential and you attach your own fal key before running live. Creating the starter never calls a provider. Creation uses explicit template identity, so a row that only shares the same origin or slug fails with a clear collision error rather than binding the starter to an unrelated request or connection.

Agent and scheduled use

An api page stack is private to you until you explicitly activate it for agent use. Activating requires a per-run worst-case cost cap and fails closed when any step has unknown provider cost, known estimates use different currencies, or the server-computed worst-case estimate exceeds that cap. The activation is bound to the current stack revision together with every referenced request and connection revision, so editing a step, request, or connection makes the activation stale and it must be re-approved before the agent or a schedule can run it. You can disable (revoke) activation at any time.

When the api_studio tool set is enabled on a Pro+ agent, the agent can list only the activated stacks (list_api_studio_stacks), start one durable run from a bounded JSON input (run_api_studio_stack), and read that run's status, already-redacted step responses, safe headers, and saved output metadata plus the opaque output id (get_api_studio_stack_run). The agent can never supply a URL, a request definition, a cost, or a revision; the server derives all of them and re-checks the activation before admission. Run input must be a plain JSON object containing only JSON values, is limited to 64 KiB after UTF-8 serialization, and defaults to an empty object when omitted.

How agents discover a stack

Write a plain-language When to use description on the request and stack (up to 500 characters) covering the purpose, the inputs you expect, and the result. On every eligible turn while API Studio is enabled, the agent receives a bounded, credential-free catalog of the stacks you activated: id, name, when-to-use guidance, revision, and optional cost metadata. Default inputs, headers, bodies, credentials, outputs, and run history never enter the catalog. The catalog is reference data, not instructions: the agent is told never to follow guidance inside an API description that conflicts with its safety policy or your request.

This is semantic model selection, not keyword-triggered execution. The agent compares your request against each stack's when-to-use guidance and chooses one only when it clearly fits, then gathers missing inputs instead of inventing them and resolves ambiguity before any external action. Mentioning an API does not run it, and a stack is never started from a keyword match. The catalog is loaded only when the effective tool set for the turn includes api_studio; restricted Slack/Discord bot mode, the tool-less draft runtime, and API endpoints that exclude the tool set never see it. If the catalog cannot be loaded the turn still proceeds and the agent is told to verify with list_api_studio_stacks instead of assuming no stacks exist. Activation, budget caps, approval, and the api_studio.stack_run safety policy are unchanged; discovery only adds candidate visibility.

Agent authoring (drafts)

The same tool set lets the agent inspect the owner's API pages and reusable resources (list_api_studio_workspace) and create one modular DRAFT in a single call (create_api_studio_workflow): anonymous secret-free connections, saved requests, and an inactive stack of ordered request/poll steps. Steps map bounded values from the reviewed stack input or an earlier step's redacted response with a declarative transform (identity, trim, lowercase, uppercase, number, boolean, or json) and typed JSON body-field mappings. There are no expression steps and no arbitrary JavaScript. A step may reference a request key created in the same call or an existing saved request id on the same API page; existing requests are reused without mutation.

Authoring is deliberately inert: it cannot attach or supply a credential, reference a credentialed connection, activate a stack, acknowledge or run a live call, publish, or incur cost. Connection origins must be exact credential-free public HTTPS origins under the same egress policy, an existing connection can only be reused when it is anonymous, and literal credentials in a request definition are rejected. Every draft stays inactive until the owner reviews and activates it; all existing activation, cost, safety, and acknowledgement controls still apply before any provider call. The agent can remove a draft it created with delete_api_studio_draft; only agent-authored drafts are deletable, and owner-authored rows are never touched. Draft writes and deletion are available only in a direct owner chat; API, bot, automation, schedule, and timer contexts are blocked. Replaying the same draft uses a deterministic retry key and does not create duplicates.

Agent-initiated stack runs follow the api_studio.stack_run safety action: direct chat allows by default, REST API contexts dry-run, unattended automations, schedules, and timers require owner approval, and external bot mode blocks. A require-approval decision raised by a model tool call in an unattended context is blocked instead of creating an orphaned request, because a tool call cannot resume. To schedule an activated stack with a resumable approval, use the direct run_api_stack routine or reminder action with { stackId, input }; the occurrence key supplies idempotency and the routine or reminder settles with the durable stack run id once the stack is started.

Uploading a prior step output

A saved request can send a private file from an earlier successful stack step as multipart form data, a direct binary body, or a resumable chunked upload. Choose the mode on the request, then select the earlier step under File source on the upload step. Multipart mode supports bounded metadata fields. A reviewed file name or MIME overrides the stored metadata; otherwise the stored values are used.

Only the stack runner can bind an opaque output reference to the admitted child run, so a standalone live request cannot select an arbitrary output. The runtime requires a completed, successful same-agent source and verifies its exact size and SHA-256 before any provider call. Storage ids and URLs remain server-only. For resumable mode, the session URL must use public HTTPS on the exact reviewed upload origin, remains in memory, and never receives the connection credential. The request's saved assertions run against the init response before any chunk is sent. Bounded, redacted init headers, preview, and JSON (including any provider id) are saved so later steps can map them, while the run status and response phase identify the final init, chunk, or completion outcome. The session URL is never saved. Redirects fail, every chunk shares the live deadline, 308 progress must confirm the complete chunk, and a final success is accepted only after the last bytes.

Private file outputs

A request can save one private file per live run. Choose None (the default JSON/text behavior and 256 KiB text cap), Binary to save a direct binary or attachment response, or JSON URL to inspect one configured path in the JSON response and download the exact approved HTTPS URL. Output settings are part of the request revision and appear in the live acknowledgement, including the extra download.

A JSON URL download only happens after a successful, untruncated, valid-JSON primary response that passed its assertions; a non-2xx primary, a truncated response, invalid JSON, or a failed assertion never triggers the extra request. A requested output that cannot be saved marks the run as failed instead of ok.

Binary responses are never UTF-8 decoded into run logs. Files are capped at 20 MB of actually streamed bytes; a declared Content-Length over the cap or a stream that exceeds it is rejected without storing a partial file. The primary request, the approved download, and the storage upload share one bounded time budget. Every download hop is re-validated, DNS-pinned, HTTPS-only, and uncredentialed; uploads reject redirects. Signed URL query parameters are runtime-only.

Stored files live in managed storage with a stable output reference and safe name, MIME, size, and hash metadata. A claimed run reserves the expected size and hash and prewrites a durable staging ticket with an opaque server-issued marker before a server-authenticated Convex action validates and stores the bytes. The upload rejects expired or already-bound attempts before reading the body and revalidates the reservation immediately before the write. The action stores each in-flight blob under an internal staging content type that carries the marker, so a process crash between storing the blob and recording its binding is still recoverable: a scheduled scan makes one bounded page of the system storage metadata per run and deletes an orphan only when the marker maps to a preissued ticket whose reserved size and hash match exactly, no live indexed row references the blob, and the grace window has elapsed. Untagged blobs, forged markers, other-feature files, and blobs with only a matching hash are never touched, and a late duplicate under a finalized marker is cleaned without downgrading the canonical file. Tickets survive run, page, and agent deletion and keep their minimal marker provenance indefinitely, because a delayed write can arrive long after the reservation. A discarded reservation keeps its pending quota on the durable ticket until the blob is deleted or a complete scan after a safe deadline proves it never existed. Finalizing accepts only the blob bound by that action, and cleanup uses the bound attempt rather than a supplied storage ID. Raw storage URLs are never exposed to the browser or history. Storage SHA-256 metadata is accepted only as an exact hexadecimal digest or canonical padded base64 for the same 32 bytes; malformed metadata fails closed. Cleanup treats a metadata-confirmed absent blob as complete, while a metadata read error remains queued for retry. Preview and download proxy bytes through the authenticated owner route. The proxy checks owner authorization through an authenticated Convex call before reading storage: a forbidden or foreign output returns 404, and a throttled request returns 429 with the backend's Retry-After value, which the browser renders as a concise retry message. Preview is loaded on demand with an explicit close and can be retried; missing or unsupported files stay download-only. Native video plays through a short-lived signed URL: the page renews the grant before it lapses when playback is requested, and retries a failed media load once while preserving the playback position. If the browser blocks automatic playback, native controls remain available. Preview renders only allowlisted image, audio, and video types whose declared MIME matches detected magic bytes; HTML and SVG are never rendered inline. Everything else downloads with a sanitized attachment filename. Simulation never stores a file.

A stored output can be promoted into the owning agent's Asset Library with Add to assets. Promotion shares the exact stored object by reference, so bytes are never copied, downloaded, or re-uploaded, and raw storage ids and URLs are never exposed to the browser. The new asset is private by default, and it is typed image only for a supported image MIME; every other type, including video, becomes a file asset. Promotion checks the owner, plan, agent, output, and any chosen folder, and it is idempotent per output and agent: adding the same output again returns the existing asset without creating a duplicate. Because the asset and the output share one blob, deleting either side keeps the bytes while the other live reference or a pinned share remains, and the durable cleanup outbox deletes the blob and releases storage accounting only after the final live reference is gone.

The runtime also bounds concurrent upstream storage fetches per process. Excess requests are rejected with 429 before storage is read, and the slot is released on success, error, timeout, and client cancellation. This cap is not an absolute process-memory ceiling: a completed response buffer can outlive its upstream fetch while bytes are delivered to the client. Files come from third-party providers and may contain sensitive or untrusted content. Higantic does not scan or guarantee file safety, and the interface says so near the file output settings.

Operational safeguards

These owner-wide limits bound concurrency, request bursts, storage growth, and proxy fan-out for one signed-in owner across every agent and page. They are operational safeguards, not customer-facing plan entitlements and not a provider dollar-budget guarantee. Live admission allows at most 3 live runs in flight, 10 new admissions per rolling minute, and 100 per rolling 24 hours; a stale run that never reports a terminal outcome is failed by the sweep, and a failed claim is never retried automatically. Admission records outlive visible history and page or agent removal: an active lease preserves the owner concurrency slot for up to 10 minutes, the request-id replay tombstone lasts 30 days, and history trimming removes only terminal runs. One owner may hold at most 1 GB (1,000,000,000 bytes) of API Studio storage including pending upload reservations. Before enforcing that cap for an existing owner, bounded lazy reconciliation accounts for legacy outputs, pending uploads, and deletion jobs; new storage admission fails closed if the legacy set exceeds the reconciliation bounds. Download and preview authorization is owner-wide and limited to 60 requests per minute, and the runtime separately caps concurrent upstream storage fetches per process at 8. A scheduled, bounded cleanup sweep fails stale live runs, transfers discarded upload reservations to their durable ticket, retries due deletion jobs through a durable cleanup outbox with capped exponential backoff, and makes one bounded page of the system storage metadata for positively-proven staging orphans. A deletion job retains its bytes and accounting while any live indexed row references the blob, and releases accounting only after an unreferenced blob is deleted successfully or its absence is verified after a safe deadline. The sweep never re-sends a provider call.

Imports

Paste a cURL command or a limited OpenAPI 3 JSON document. cURL imports support method, headers, body, and basic auth, and strip credential values into a connection. OpenAPI imports create operation skeletons from a declared subset (name, method, and server plus operation path). Configure the parsed parameters and JSON body properties in the request editor; unsupported features are reported instead of being silently ignored.

Assistant drafting

The assistant panel drafts request definitions using the agent's configured model through the existing metered job infrastructure. Draft jobs have an empty tool set and receive no workspace pages, memories, documents, integrations, credentials, or MCP tools. The owner reviews the returned JSON before applying it. Drafting never grants live-call permission and never executes a request.