Create a tunnel
⚠️
Preview — this feature is being built; the design below is the spec.
POST https://app.syntic.ai/v1/tunnelsCreate a tunnel so the MCP connector and agents can reach an MCP server inside your private network. You run the small syntic-tunnel connector next to the server; it dials out to Syntic over TLS on port 443, so no inbound firewall rule or public address is needed. The response holds the connector token, shown only once.
For how this fits into a full workflow, see MCP tunnels.
Headers
| Header | Required | Value |
|---|---|---|
Authorization | Yes | Bearer <key>: a private inference key (sk_live_...). See Authentication. |
syntic-beta | Yes, while in preview | mcp-tunnels-2026-12-01. Without it the call fails with 400 beta_required. See Versioning. |
Content-Type | Yes | application/json |
Idempotency-Key | No | Up to 255 characters. Retrying with the same key within 24 hours returns the first result instead of acting twice. See Idempotency. |
Body parameters
| Parameter | Type | Required | Notes |
|---|---|---|---|
name | string | Yes | 1 to 64 characters, unique in the workspace. |
allowed_targets | array of strings | Yes | 1 to 20 URLs (http or https) the connector may forward to. |
auth_mode | string | No | token (default) or mtls. |
description | string | No | Up to 200 characters. |
Response
201 Created, Content-Type: application/json
{
"id": "tnl_01JCE4G6J8L0N2Q4S6U8",
"type": "tunnel",
"name": "erp-onprem",
"description": "On-prem ERP MCP server",
"workspace_id": "wrkspc_01JC0A2C4E6G8J0L2N4Q",
"allowed_targets": [
"http://erp-mcp.internal:8080/mcp"
],
"auth_mode": "token",
"status": "disconnected",
"connections": {
"active": 0,
"last_seen_at": null
},
"region": "eu",
"created_at": "2026-10-28T09:00:00Z",
"updated_at": "2026-10-28T09:00:00Z",
"connector_token": "stn_live_9QxF…redacted"
}| Field | Type | Description |
|---|---|---|
id | string | Starts with tnl_. Use it as tunnel_id on an MCP server entry. |
allowed_targets | array | The only URLs inside your network the connector will forward to. Anything else is refused by the connector itself. |
auth_mode | string | How connectors prove who they are: token (connector token) or mtls (client certificate from this tunnel’s certificates). |
status | string | connected when at least one connector is online, disconnected otherwise, disabled when turned off. |
connections | object | How many connector instances are online and when one last checked in. |
connector_token | string | Starts with stn_. Pass it to the connector as SYNTIC_TUNNEL_TOKEN. Returned only here and by rotate. |
Examples
curl -sS "https://app.syntic.ai/v1/tunnels" \
-H "Authorization: Bearer $SYNTIC_API_KEY" \
-H "syntic-beta: mcp-tunnels-2026-12-01" \
-H "Idempotency-Key: 8d6f0c1e-4b2a-4a57-9f0e-2f1d3c4b5a69" \
-H "Content-Type: application/json" \
-d '{
"name": "erp-onprem",
"description": "On-prem ERP MCP server",
"allowed_targets": [
"http://erp-mcp.internal:8080/mcp"
]
}'Errors
Errors use the error envelope and carry a request_id. Codes specific to this operation:
| Status | type | code | When |
|---|---|---|---|
| 400 | invalid_request_error | beta_required | The syntic-beta header is missing. |
| 409 | conflict_error | name_taken | Another tunnel in the workspace has this name. |
| 409 | conflict_error | tunnel_limit_reached | The workspace already has 25 tunnels. |
| 401 | authentication_error | invalid_api_key | The key is missing, unknown, revoked or expired. |
| 429 | rate_limit_error | rate_limited | Too many requests; wait for Retry-After. See Rate-limit headers. |
Was this page helpful?