manifest.json
manifest.json is the integration registry for your Swytchcode project.
It stores metadata about every installed integration, including its version, API endpoints, authentication configuration, and execution behavior.
Unlike tooling.json, which defines what can execute, manifest.json defines how an integration executes.
The file is located at:
.swytchcode/integrations/manifest.jsonEvery integration installed using swy get or swy add automatically updates this file.
Both the CLI and the MCP server share this file during execution. Updates are serialized to prevent corruption when multiple tools modify it simultaneously.
What does manifest.json do?
For every installed integration, Swytchcode stores:
- Integration version
- Sandbox endpoint
- Production endpoint
- Authentication metadata
- Method count
- Workflow count
- Execution policy
During execution, the kernel reads this file to determine:
- Which endpoint should receive the request
- How authentication should work
- Whether retries are allowed
- Timeout behavior
- Idempotency settings
- Concurrency limits
File Structure
A simplified example looks like this:
{ "stripe.stripe": { "version": "v2", "sandbox_endpoint": "https://api.stripe.com", "production_endpoint": "https://api.stripe.com", "methods": 42, "workflows": 3, "auth": { "type": "api_key", "header": "Authorization" } }}Each top-level key represents a single integration.
Entry Fields
Each integration contains the following fields.
version
Defines the pinned version of the integration, e.g. "v2". This is the same version string that appears next to the integration in tooling.json.integrations (for example "stripe.stripe": { "version": "v2" }) - the two files must agree, since swy bootstrap and swy sync compare them to decide what to fetch.
{ "version": "v2"}Swytchcode always executes using the pinned version stored in the manifest, never “whatever is newest.” If you want a newer integration version, run swy get <project> again to fetch the new bundle and update this file - editing the field by hand won’t fetch anything.
sandbox_endpoint
Defines the base URL used when the project is running in sandbox mode (tooling.json.mode: "sandbox").
{ "sandbox_endpoint": "https://sandbox.example.com"}Many providers (Stripe is a common example) use the same host for sandbox and production and distinguish environments by which API key you authenticate with instead of by URL - in that case sandbox_endpoint and production_endpoint are identical, as shown in the Complete Example below.
production_endpoint
Defines the base URL used for production execution (tooling.json.mode: "production").
{ "production_endpoint": "https://api.example.com"}Because the environment is resolved from tooling.json.mode rather than from a flag on exec, switching a project from sandbox to production means changing mode in tooling.json (or re-running swy init --mode=production) once, rather than remembering to pass an environment flag on every call.
methods
Number of executable methods included in the integration bundle, e.g. 42.
{ "methods": 42}This value is informational - it reflects what’s available in the fetched bundle under .swytchcode/integrations/, not what’s enabled in your project. Use swy list tooling to see what’s actually been added via swy add, and swy info <canonical_id> to inspect one method in detail. It’s maintained automatically by swy get, swy bootstrap, and swy sync; don’t hand-edit it.
workflows
Number of workflows provided by the integration, e.g. 5.
{ "workflows": 5}Same caveat as methods: this counts what’s in the bundle, not what’s registered in tooling.json.tools. Run swy add workflow <canonical_id> to actually enable one.
auth
Authentication metadata used by Swytchcode to know how to authenticate against this provider - it’s the schema, not the secret. The actual key or token is never stored here; it’s resolved separately at execution time (see Managed Authentication).
Example:
{ "auth": { "type": "api_key", "header": "Authorization" }}Depending on the integration, authentication metadata may include:
- Authentication type (
api_keyoroauth) - OAuth scopes
- Authorization header name
- Token format
swy auth connect [provider] reads this block to decide whether to prompt for an API key or start an OAuth flow, and swy auth connect with no argument reads it across every installed integration to list which providers still need credentials. swy doctor also checks this block as part of validating that installed integrations are fully configured.
execution_policy
Defines how HTTP requests to this integration behave: retries, timeouts, concurrency, response-size limits, and idempotency. Every field is optional and unset fields fall back to the built-in defaults - see the full Execution Policy breakdown below for every field, its default, and when to change it.
Environment Selection
Swytchcode automatically chooses the correct endpoint using the project mode defined in tooling.json.
tooling.json
mode = sandbox │ ▼sandbox_endpointtooling.json
mode = production │ ▼production_endpointThe final request URL is built as:
Base URL +Method Endpoint =Final Request URLFor example:
https://api.stripe.com +/v1/customers =https://api.stripe.com/v1/customersWhenever a request executes, Swytchcode prints the active environment.
Example:
Running live - stripe (production)This prevents accidental production requests.
If you’re not sure an endpoint is reachable before you run a real workflow against it, swy doctor --network checks every configured endpoint (sandbox and production, across all installed integrations) and reports its current status.
URL Security Rules
Swytchcode enforces URL safety automatically.
HTTPS
HTTPS is supported for every host.
https://api.stripe.comHTTP
HTTP is only allowed for local development.
Supported hosts:
- localhost
- 127.0.0.1
- ::1
Requests to external HTTP endpoints are rejected.
Self-signed certificates
For local development, TLS verification can be disabled.
SWYTCHCODE_INSECURE=1This is only allowed outside CI environments.
When running in GitHub Actions, GitLab CI, or other supported CI environments, insecure TLS is always rejected.
Execution Policy
The execution_policy object controls how HTTP requests are executed for a single integration: retry attempts, retry delays, timeouts, concurrency, response-size limits, and idempotency. It lives inside that integration’s entry in manifest.json, so different integrations can have different policies - a flaky third-party API might get a higher max_retries while an internal service you fully trust gets none.
Every field is optional. You only need to set the fields you want to override; Swytchcode merges the rest with its built-in defaults (documented field-by-field below).
Example - retry more aggressively and allow more time per request for a slow provider:
{ "execution_policy": { "max_retries": 5, "http_timeout_ms": 60000 }}Retry Configuration
max_retries
Maximum retry attempts after the first request.
Default:
3Negative values are treated as 0.
retry_on
HTTP status codes that trigger retries.
Default:
[ 429, 503, 504]non_retryable
Status codes that are never retried.
Default:
[ 400, 401, 403, 404, 422]on_401
Determines what happens when authentication fails.
Supported values:
| Value | Description |
|---|---|
fail | Immediately fail the request. |
refresh_and_retry | Refresh OAuth credentials once and retry. |
Default:
{ "on_401": "fail"}Retry Delays
base_delay_ms
Initial retry delay.
Default:
500(milliseconds)
max_delay_ms
Maximum retry delay.
Default:
30000(milliseconds)
Timeouts
connect_timeout_ms
Maximum DNS and TCP connection time.
Default:
5000http_timeout_ms
Maximum duration for an individual request.
Default:
30000total_timeout_ms
Maximum duration including all retries.
Default:
90000Concurrency
max_concurrent
Limits parallel requests to a provider.
Default:
5Setting the value to 0 or a negative number disables the limiter.
Response Size
max_response_bytes
Maximum response size before truncation.
Default:
102400(bytes)
Values less than or equal to zero disable response truncation.
Idempotency
Mutating APIs sometimes receive duplicate requests due to retries or network failures.
The idempotency object prevents duplicate operations by attaching an idempotency key.
Example:
{ "idempotency": { "mode": "dynamic", "scope": "workflow" }}mode
Determines whether idempotency is enabled.
| Value | Description |
|---|---|
none | Disable idempotency. |
dynamic | Automatically attach an idempotency key. |
Default:
noneheader_name
Header used for the idempotency key.
Default:
Idempotency-Keyscope
Determines how keys are generated.
| Value | Description |
|---|---|
call | New key for every request. |
workflow | Stable key across workflow execution. |
Complete Example
{ "stripe.stripe": { "version": "v2", "sandbox_endpoint": "https://api.stripe.com", "production_endpoint": "https://api.stripe.com", "methods": 42, "workflows": 3, "auth": { "type": "api_key", "header": "Authorization" }, "execution_policy": { "max_retries": 5, "on_401": "refresh_and_retry", "max_concurrent": 3, "idempotency": { "mode": "dynamic", "scope": "workflow" } } }}How manifest.json Fits into Execution
Every API execution follows the same flow.
tooling.json │ │ Is this tool trusted? ▼
policies.json │ │ Is this request allowed? ▼
manifest.json │ │ Which endpoint? │ Which auth? │ Retry policy? │ Timeout? │ Idempotency? ▼
Execute API Requesttooling.json defines what can execute.
policies.json defines whether it should execute.
manifest.json defines how it executes.
Together, these three files form the core execution model of Swytchcode.
Best Practices
- Do not edit generated values unless necessary.
- Commit
manifest.jsonto version control. - Keep integration versions pinned.
- Prefer sandbox mode during development.
- Configure retries based on the API provider.
- Enable idempotency for mutating operations.
- Review timeout settings for long-running APIs.
Continue learning about the execution pipeline: