sandpi/ platform

Configure the workspace

Egress credentials

Give agents outbound service access through network injection.

On this page

Choose outbound access

Platform Environments support outbound service credentials through Sandbox0's network injection. The authored platform-openapi.json and generated API details cover creation, list/detail, configuration replacement, material rotation and deletion, with request examples. Supported projections are HTTP headers, request placeholder substitution, mTLS, username/password and SSH proxy. These credentials are separate from your Session model API keys.

Outbound restrictions

Credential injection authenticates matching outbound requests; it is not a destination allowlist. A credential's domains, ports and fail-closed policy restrict that credential rule, not all Environment traffic.

Configure the Environment's base network policy through the API or console. In block-all, enabled egress credentials with a current source version also allow their configured destinations and ports. Removing all base domain exceptions therefore does not block these credential destinations. Do not assume that omitting credentials blocks network access.

Credential rules do not merge. When enabled rules overlap for the same domain, port and protocol, only the first matching credential is injected. Sandpi orders rules by credential creation time, then credential ID; editing a credential does not move it ahead of an older rule. Keep all HTTP headers needed for one service in a single credential projection, or use destinations that do not overlap. The Platform API does not expose Sandbox0's request-level httpMatch selector.

Scope and secret material

Use a personal token for a personal Environment, or a token for its owning Project. Cross-owner, cross-Project and personal-to-Project access returns 404 before any credential source access. Secret material goes directly to Sandbox0; Sandpi stores only configuration and observed version/status. Reads never return material or the internal source reference. Do not put secrets in projection templates; refer to material variables instead.

Update credentials during execution

Mutations take the Environment lifecycle lock and require its state to be ready. They also work while its Sandbox is paused. An active Run or checkpoint can delay credential mutations while holding the lifecycle lock. After they acquire the lock and apply, rotation and policy edits affect subsequent outbound connections; established connections are not retroactively reauthenticated. Resolver kind is immutable. Disabling a credential retains its source; deleting it removes both the binding and source. Failed operations retain reconciliation state, so inspect the list before retrying creation after an ambiguous failure. Creating the same display name twice returns a conflict rather than allocating another source.

Fork and rollback behavior

Credentials are Environment configuration outside RootFS checkpoints. Rollback does not restore an earlier credential version. Forks start without credential records or bindings; configure the child explicitly. Environment deletion removes the Sandbox before deleting its credential sources. The existing TUI credential routes remain unavailable for Platform Environments.

Create an Environment egress credential

POST /v1/environments/{environmentId}/egress-credentials

Requires a personal token for a personal Environment or a token scoped to the owning Project. Secret material is stored only in Sandbox0. Mutations use the Environment lifecycle lock and require a ready Environment; paused Environments are supported. Active work can delay mutations while holding the lifecycle lock. Applied changes affect subsequent outbound connections. Credentials are not inherited by forks and are not restored by Run rollback.

Authentication: Platform API bearer token

Parameters and headers
FieldType and constraintsRequiredDescription
path: environmentIdstring · min length 1YesEnvironment identifier. It must belong to the caller’s account or Project.

Request example

sh
curl -X POST \
    "https://api.sandpi.ai/v1/environments/$ENVIRONMENT_ID/egress-credentials" \
    -H "Authorization: Bearer $SANDPI_API_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
  "name": "GitHub API",
  "resolverKind": "static_headers",
  "projection": {
    "type": "http_headers",
    "headers": [
      {
        "name": "Authorization",
        "valueTemplate": "Bearer {{ .token }}"
      }
    ]
  },
  "rule": {
    "protocol": "https",
    "domains": [
      "api.github.com"
    ],
    "ports": [
      {
        "port": 443
      }
    ],
    "failurePolicy": "fail-closed"
  },
  "enabled": true,
  "material": {
    "type": "static_headers",
    "values": {
      "token": "YOUR_GITHUB_TOKEN"
    }
  }
}'
Request body · required application/json

Maximum bytes: 2,097,152

Outbound credential configuration and write-only material for creation.

FieldType and constraintsRequiredDescription
namestring · min length 1; max length 80
Validation pattern\S
YesHuman-readable name for this resource.
resolverKindstring · values: "static_headers" | "static_tls_client_certificate" | "static_username_password" | "static_ssh_private_key"YesCredential material resolver. Its kind is immutable after creation and must match the material type.
projectionone of the variants belowYesProjection variant applied at the network boundary. Choose the type matching the configured resolver.
projectionobjectYestype = "http_headers"—
projection.typestring · values: "http_headers"Yestype = "http_headers"Discriminator selecting the configuration or secret-material variant.
projection.headersarray · min 1 items; max 32 itemsYestype = "http_headers"Header definitions or secret header values applied by this configuration.
projection.headers[]objectYeseach array item—
projection.headers[].namestring · min length 1; max length 128
Validation pattern^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$
Yeseach array itemHuman-readable name for this resource.
projection.headers[].valueTemplatestring · min length 1; max length 2048Yeseach array itemProjection template referring to credential variables; do not embed a secret value here.
projectionobjectYestype = "placeholder_substitution"—
projection.typestring · values: "placeholder_substitution"Yestype = "placeholder_substitution"Discriminator selecting the configuration or secret-material variant.
projection.replacementsarray · min 1 items; max 32 itemsYestype = "placeholder_substitution"Placeholder replacement rules applied at the network boundary.
projection.replacements[]objectYeseach array item—
projection.replacements[].placeholderstring · min length 1; max length 512Yeseach array itemLiteral placeholder to replace in the selected request locations.
projection.replacements[].valueTemplatestring · min length 1; max length 2048Yeseach array itemProjection template referring to credential variables; do not embed a secret value here.
projection.replacements[].locationsarray · min 1 items; max 3 itemsYeseach array itemRequest locations where placeholder replacement applies.
projection.replacements[].locations[]string · values: "header" | "query" | "body"Yeseach array item—
projectionobjectYestype = "tls_client_certificate"—
projection.typestring · values: "tls_client_certificate"Yestype = "tls_client_certificate"Discriminator selecting the configuration or secret-material variant.
projectionobjectYestype = "username_password"—
projection.typestring · values: "username_password"Yestype = "username_password"Discriminator selecting the configuration or secret-material variant.
projectionobjectYestype = "ssh_proxy"—
projection.typestring · values: "ssh_proxy"Yestype = "ssh_proxy"Discriminator selecting the configuration or secret-material variant.
projection.upstreamUsernamestring · min length 1; max length 255Yestype = "ssh_proxy"Username used for the upstream SSH connection.
projection.sandboxPublicKeysarray · min 1 items; max 16 itemsYestype = "ssh_proxy"Public keys allowed to use this Sandbox-side SSH proxy binding.
projection.sandboxPublicKeys[]string · min length 1; max length 16384Yeseach array item—
projection.knownHostsarray · min 0 items; max 64 itemsNotype = "ssh_proxy"Known-host entries for upstream SSH host verification.
projection.knownHosts[]string · min length 1; max length 16384Yeseach array item—
ruleobjectYesMatching outbound destinations and resolver failure policy.
rule.protocolstring · values: "http" | "https" | "grpc" | "tls" | "ssh" | "socks5" | "mqtt" | "redis"Yeswithin ruleNetwork protocol to which the binding applies.
rule.domainsarray · min 1 items; max 128 itemsYeswithin ruleDestination domain patterns matched by the credential rule.
rule.domains[]string · min length 1; max length 255Yeseach array itemExact or wildcard domain, e.g. api.example.com or *.example.com; URLs, paths and ports are rejected. Domains are normalized and deduplicated.
rule.portsarray · min 1 items; max 16 itemsYeswithin ruleDestination ports matched by the credential rule.
rule.ports[]objectYeseach array item—
rule.ports[].portinteger · ≥ 1; ≤ 65535Yeseach array itemPort number matched by this destination rule.
rule.ports[].protocolstring · values: "tcp"; default: "tcp"Noeach array itemNetwork protocol to which the binding applies.
rule.failurePolicystring · values: "fail-closed" | "fail-open"; default: "fail-closed"Nowithin ruleBehavior when the network-boundary credential cannot be resolved.
enabledboolean · default: trueNoWhether this configuration is enabled for future use.
materialone of the variants belowYesWrite-only Sandbox0 source material. Never returned or stored in Sandpi PostgreSQL. The type must match resolverKind.
materialobjectYestype = "static_headers"—
material.typestring · values: "static_headers"Yestype = "static_headers"Discriminator selecting the configuration or secret-material variant.
material.valuesobject · min 1 keys; max 32 keysYestype = "static_headers"Map of secret variable names to their write-only values.
material.values.{key}string · min length 1; max length 1048576; write onlyNoadditional keys—
materialobjectYestype = "static_tls_client_certificate"—
material.typestring · values: "static_tls_client_certificate"Yestype = "static_tls_client_certificate"Discriminator selecting the configuration or secret-material variant.
material.certificatePemstring · min length 1; max length 1048576; write onlyYestype = "static_tls_client_certificate"PEM-encoded client certificate supplied only when creating or rotating material.
material.privateKeyPemstring · min length 1; max length 1048576; write onlyYestype = "static_tls_client_certificate"PEM-encoded private key supplied only when creating or rotating material.
material.caPemstring · max length 1048576; write onlyNotype = "static_tls_client_certificate"Optional PEM-encoded certificate authority used with this material.
materialobjectYestype = "static_username_password"—
material.typestring · values: "static_username_password"Yestype = "static_username_password"Discriminator selecting the configuration or secret-material variant.
material.usernamestring · min length 1; max length 1024; write onlyYestype = "static_username_password"Write-only upstream authentication username.
material.passwordstring · min length 1; max length 1048576; write onlyYestype = "static_username_password"Write-only upstream authentication password.
materialobjectYestype = "static_ssh_private_key"—
material.typestring · values: "static_ssh_private_key"Yestype = "static_ssh_private_key"Discriminator selecting the configuration or secret-material variant.
material.privateKeyPemstring · min length 1; max length 1048576; write onlyYestype = "static_ssh_private_key"PEM-encoded private key supplied only when creating or rotating material.
material.passphrasestring · max length 1048576; write onlyNotype = "static_ssh_private_key"Optional write-only private-key passphrase.
Example
Example
{
  "name": "GitHub API",
  "resolverKind": "static_headers",
  "projection": {
    "type": "http_headers",
    "headers": [
      {
        "name": "Authorization",
        "valueTemplate": "Bearer {{ .token }}"
      }
    ]
  },
  "rule": {
    "protocol": "https",
    "domains": [
      "api.github.com"
    ],
    "ports": [
      {
        "port": 443
      }
    ],
    "failurePolicy": "fail-closed"
  },
  "enabled": true,
  "material": {
    "type": "static_headers",
    "values": {
      "token": "YOUR_GITHUB_TOKEN"
    }
  }
}

Responses

201 Created.
Response body application/json
FieldType and constraintsRequiredDescription
dataobject · extra fields rejectedYesSecret-free configuration and observed source state. Contains neither material nor the internal Sandbox0 source reference.
data.namestring · min length 1; max length 80
Validation pattern\S
Yeswithin dataHuman-readable name for this resource.
data.resolverKindstring · values: "static_headers" | "static_tls_client_certificate" | "static_username_password" | "static_ssh_private_key"Yeswithin dataCredential material resolver. Its kind is immutable after creation and must match the material type.
data.projectionone of the variants belowYeswithin dataProjection variant applied at the network boundary. Choose the type matching the configured resolver.
data.projectionobjectYestype = "http_headers"—
data.projection.typestring · values: "http_headers"Yestype = "http_headers"Discriminator selecting the configuration or secret-material variant.
data.projection.headersarray · min 1 items; max 32 itemsYestype = "http_headers"Header definitions or secret header values applied by this configuration.
data.projection.headers[]objectYeseach array item—
data.projection.headers[].namestring · min length 1; max length 128
Validation pattern^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$
Yeseach array itemHuman-readable name for this resource.
data.projection.headers[].valueTemplatestring · min length 1; max length 2048Yeseach array itemProjection template referring to credential variables; do not embed a secret value here.
data.projectionobjectYestype = "placeholder_substitution"—
data.projection.typestring · values: "placeholder_substitution"Yestype = "placeholder_substitution"Discriminator selecting the configuration or secret-material variant.
data.projection.replacementsarray · min 1 items; max 32 itemsYestype = "placeholder_substitution"Placeholder replacement rules applied at the network boundary.
data.projection.replacements[]objectYeseach array item—
data.projection.replacements[].placeholderstring · min length 1; max length 512Yeseach array itemLiteral placeholder to replace in the selected request locations.
data.projection.replacements[].valueTemplatestring · min length 1; max length 2048Yeseach array itemProjection template referring to credential variables; do not embed a secret value here.
data.projection.replacements[].locationsarray · min 1 items; max 3 itemsYeseach array itemRequest locations where placeholder replacement applies.
data.projection.replacements[].locations[]string · values: "header" | "query" | "body"Yeseach array item—
data.projectionobjectYestype = "tls_client_certificate"—
data.projection.typestring · values: "tls_client_certificate"Yestype = "tls_client_certificate"Discriminator selecting the configuration or secret-material variant.
data.projectionobjectYestype = "username_password"—
data.projection.typestring · values: "username_password"Yestype = "username_password"Discriminator selecting the configuration or secret-material variant.
data.projectionobjectYestype = "ssh_proxy"—
data.projection.typestring · values: "ssh_proxy"Yestype = "ssh_proxy"Discriminator selecting the configuration or secret-material variant.
data.projection.upstreamUsernamestring · min length 1; max length 255Yestype = "ssh_proxy"Username used for the upstream SSH connection.
data.projection.sandboxPublicKeysarray · min 1 items; max 16 itemsYestype = "ssh_proxy"Public keys allowed to use this Sandbox-side SSH proxy binding.
data.projection.sandboxPublicKeys[]string · min length 1; max length 16384Yeseach array item—
data.projection.knownHostsarray · min 0 items; max 64 itemsNotype = "ssh_proxy"Known-host entries for upstream SSH host verification.
data.projection.knownHosts[]string · min length 1; max length 16384Yeseach array item—
data.ruleobjectYeswithin dataMatching outbound destinations and resolver failure policy.
data.rule.protocolstring · values: "http" | "https" | "grpc" | "tls" | "ssh" | "socks5" | "mqtt" | "redis"Yeswithin dataNetwork protocol to which the binding applies.
data.rule.domainsarray · min 1 items; max 128 itemsYeswithin dataDestination domain patterns matched by the credential rule.
data.rule.domains[]string · min length 1; max length 255Yeseach array itemExact or wildcard domain, e.g. api.example.com or *.example.com; URLs, paths and ports are rejected. Domains are normalized and deduplicated.
data.rule.portsarray · min 1 items; max 16 itemsYeswithin dataDestination ports matched by the credential rule.
data.rule.ports[]objectYeseach array item—
data.rule.ports[].portinteger · ≥ 1; ≤ 65535Yeseach array itemPort number matched by this destination rule.
data.rule.ports[].protocolstring · values: "tcp"; default: "tcp"Noeach array itemNetwork protocol to which the binding applies.
data.rule.failurePolicystring · values: "fail-closed" | "fail-open"; default: "fail-closed"Nowithin dataBehavior when the network-boundary credential cannot be resolved.
data.enabledboolean · default: trueYeswithin dataWhether this configuration is enabled for future use.
data.idstring · min length 1Yeswithin dataResource identifier used to read or manage this resource.
data.environmentIdstring · min length 1Yeswithin dataEnvironment identifier. It must belong to the caller’s account or Project.
data.statusstring · values: "provisioning" | "active" | "error" | "deleting"Yeswithin dataCurrent resource state; inspect the allowed values and the operation’s lifecycle notes.
data.currentVersioninteger · ≥ 1Nowithin dataObserved current credential source version.
data.sourceStatusstring · min length 1Nowithin dataObserved credential source state from Sandbox0.
data.errorstring · min length 1Nowithin dataStructured failure information. Inspect the stable code and retain the request ID for investigation.
data.createdAtnumberYeswithin dataCreation time as a Unix timestamp in seconds.
data.updatedAtnumberYeswithin dataLast update time as a Unix timestamp in seconds.
Example
Example
{
  "data": {
    "name": "example",
    "resolverKind": "static_headers",
    "projection": {
      "type": "http_headers",
      "headers": [
        {
          "name": "example",
          "valueTemplate": "example"
        }
      ]
    },
    "rule": {
      "protocol": "http",
      "domains": [
        "example"
      ],
      "ports": [
        {
          "port": 1
        }
      ]
    },
    "enabled": false,
    "id": "example",
    "environmentId": "example",
    "status": "provisioning",
    "createdAt": 0,
    "updatedAt": 0
  }
}
Error responses
default Sandpi error.
Error body application/json

Standard error envelope containing a stable code, diagnostic message and request identity.

FieldType and constraintsRequiredDescription
errorobject · extra fields rejectedYesStructured failure information. Inspect the stable code and retain the request ID for investigation.
error.codestringYeswithin errorStable error code used to distinguish failures programmatically.
error.messagestringYeswithin errorHuman-readable diagnostic text.
error.requestIdstringYeswithin errorRequest identifier for correlating diagnostics and support investigations.
error.detailsanyNowithin errorOptional structured error context. Its shape is specific to the service failure.
error.loginUrlstringNowithin errorAuthentication URL supplied when a browser login is required.
error.registrationOpenbooleanNowithin errorWhether new account registration is enabled for this deployment.
Example
Example
{
  "error": {
    "code": "platform_balance_insufficient",
    "message": "Top up Platform credits before submitting a Run.",
    "requestId": "req_example"
  }
}

Verify and rotate

Inspect the credential’s observed status before testing a new outbound connection. Replace material using the rotation operation, and check status again. Established connections can continue with their earlier authentication; reconnect to exercise the new version.

List Environment egress credentials

GET /v1/environments/{environmentId}/egress-credentials

Requires a personal token for a personal Environment or a token scoped to the owning Project. Secret material is stored only in Sandbox0. Mutations use the Environment lifecycle lock and require a ready Environment; paused Environments are supported. Active work can delay mutations while holding the lifecycle lock. Applied changes affect subsequent outbound connections. Credentials are not inherited by forks and are not restored by Run rollback.

Authentication: Platform API bearer token

Parameters and headers
FieldType and constraintsRequiredDescription
path: environmentIdstring · min length 1YesEnvironment identifier. It must belong to the caller’s account or Project.

Request example

sh
curl \
    "https://api.sandpi.ai/v1/environments/$ENVIRONMENT_ID/egress-credentials" \
    -H "Authorization: Bearer $SANDPI_API_TOKEN"

No request body.

Responses

200 OK.
Response body application/json
FieldType and constraintsRequiredDescription
dataarrayYesSuccessful result wrapped by the API. The child fields describe its content.
data[]object · extra fields rejectedYeseach array itemSecret-free configuration and observed source state. Contains neither material nor the internal Sandbox0 source reference.
data[].namestring · min length 1; max length 80
Validation pattern\S
Yeseach array itemHuman-readable name for this resource.
data[].resolverKindstring · values: "static_headers" | "static_tls_client_certificate" | "static_username_password" | "static_ssh_private_key"Yeseach array itemCredential material resolver. Its kind is immutable after creation and must match the material type.
data[].projectionone of the variants belowYeseach array itemProjection variant applied at the network boundary. Choose the type matching the configured resolver.
data[].projectionobjectYestype = "http_headers"—
data[].projection.typestring · values: "http_headers"Yestype = "http_headers"Discriminator selecting the configuration or secret-material variant.
data[].projection.headersarray · min 1 items; max 32 itemsYestype = "http_headers"Header definitions or secret header values applied by this configuration.
data[].projection.headers[]objectYeseach array item—
data[].projection.headers[].namestring · min length 1; max length 128
Validation pattern^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$
Yeseach array itemHuman-readable name for this resource.
data[].projection.headers[].valueTemplatestring · min length 1; max length 2048Yeseach array itemProjection template referring to credential variables; do not embed a secret value here.
data[].projectionobjectYestype = "placeholder_substitution"—
data[].projection.typestring · values: "placeholder_substitution"Yestype = "placeholder_substitution"Discriminator selecting the configuration or secret-material variant.
data[].projection.replacementsarray · min 1 items; max 32 itemsYestype = "placeholder_substitution"Placeholder replacement rules applied at the network boundary.
data[].projection.replacements[]objectYeseach array item—
data[].projection.replacements[].placeholderstring · min length 1; max length 512Yeseach array itemLiteral placeholder to replace in the selected request locations.
data[].projection.replacements[].valueTemplatestring · min length 1; max length 2048Yeseach array itemProjection template referring to credential variables; do not embed a secret value here.
data[].projection.replacements[].locationsarray · min 1 items; max 3 itemsYeseach array itemRequest locations where placeholder replacement applies.
data[].projection.replacements[].locations[]string · values: "header" | "query" | "body"Yeseach array item—
data[].projectionobjectYestype = "tls_client_certificate"—
data[].projection.typestring · values: "tls_client_certificate"Yestype = "tls_client_certificate"Discriminator selecting the configuration or secret-material variant.
data[].projectionobjectYestype = "username_password"—
data[].projection.typestring · values: "username_password"Yestype = "username_password"Discriminator selecting the configuration or secret-material variant.
data[].projectionobjectYestype = "ssh_proxy"—
data[].projection.typestring · values: "ssh_proxy"Yestype = "ssh_proxy"Discriminator selecting the configuration or secret-material variant.
data[].projection.upstreamUsernamestring · min length 1; max length 255Yestype = "ssh_proxy"Username used for the upstream SSH connection.
data[].projection.sandboxPublicKeysarray · min 1 items; max 16 itemsYestype = "ssh_proxy"Public keys allowed to use this Sandbox-side SSH proxy binding.
data[].projection.sandboxPublicKeys[]string · min length 1; max length 16384Yeseach array item—
data[].projection.knownHostsarray · min 0 items; max 64 itemsNotype = "ssh_proxy"Known-host entries for upstream SSH host verification.
data[].projection.knownHosts[]string · min length 1; max length 16384Yeseach array item—
data[].ruleobjectYeseach array itemMatching outbound destinations and resolver failure policy.
data[].rule.protocolstring · values: "http" | "https" | "grpc" | "tls" | "ssh" | "socks5" | "mqtt" | "redis"Yeseach array itemNetwork protocol to which the binding applies.
data[].rule.domainsarray · min 1 items; max 128 itemsYeseach array itemDestination domain patterns matched by the credential rule.
data[].rule.domains[]string · min length 1; max length 255Yeseach array itemExact or wildcard domain, e.g. api.example.com or *.example.com; URLs, paths and ports are rejected. Domains are normalized and deduplicated.
data[].rule.portsarray · min 1 items; max 16 itemsYeseach array itemDestination ports matched by the credential rule.
data[].rule.ports[]objectYeseach array item—
data[].rule.ports[].portinteger · ≥ 1; ≤ 65535Yeseach array itemPort number matched by this destination rule.
data[].rule.ports[].protocolstring · values: "tcp"; default: "tcp"Noeach array itemNetwork protocol to which the binding applies.
data[].rule.failurePolicystring · values: "fail-closed" | "fail-open"; default: "fail-closed"Noeach array itemBehavior when the network-boundary credential cannot be resolved.
data[].enabledboolean · default: trueYeseach array itemWhether this configuration is enabled for future use.
data[].idstring · min length 1Yeseach array itemResource identifier used to read or manage this resource.
data[].environmentIdstring · min length 1Yeseach array itemEnvironment identifier. It must belong to the caller’s account or Project.
data[].statusstring · values: "provisioning" | "active" | "error" | "deleting"Yeseach array itemCurrent resource state; inspect the allowed values and the operation’s lifecycle notes.
data[].currentVersioninteger · ≥ 1Noeach array itemObserved current credential source version.
data[].sourceStatusstring · min length 1Noeach array itemObserved credential source state from Sandbox0.
data[].errorstring · min length 1Noeach array itemStructured failure information. Inspect the stable code and retain the request ID for investigation.
data[].createdAtnumberYeseach array itemCreation time as a Unix timestamp in seconds.
data[].updatedAtnumberYeseach array itemLast update time as a Unix timestamp in seconds.
Example
Example
{
  "data": [
    {
      "name": "example",
      "resolverKind": "static_headers",
      "projection": {
        "type": "http_headers",
        "headers": [
          {
            "name": "example",
            "valueTemplate": "example"
          }
        ]
      },
      "rule": {
        "protocol": "http",
        "domains": [
          "example"
        ],
        "ports": [
          {
            "port": 1
          }
        ]
      },
      "enabled": false,
      "id": "example",
      "environmentId": "example",
      "status": "provisioning",
      "createdAt": 0,
      "updatedAt": 0
    }
  ]
}
Error responses
default Sandpi error.
Error body application/json

Standard error envelope containing a stable code, diagnostic message and request identity.

FieldType and constraintsRequiredDescription
errorobject · extra fields rejectedYesStructured failure information. Inspect the stable code and retain the request ID for investigation.
error.codestringYeswithin errorStable error code used to distinguish failures programmatically.
error.messagestringYeswithin errorHuman-readable diagnostic text.
error.requestIdstringYeswithin errorRequest identifier for correlating diagnostics and support investigations.
error.detailsanyNowithin errorOptional structured error context. Its shape is specific to the service failure.
error.loginUrlstringNowithin errorAuthentication URL supplied when a browser login is required.
error.registrationOpenbooleanNowithin errorWhether new account registration is enabled for this deployment.
Example
Example
{
  "error": {
    "code": "platform_balance_insufficient",
    "message": "Top up Platform credits before submitting a Run.",
    "requestId": "req_example"
  }
}

Replace egress credential secret material

PUT /v1/environments/{environmentId}/egress-credentials/{credentialId}/material

Requires a personal token for a personal Environment or a token scoped to the owning Project. Secret material is stored only in Sandbox0. Mutations use the Environment lifecycle lock and require a ready Environment; paused Environments are supported. Active work can delay mutations while holding the lifecycle lock. Applied changes affect subsequent outbound connections. Credentials are not inherited by forks and are not restored by Run rollback. Resolver kind is immutable; replacing material advances its version without returning it.

Authentication: Platform API bearer token

Parameters and headers
FieldType and constraintsRequiredDescription
path: environmentIdstring · min length 1YesEnvironment identifier. It must belong to the caller’s account or Project.
path: credentialIdstring · min length 1YesEgress credential identifier within this Environment.

Request example

sh
curl -X PUT \
    "https://api.sandpi.ai/v1/environments/$ENVIRONMENT_ID/egress-credentials/$CREDENTIAL_ID/material" \
    -H "Authorization: Bearer $SANDPI_API_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
  "resolverKind": "static_headers",
  "material": {
    "type": "static_headers",
    "values": {
      "token": "YOUR_NEW_GITHUB_TOKEN"
    }
  }
}'
Request body · required application/json

Maximum bytes: 2,097,152

Replacement write-only material; the resolver kind must match the existing credential.

FieldType and constraintsRequiredDescription
resolverKindstring · values: "static_headers" | "static_tls_client_certificate" | "static_username_password" | "static_ssh_private_key"YesCredential material resolver. Its kind is immutable after creation and must match the material type.
materialone of the variants belowYesWrite-only Sandbox0 source material. Never returned or stored in Sandpi PostgreSQL. The type must match resolverKind.
materialobjectYestype = "static_headers"—
material.typestring · values: "static_headers"Yestype = "static_headers"Discriminator selecting the configuration or secret-material variant.
material.valuesobject · min 1 keys; max 32 keysYestype = "static_headers"Map of secret variable names to their write-only values.
material.values.{key}string · min length 1; max length 1048576; write onlyNoadditional keys—
materialobjectYestype = "static_tls_client_certificate"—
material.typestring · values: "static_tls_client_certificate"Yestype = "static_tls_client_certificate"Discriminator selecting the configuration or secret-material variant.
material.certificatePemstring · min length 1; max length 1048576; write onlyYestype = "static_tls_client_certificate"PEM-encoded client certificate supplied only when creating or rotating material.
material.privateKeyPemstring · min length 1; max length 1048576; write onlyYestype = "static_tls_client_certificate"PEM-encoded private key supplied only when creating or rotating material.
material.caPemstring · max length 1048576; write onlyNotype = "static_tls_client_certificate"Optional PEM-encoded certificate authority used with this material.
materialobjectYestype = "static_username_password"—
material.typestring · values: "static_username_password"Yestype = "static_username_password"Discriminator selecting the configuration or secret-material variant.
material.usernamestring · min length 1; max length 1024; write onlyYestype = "static_username_password"Write-only upstream authentication username.
material.passwordstring · min length 1; max length 1048576; write onlyYestype = "static_username_password"Write-only upstream authentication password.
materialobjectYestype = "static_ssh_private_key"—
material.typestring · values: "static_ssh_private_key"Yestype = "static_ssh_private_key"Discriminator selecting the configuration or secret-material variant.
material.privateKeyPemstring · min length 1; max length 1048576; write onlyYestype = "static_ssh_private_key"PEM-encoded private key supplied only when creating or rotating material.
material.passphrasestring · max length 1048576; write onlyNotype = "static_ssh_private_key"Optional write-only private-key passphrase.
Example
Example
{
  "resolverKind": "static_headers",
  "material": {
    "type": "static_headers",
    "values": {
      "token": "YOUR_NEW_GITHUB_TOKEN"
    }
  }
}

Responses

200 OK.
Response body application/json
FieldType and constraintsRequiredDescription
dataobject · extra fields rejectedYesSecret-free configuration and observed source state. Contains neither material nor the internal Sandbox0 source reference.
data.namestring · min length 1; max length 80
Validation pattern\S
Yeswithin dataHuman-readable name for this resource.
data.resolverKindstring · values: "static_headers" | "static_tls_client_certificate" | "static_username_password" | "static_ssh_private_key"Yeswithin dataCredential material resolver. Its kind is immutable after creation and must match the material type.
data.projectionone of the variants belowYeswithin dataProjection variant applied at the network boundary. Choose the type matching the configured resolver.
data.projectionobjectYestype = "http_headers"—
data.projection.typestring · values: "http_headers"Yestype = "http_headers"Discriminator selecting the configuration or secret-material variant.
data.projection.headersarray · min 1 items; max 32 itemsYestype = "http_headers"Header definitions or secret header values applied by this configuration.
data.projection.headers[]objectYeseach array item—
data.projection.headers[].namestring · min length 1; max length 128
Validation pattern^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$
Yeseach array itemHuman-readable name for this resource.
data.projection.headers[].valueTemplatestring · min length 1; max length 2048Yeseach array itemProjection template referring to credential variables; do not embed a secret value here.
data.projectionobjectYestype = "placeholder_substitution"—
data.projection.typestring · values: "placeholder_substitution"Yestype = "placeholder_substitution"Discriminator selecting the configuration or secret-material variant.
data.projection.replacementsarray · min 1 items; max 32 itemsYestype = "placeholder_substitution"Placeholder replacement rules applied at the network boundary.
data.projection.replacements[]objectYeseach array item—
data.projection.replacements[].placeholderstring · min length 1; max length 512Yeseach array itemLiteral placeholder to replace in the selected request locations.
data.projection.replacements[].valueTemplatestring · min length 1; max length 2048Yeseach array itemProjection template referring to credential variables; do not embed a secret value here.
data.projection.replacements[].locationsarray · min 1 items; max 3 itemsYeseach array itemRequest locations where placeholder replacement applies.
data.projection.replacements[].locations[]string · values: "header" | "query" | "body"Yeseach array item—
data.projectionobjectYestype = "tls_client_certificate"—
data.projection.typestring · values: "tls_client_certificate"Yestype = "tls_client_certificate"Discriminator selecting the configuration or secret-material variant.
data.projectionobjectYestype = "username_password"—
data.projection.typestring · values: "username_password"Yestype = "username_password"Discriminator selecting the configuration or secret-material variant.
data.projectionobjectYestype = "ssh_proxy"—
data.projection.typestring · values: "ssh_proxy"Yestype = "ssh_proxy"Discriminator selecting the configuration or secret-material variant.
data.projection.upstreamUsernamestring · min length 1; max length 255Yestype = "ssh_proxy"Username used for the upstream SSH connection.
data.projection.sandboxPublicKeysarray · min 1 items; max 16 itemsYestype = "ssh_proxy"Public keys allowed to use this Sandbox-side SSH proxy binding.
data.projection.sandboxPublicKeys[]string · min length 1; max length 16384Yeseach array item—
data.projection.knownHostsarray · min 0 items; max 64 itemsNotype = "ssh_proxy"Known-host entries for upstream SSH host verification.
data.projection.knownHosts[]string · min length 1; max length 16384Yeseach array item—
data.ruleobjectYeswithin dataMatching outbound destinations and resolver failure policy.
data.rule.protocolstring · values: "http" | "https" | "grpc" | "tls" | "ssh" | "socks5" | "mqtt" | "redis"Yeswithin dataNetwork protocol to which the binding applies.
data.rule.domainsarray · min 1 items; max 128 itemsYeswithin dataDestination domain patterns matched by the credential rule.
data.rule.domains[]string · min length 1; max length 255Yeseach array itemExact or wildcard domain, e.g. api.example.com or *.example.com; URLs, paths and ports are rejected. Domains are normalized and deduplicated.
data.rule.portsarray · min 1 items; max 16 itemsYeswithin dataDestination ports matched by the credential rule.
data.rule.ports[]objectYeseach array item—
data.rule.ports[].portinteger · ≥ 1; ≤ 65535Yeseach array itemPort number matched by this destination rule.
data.rule.ports[].protocolstring · values: "tcp"; default: "tcp"Noeach array itemNetwork protocol to which the binding applies.
data.rule.failurePolicystring · values: "fail-closed" | "fail-open"; default: "fail-closed"Nowithin dataBehavior when the network-boundary credential cannot be resolved.
data.enabledboolean · default: trueYeswithin dataWhether this configuration is enabled for future use.
data.idstring · min length 1Yeswithin dataResource identifier used to read or manage this resource.
data.environmentIdstring · min length 1Yeswithin dataEnvironment identifier. It must belong to the caller’s account or Project.
data.statusstring · values: "provisioning" | "active" | "error" | "deleting"Yeswithin dataCurrent resource state; inspect the allowed values and the operation’s lifecycle notes.
data.currentVersioninteger · ≥ 1Nowithin dataObserved current credential source version.
data.sourceStatusstring · min length 1Nowithin dataObserved credential source state from Sandbox0.
data.errorstring · min length 1Nowithin dataStructured failure information. Inspect the stable code and retain the request ID for investigation.
data.createdAtnumberYeswithin dataCreation time as a Unix timestamp in seconds.
data.updatedAtnumberYeswithin dataLast update time as a Unix timestamp in seconds.
Example
Example
{
  "data": {
    "name": "example",
    "resolverKind": "static_headers",
    "projection": {
      "type": "http_headers",
      "headers": [
        {
          "name": "example",
          "valueTemplate": "example"
        }
      ]
    },
    "rule": {
      "protocol": "http",
      "domains": [
        "example"
      ],
      "ports": [
        {
          "port": 1
        }
      ]
    },
    "enabled": false,
    "id": "example",
    "environmentId": "example",
    "status": "provisioning",
    "createdAt": 0,
    "updatedAt": 0
  }
}
Error responses
default Sandpi error.
Error body application/json

Standard error envelope containing a stable code, diagnostic message and request identity.

FieldType and constraintsRequiredDescription
errorobject · extra fields rejectedYesStructured failure information. Inspect the stable code and retain the request ID for investigation.
error.codestringYeswithin errorStable error code used to distinguish failures programmatically.
error.messagestringYeswithin errorHuman-readable diagnostic text.
error.requestIdstringYeswithin errorRequest identifier for correlating diagnostics and support investigations.
error.detailsanyNowithin errorOptional structured error context. Its shape is specific to the service failure.
error.loginUrlstringNowithin errorAuthentication URL supplied when a browser login is required.
error.registrationOpenbooleanNowithin errorWhether new account registration is enabled for this deployment.
Example
Example
{
  "error": {
    "code": "platform_balance_insufficient",
    "message": "Top up Platform credits before submitting a Run.",
    "requestId": "req_example"
  }
}

Inbound versus outbound credentials

These credentials let an agent call a third-party service. They do not authenticate events sent to Sandpi. A Parseable webhook password authenticates incoming alerts; configure separate egress access or MCP tools if the agent also needs to query logs. See inbound webhooks.

Read and replace a binding

Read configuration and observed status, then replace the non-secret connection rules or projection. Secret changes use the separate material rotation operation.

Get an Environment egress credential

GET /v1/environments/{environmentId}/egress-credentials/{credentialId}

Requires a personal token for a personal Environment or a token scoped to the owning Project. Secret material is stored only in Sandbox0. Mutations use the Environment lifecycle lock and require a ready Environment; paused Environments are supported. Active work can delay mutations while holding the lifecycle lock. Applied changes affect subsequent outbound connections. Credentials are not inherited by forks and are not restored by Run rollback.

Authentication: Platform API bearer token

Parameters and headers
FieldType and constraintsRequiredDescription
path: environmentIdstring · min length 1YesEnvironment identifier. It must belong to the caller’s account or Project.
path: credentialIdstring · min length 1YesEgress credential identifier within this Environment.

Request example

sh
curl \
    "https://api.sandpi.ai/v1/environments/$ENVIRONMENT_ID/egress-credentials/$CREDENTIAL_ID" \
    -H "Authorization: Bearer $SANDPI_API_TOKEN"

No request body.

Responses

200 OK.
Response body application/json
FieldType and constraintsRequiredDescription
dataobject · extra fields rejectedYesSecret-free configuration and observed source state. Contains neither material nor the internal Sandbox0 source reference.
data.namestring · min length 1; max length 80
Validation pattern\S
Yeswithin dataHuman-readable name for this resource.
data.resolverKindstring · values: "static_headers" | "static_tls_client_certificate" | "static_username_password" | "static_ssh_private_key"Yeswithin dataCredential material resolver. Its kind is immutable after creation and must match the material type.
data.projectionone of the variants belowYeswithin dataProjection variant applied at the network boundary. Choose the type matching the configured resolver.
data.projectionobjectYestype = "http_headers"—
data.projection.typestring · values: "http_headers"Yestype = "http_headers"Discriminator selecting the configuration or secret-material variant.
data.projection.headersarray · min 1 items; max 32 itemsYestype = "http_headers"Header definitions or secret header values applied by this configuration.
data.projection.headers[]objectYeseach array item—
data.projection.headers[].namestring · min length 1; max length 128
Validation pattern^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$
Yeseach array itemHuman-readable name for this resource.
data.projection.headers[].valueTemplatestring · min length 1; max length 2048Yeseach array itemProjection template referring to credential variables; do not embed a secret value here.
data.projectionobjectYestype = "placeholder_substitution"—
data.projection.typestring · values: "placeholder_substitution"Yestype = "placeholder_substitution"Discriminator selecting the configuration or secret-material variant.
data.projection.replacementsarray · min 1 items; max 32 itemsYestype = "placeholder_substitution"Placeholder replacement rules applied at the network boundary.
data.projection.replacements[]objectYeseach array item—
data.projection.replacements[].placeholderstring · min length 1; max length 512Yeseach array itemLiteral placeholder to replace in the selected request locations.
data.projection.replacements[].valueTemplatestring · min length 1; max length 2048Yeseach array itemProjection template referring to credential variables; do not embed a secret value here.
data.projection.replacements[].locationsarray · min 1 items; max 3 itemsYeseach array itemRequest locations where placeholder replacement applies.
data.projection.replacements[].locations[]string · values: "header" | "query" | "body"Yeseach array item—
data.projectionobjectYestype = "tls_client_certificate"—
data.projection.typestring · values: "tls_client_certificate"Yestype = "tls_client_certificate"Discriminator selecting the configuration or secret-material variant.
data.projectionobjectYestype = "username_password"—
data.projection.typestring · values: "username_password"Yestype = "username_password"Discriminator selecting the configuration or secret-material variant.
data.projectionobjectYestype = "ssh_proxy"—
data.projection.typestring · values: "ssh_proxy"Yestype = "ssh_proxy"Discriminator selecting the configuration or secret-material variant.
data.projection.upstreamUsernamestring · min length 1; max length 255Yestype = "ssh_proxy"Username used for the upstream SSH connection.
data.projection.sandboxPublicKeysarray · min 1 items; max 16 itemsYestype = "ssh_proxy"Public keys allowed to use this Sandbox-side SSH proxy binding.
data.projection.sandboxPublicKeys[]string · min length 1; max length 16384Yeseach array item—
data.projection.knownHostsarray · min 0 items; max 64 itemsNotype = "ssh_proxy"Known-host entries for upstream SSH host verification.
data.projection.knownHosts[]string · min length 1; max length 16384Yeseach array item—
data.ruleobjectYeswithin dataMatching outbound destinations and resolver failure policy.
data.rule.protocolstring · values: "http" | "https" | "grpc" | "tls" | "ssh" | "socks5" | "mqtt" | "redis"Yeswithin dataNetwork protocol to which the binding applies.
data.rule.domainsarray · min 1 items; max 128 itemsYeswithin dataDestination domain patterns matched by the credential rule.
data.rule.domains[]string · min length 1; max length 255Yeseach array itemExact or wildcard domain, e.g. api.example.com or *.example.com; URLs, paths and ports are rejected. Domains are normalized and deduplicated.
data.rule.portsarray · min 1 items; max 16 itemsYeswithin dataDestination ports matched by the credential rule.
data.rule.ports[]objectYeseach array item—
data.rule.ports[].portinteger · ≥ 1; ≤ 65535Yeseach array itemPort number matched by this destination rule.
data.rule.ports[].protocolstring · values: "tcp"; default: "tcp"Noeach array itemNetwork protocol to which the binding applies.
data.rule.failurePolicystring · values: "fail-closed" | "fail-open"; default: "fail-closed"Nowithin dataBehavior when the network-boundary credential cannot be resolved.
data.enabledboolean · default: trueYeswithin dataWhether this configuration is enabled for future use.
data.idstring · min length 1Yeswithin dataResource identifier used to read or manage this resource.
data.environmentIdstring · min length 1Yeswithin dataEnvironment identifier. It must belong to the caller’s account or Project.
data.statusstring · values: "provisioning" | "active" | "error" | "deleting"Yeswithin dataCurrent resource state; inspect the allowed values and the operation’s lifecycle notes.
data.currentVersioninteger · ≥ 1Nowithin dataObserved current credential source version.
data.sourceStatusstring · min length 1Nowithin dataObserved credential source state from Sandbox0.
data.errorstring · min length 1Nowithin dataStructured failure information. Inspect the stable code and retain the request ID for investigation.
data.createdAtnumberYeswithin dataCreation time as a Unix timestamp in seconds.
data.updatedAtnumberYeswithin dataLast update time as a Unix timestamp in seconds.
Example
Example
{
  "data": {
    "name": "example",
    "resolverKind": "static_headers",
    "projection": {
      "type": "http_headers",
      "headers": [
        {
          "name": "example",
          "valueTemplate": "example"
        }
      ]
    },
    "rule": {
      "protocol": "http",
      "domains": [
        "example"
      ],
      "ports": [
        {
          "port": 1
        }
      ]
    },
    "enabled": false,
    "id": "example",
    "environmentId": "example",
    "status": "provisioning",
    "createdAt": 0,
    "updatedAt": 0
  }
}
Error responses
default Sandpi error.
Error body application/json

Standard error envelope containing a stable code, diagnostic message and request identity.

FieldType and constraintsRequiredDescription
errorobject · extra fields rejectedYesStructured failure information. Inspect the stable code and retain the request ID for investigation.
error.codestringYeswithin errorStable error code used to distinguish failures programmatically.
error.messagestringYeswithin errorHuman-readable diagnostic text.
error.requestIdstringYeswithin errorRequest identifier for correlating diagnostics and support investigations.
error.detailsanyNowithin errorOptional structured error context. Its shape is specific to the service failure.
error.loginUrlstringNowithin errorAuthentication URL supplied when a browser login is required.
error.registrationOpenbooleanNowithin errorWhether new account registration is enabled for this deployment.
Example
Example
{
  "error": {
    "code": "platform_balance_insufficient",
    "message": "Top up Platform credits before submitting a Run.",
    "requestId": "req_example"
  }
}

Replace an egress credential configuration

PUT /v1/environments/{environmentId}/egress-credentials/{credentialId}

Requires a personal token for a personal Environment or a token scoped to the owning Project. Secret material is stored only in Sandbox0. Mutations use the Environment lifecycle lock and require a ready Environment; paused Environments are supported. Active work can delay mutations while holding the lifecycle lock. Applied changes affect subsequent outbound connections. Credentials are not inherited by forks and are not restored by Run rollback. Resolver kind is immutable. Set enabled=false to disable injection without deleting the source.

Authentication: Platform API bearer token

Parameters and headers
FieldType and constraintsRequiredDescription
path: environmentIdstring · min length 1YesEnvironment identifier. It must belong to the caller’s account or Project.
path: credentialIdstring · min length 1YesEgress credential identifier within this Environment.

Request example

sh
curl -X PUT \
    "https://api.sandpi.ai/v1/environments/$ENVIRONMENT_ID/egress-credentials/$CREDENTIAL_ID" \
    -H "Authorization: Bearer $SANDPI_API_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
  "name": "GitHub API",
  "resolverKind": "static_headers",
  "projection": {
    "type": "http_headers",
    "headers": [
      {
        "name": "Authorization",
        "valueTemplate": "Bearer {{ .token }}"
      }
    ]
  },
  "rule": {
    "protocol": "https",
    "domains": [
      "api.github.com"
    ],
    "ports": [
      {
        "port": 443
      }
    ],
    "failurePolicy": "fail-closed"
  },
  "enabled": true
}'
Request body · required application/json

Maximum bytes: 2,097,152

Non-secret binding configuration; secret material is supplied separately.

FieldType and constraintsRequiredDescription
namestring · min length 1; max length 80
Validation pattern\S
YesHuman-readable name for this resource.
resolverKindstring · values: "static_headers" | "static_tls_client_certificate" | "static_username_password" | "static_ssh_private_key"YesCredential material resolver. Its kind is immutable after creation and must match the material type.
projectionone of the variants belowYesProjection variant applied at the network boundary. Choose the type matching the configured resolver.
projectionobjectYestype = "http_headers"—
projection.typestring · values: "http_headers"Yestype = "http_headers"Discriminator selecting the configuration or secret-material variant.
projection.headersarray · min 1 items; max 32 itemsYestype = "http_headers"Header definitions or secret header values applied by this configuration.
projection.headers[]objectYeseach array item—
projection.headers[].namestring · min length 1; max length 128
Validation pattern^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$
Yeseach array itemHuman-readable name for this resource.
projection.headers[].valueTemplatestring · min length 1; max length 2048Yeseach array itemProjection template referring to credential variables; do not embed a secret value here.
projectionobjectYestype = "placeholder_substitution"—
projection.typestring · values: "placeholder_substitution"Yestype = "placeholder_substitution"Discriminator selecting the configuration or secret-material variant.
projection.replacementsarray · min 1 items; max 32 itemsYestype = "placeholder_substitution"Placeholder replacement rules applied at the network boundary.
projection.replacements[]objectYeseach array item—
projection.replacements[].placeholderstring · min length 1; max length 512Yeseach array itemLiteral placeholder to replace in the selected request locations.
projection.replacements[].valueTemplatestring · min length 1; max length 2048Yeseach array itemProjection template referring to credential variables; do not embed a secret value here.
projection.replacements[].locationsarray · min 1 items; max 3 itemsYeseach array itemRequest locations where placeholder replacement applies.
projection.replacements[].locations[]string · values: "header" | "query" | "body"Yeseach array item—
projectionobjectYestype = "tls_client_certificate"—
projection.typestring · values: "tls_client_certificate"Yestype = "tls_client_certificate"Discriminator selecting the configuration or secret-material variant.
projectionobjectYestype = "username_password"—
projection.typestring · values: "username_password"Yestype = "username_password"Discriminator selecting the configuration or secret-material variant.
projectionobjectYestype = "ssh_proxy"—
projection.typestring · values: "ssh_proxy"Yestype = "ssh_proxy"Discriminator selecting the configuration or secret-material variant.
projection.upstreamUsernamestring · min length 1; max length 255Yestype = "ssh_proxy"Username used for the upstream SSH connection.
projection.sandboxPublicKeysarray · min 1 items; max 16 itemsYestype = "ssh_proxy"Public keys allowed to use this Sandbox-side SSH proxy binding.
projection.sandboxPublicKeys[]string · min length 1; max length 16384Yeseach array item—
projection.knownHostsarray · min 0 items; max 64 itemsNotype = "ssh_proxy"Known-host entries for upstream SSH host verification.
projection.knownHosts[]string · min length 1; max length 16384Yeseach array item—
ruleobjectYesMatching outbound destinations and resolver failure policy.
rule.protocolstring · values: "http" | "https" | "grpc" | "tls" | "ssh" | "socks5" | "mqtt" | "redis"Yeswithin ruleNetwork protocol to which the binding applies.
rule.domainsarray · min 1 items; max 128 itemsYeswithin ruleDestination domain patterns matched by the credential rule.
rule.domains[]string · min length 1; max length 255Yeseach array itemExact or wildcard domain, e.g. api.example.com or *.example.com; URLs, paths and ports are rejected. Domains are normalized and deduplicated.
rule.portsarray · min 1 items; max 16 itemsYeswithin ruleDestination ports matched by the credential rule.
rule.ports[]objectYeseach array item—
rule.ports[].portinteger · ≥ 1; ≤ 65535Yeseach array itemPort number matched by this destination rule.
rule.ports[].protocolstring · values: "tcp"; default: "tcp"Noeach array itemNetwork protocol to which the binding applies.
rule.failurePolicystring · values: "fail-closed" | "fail-open"; default: "fail-closed"Nowithin ruleBehavior when the network-boundary credential cannot be resolved.
enabledboolean · default: trueNoWhether this configuration is enabled for future use.
Example
Example
{
  "name": "GitHub API",
  "resolverKind": "static_headers",
  "projection": {
    "type": "http_headers",
    "headers": [
      {
        "name": "Authorization",
        "valueTemplate": "Bearer {{ .token }}"
      }
    ]
  },
  "rule": {
    "protocol": "https",
    "domains": [
      "api.github.com"
    ],
    "ports": [
      {
        "port": 443
      }
    ],
    "failurePolicy": "fail-closed"
  },
  "enabled": true
}

Responses

200 OK.
Response body application/json
FieldType and constraintsRequiredDescription
dataobject · extra fields rejectedYesSecret-free configuration and observed source state. Contains neither material nor the internal Sandbox0 source reference.
data.namestring · min length 1; max length 80
Validation pattern\S
Yeswithin dataHuman-readable name for this resource.
data.resolverKindstring · values: "static_headers" | "static_tls_client_certificate" | "static_username_password" | "static_ssh_private_key"Yeswithin dataCredential material resolver. Its kind is immutable after creation and must match the material type.
data.projectionone of the variants belowYeswithin dataProjection variant applied at the network boundary. Choose the type matching the configured resolver.
data.projectionobjectYestype = "http_headers"—
data.projection.typestring · values: "http_headers"Yestype = "http_headers"Discriminator selecting the configuration or secret-material variant.
data.projection.headersarray · min 1 items; max 32 itemsYestype = "http_headers"Header definitions or secret header values applied by this configuration.
data.projection.headers[]objectYeseach array item—
data.projection.headers[].namestring · min length 1; max length 128
Validation pattern^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$
Yeseach array itemHuman-readable name for this resource.
data.projection.headers[].valueTemplatestring · min length 1; max length 2048Yeseach array itemProjection template referring to credential variables; do not embed a secret value here.
data.projectionobjectYestype = "placeholder_substitution"—
data.projection.typestring · values: "placeholder_substitution"Yestype = "placeholder_substitution"Discriminator selecting the configuration or secret-material variant.
data.projection.replacementsarray · min 1 items; max 32 itemsYestype = "placeholder_substitution"Placeholder replacement rules applied at the network boundary.
data.projection.replacements[]objectYeseach array item—
data.projection.replacements[].placeholderstring · min length 1; max length 512Yeseach array itemLiteral placeholder to replace in the selected request locations.
data.projection.replacements[].valueTemplatestring · min length 1; max length 2048Yeseach array itemProjection template referring to credential variables; do not embed a secret value here.
data.projection.replacements[].locationsarray · min 1 items; max 3 itemsYeseach array itemRequest locations where placeholder replacement applies.
data.projection.replacements[].locations[]string · values: "header" | "query" | "body"Yeseach array item—
data.projectionobjectYestype = "tls_client_certificate"—
data.projection.typestring · values: "tls_client_certificate"Yestype = "tls_client_certificate"Discriminator selecting the configuration or secret-material variant.
data.projectionobjectYestype = "username_password"—
data.projection.typestring · values: "username_password"Yestype = "username_password"Discriminator selecting the configuration or secret-material variant.
data.projectionobjectYestype = "ssh_proxy"—
data.projection.typestring · values: "ssh_proxy"Yestype = "ssh_proxy"Discriminator selecting the configuration or secret-material variant.
data.projection.upstreamUsernamestring · min length 1; max length 255Yestype = "ssh_proxy"Username used for the upstream SSH connection.
data.projection.sandboxPublicKeysarray · min 1 items; max 16 itemsYestype = "ssh_proxy"Public keys allowed to use this Sandbox-side SSH proxy binding.
data.projection.sandboxPublicKeys[]string · min length 1; max length 16384Yeseach array item—
data.projection.knownHostsarray · min 0 items; max 64 itemsNotype = "ssh_proxy"Known-host entries for upstream SSH host verification.
data.projection.knownHosts[]string · min length 1; max length 16384Yeseach array item—
data.ruleobjectYeswithin dataMatching outbound destinations and resolver failure policy.
data.rule.protocolstring · values: "http" | "https" | "grpc" | "tls" | "ssh" | "socks5" | "mqtt" | "redis"Yeswithin dataNetwork protocol to which the binding applies.
data.rule.domainsarray · min 1 items; max 128 itemsYeswithin dataDestination domain patterns matched by the credential rule.
data.rule.domains[]string · min length 1; max length 255Yeseach array itemExact or wildcard domain, e.g. api.example.com or *.example.com; URLs, paths and ports are rejected. Domains are normalized and deduplicated.
data.rule.portsarray · min 1 items; max 16 itemsYeswithin dataDestination ports matched by the credential rule.
data.rule.ports[]objectYeseach array item—
data.rule.ports[].portinteger · ≥ 1; ≤ 65535Yeseach array itemPort number matched by this destination rule.
data.rule.ports[].protocolstring · values: "tcp"; default: "tcp"Noeach array itemNetwork protocol to which the binding applies.
data.rule.failurePolicystring · values: "fail-closed" | "fail-open"; default: "fail-closed"Nowithin dataBehavior when the network-boundary credential cannot be resolved.
data.enabledboolean · default: trueYeswithin dataWhether this configuration is enabled for future use.
data.idstring · min length 1Yeswithin dataResource identifier used to read or manage this resource.
data.environmentIdstring · min length 1Yeswithin dataEnvironment identifier. It must belong to the caller’s account or Project.
data.statusstring · values: "provisioning" | "active" | "error" | "deleting"Yeswithin dataCurrent resource state; inspect the allowed values and the operation’s lifecycle notes.
data.currentVersioninteger · ≥ 1Nowithin dataObserved current credential source version.
data.sourceStatusstring · min length 1Nowithin dataObserved credential source state from Sandbox0.
data.errorstring · min length 1Nowithin dataStructured failure information. Inspect the stable code and retain the request ID for investigation.
data.createdAtnumberYeswithin dataCreation time as a Unix timestamp in seconds.
data.updatedAtnumberYeswithin dataLast update time as a Unix timestamp in seconds.
Example
Example
{
  "data": {
    "name": "example",
    "resolverKind": "static_headers",
    "projection": {
      "type": "http_headers",
      "headers": [
        {
          "name": "example",
          "valueTemplate": "example"
        }
      ]
    },
    "rule": {
      "protocol": "http",
      "domains": [
        "example"
      ],
      "ports": [
        {
          "port": 1
        }
      ]
    },
    "enabled": false,
    "id": "example",
    "environmentId": "example",
    "status": "provisioning",
    "createdAt": 0,
    "updatedAt": 0
  }
}
Error responses
default Sandpi error.
Error body application/json

Standard error envelope containing a stable code, diagnostic message and request identity.

FieldType and constraintsRequiredDescription
errorobject · extra fields rejectedYesStructured failure information. Inspect the stable code and retain the request ID for investigation.
error.codestringYeswithin errorStable error code used to distinguish failures programmatically.
error.messagestringYeswithin errorHuman-readable diagnostic text.
error.requestIdstringYeswithin errorRequest identifier for correlating diagnostics and support investigations.
error.detailsanyNowithin errorOptional structured error context. Its shape is specific to the service failure.
error.loginUrlstringNowithin errorAuthentication URL supplied when a browser login is required.
error.registrationOpenbooleanNowithin errorWhether new account registration is enabled for this deployment.
Example
Example
{
  "error": {
    "code": "platform_balance_insufficient",
    "message": "Top up Platform credits before submitting a Run.",
    "requestId": "req_example"
  }
}

Delete a credential

Deletion removes the binding and its source. It does not reauthenticate already established connections.

Delete an Environment egress credential

DELETE /v1/environments/{environmentId}/egress-credentials/{credentialId}

Requires a personal token for a personal Environment or a token scoped to the owning Project. Secret material is stored only in Sandbox0. Mutations use the Environment lifecycle lock and require a ready Environment; paused Environments are supported. Active work can delay mutations while holding the lifecycle lock. Applied changes affect subsequent outbound connections. Credentials are not inherited by forks and are not restored by Run rollback.

Authentication: Platform API bearer token

Parameters and headers
FieldType and constraintsRequiredDescription
path: environmentIdstring · min length 1YesEnvironment identifier. It must belong to the caller’s account or Project.
path: credentialIdstring · min length 1YesEgress credential identifier within this Environment.

Request example

sh
curl -X DELETE \
    "https://api.sandpi.ai/v1/environments/$ENVIRONMENT_ID/egress-credentials/$CREDENTIAL_ID" \
    -H "Authorization: Bearer $SANDPI_API_TOKEN"

No request body.

Responses

204 Deleted.

Empty response body.

Error responses
default Sandpi error.
Error body application/json

Standard error envelope containing a stable code, diagnostic message and request identity.

FieldType and constraintsRequiredDescription
errorobject · extra fields rejectedYesStructured failure information. Inspect the stable code and retain the request ID for investigation.
error.codestringYeswithin errorStable error code used to distinguish failures programmatically.
error.messagestringYeswithin errorHuman-readable diagnostic text.
error.requestIdstringYeswithin errorRequest identifier for correlating diagnostics and support investigations.
error.detailsanyNowithin errorOptional structured error context. Its shape is specific to the service failure.
error.loginUrlstringNowithin errorAuthentication URL supplied when a browser login is required.
error.registrationOpenbooleanNowithin errorWhether new account registration is enabled for this deployment.
Example
Example
{
  "error": {
    "code": "platform_balance_insufficient",
    "message": "Top up Platform credits before submitting a Run.",
    "requestId": "req_example"
  }
}