Skip to content

Proxy hooks intercept container traffic before it reaches the real service. Each container has a per-service list of hooks; within a service, hooks are evaluated in position order and the first matching hook wins. All destructive write operations require an If-Match precondition header to prevent lost-update races against concurrent editors.

A hook describes a traffic match and the script that runs when a request matches.

id

string — 26-character Crockford base32 ULID (lowercase). Assigned by the server on create.

position

integer (min 0) — 0-indexed position in the service array.

match

object — Request matcher.

  • method: string or string[] — one of *, GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS.
  • path: string (max length 257).
  • headers: object<string, string> — header presence/value requirements.

script

object — Script reference.

  • subdomain: string (optional).
  • execId: string (optional).
  • path: stringrequired, the script path.

timeout

integer (1–30000) — Execution timeout in milliseconds.

applies_to

object — Scoping.

  • groups: string[] (min 1) — group identifiers this hook applies to.

Returns all hooks for the given container, grouped by service, along with the current file_version and etag.

NameInTypeRequiredDescription
idpathstringYesContainer ID
{
"statusCode": 200,
"message": "Proxy hooks listed successfully",
"data": {
"hooks": {
"my-service": [
{
"id": "01h2x9z8k7v6c5b4n3m2q1p0r9",
"position": 0,
"match": {
"method": "GET",
"path": "/api/v1/users",
"headers": { "x-api-version": "2" }
},
"script": {
"subdomain": "auth-mock",
"execId": "01h2x9z8k7v6c5b4n3m2q1p0r8",
"path": "/hooks/redirect.js"
},
"timeout": 5000,
"applies_to": {
"groups": ["group_alpha"]
}
}
],
"billing": [
{
"id": "01h2x9z8k7v6c5b4n3m2q1p0t0",
"position": 0,
"match": {
"method": "POST",
"path": "/invoices"
},
"script": {
"path": "/hooks/invoice-stub.js"
},
"timeout": 2000
}
]
},
"file_version": 42,
"etag": "file:v42"
}
}
const { data } = await client.api.proxyHooks.listContainerProxyHooks({
id: "container_01h2x9z8k7v6c5b4n3m2q1p0r9"
});

GET /api/v1/containers/{id}/proxy/hooks/{service}

Section titled “GET /api/v1/containers/{id}/proxy/hooks/{service}”

Returns the ordered hook array for a single service. First-match-wins within this list.

NameInTypeRequiredDescription
idpathstringYesContainer ID
servicepathstringYesService name
{
"statusCode": 200,
"message": "Service hooks listed successfully",
"data": {
"service": "my-service",
"hooks": [
{
"id": "01h2x9z8k7v6c5b4n3m2q1p0r9",
"position": 0,
"match": {
"method": "GET",
"path": "/api/v1/users",
"headers": { "x-api-version": "2" }
},
"script": {
"subdomain": "auth-mock",
"execId": "01h2x9z8k7v6c5b4n3m2q1p0r8",
"path": "/hooks/redirect.js"
},
"timeout": 5000,
"applies_to": {
"groups": ["group_alpha"]
}
}
],
"file_version": 42,
"etag": "file:v42"
}
}
const { data } = await client.api.proxyHooks.listContainerProxyServiceHooks({
id: "container_01h2x9z8k7v6c5b4n3m2q1p0r9",
service: "my-service"
});

GET /api/v1/containers/{id}/proxy/hooks/{service}/{hookId}

Section titled “GET /api/v1/containers/{id}/proxy/hooks/{service}/{hookId}”

Returns a single hook by id.

NameInTypeRequiredDescription
idpathstringYesContainer ID
servicepathstringYesService name
hookIdpathstringYes26-char Crockford base32 ULID (lowercase)
{
"statusCode": 200,
"message": "Hook retrieved successfully",
"data": {
"hook": {
"id": "01h2x9z8k7v6c5b4n3m2q1p0r9",
"position": 0,
"match": {
"method": "GET",
"path": "/api/v1/users",
"headers": { "x-api-version": "2" }
},
"script": {
"subdomain": "auth-mock",
"execId": "01h2x9z8k7v6c5b4n3m2q1p0r8",
"path": "/hooks/redirect.js"
},
"timeout": 5000,
"applies_to": {
"groups": ["group_alpha"]
}
},
"file_version": 42,
"etag": "file:v42"
}
}
const { data } = await client.api.proxyHooks.getContainerProxyHook({
id: "container_01h2x9z8k7v6c5b4n3m2q1p0r9",
service: "my-service",
hookId: "01h2x9z8k7v6c5b4n3m2q1p0r9"
});

POST /api/v1/containers/{id}/proxy/hooks/{service}

Section titled “POST /api/v1/containers/{id}/proxy/hooks/{service}”

Create a new hook under a service. Requires If-Match: file:v{N} header. Omit position to append; include it to insert at a specific 0-indexed position.

NameInTypeRequiredDescription
idpathstringYesContainer ID
servicepathstringYesService name
if-matchheaderstringNofile:v{N} ETag precondition
NameTypeRequiredDescription
matchobjectYesRequest matcher (method, path, headers).
scriptobjectYesScript reference. path is required inside.
timeoutintegerNoExecution timeout in milliseconds (1–30000).
applies_toobjectNoScoping via groups (array, min 1).
positionintegerNo0-indexed insertion position. Omit to append.
{
"match": {
"method": "POST",
"path": "/api/v1/orders",
"headers": { "content-type": "application/json" }
},
"script": {
"subdomain": "orders-mock",
"execId": "01h2x9z8k7v6c5b4n3m2q1p0r8",
"path": "/hooks/order-redirect.js"
},
"timeout": 3000,
"applies_to": {
"groups": ["group_alpha", "group_beta"]
},
"position": 0
}
{
"statusCode": 201,
"message": "Hook created successfully",
"data": {
"hook": {
"id": "01h2x9z8k7v6c5b4n3m2q1p0r9",
"position": 0,
"match": {
"method": "POST",
"path": "/api/v1/orders",
"headers": { "content-type": "application/json" }
},
"script": {
"subdomain": "orders-mock",
"execId": "01h2x9z8k7v6c5b4n3m2q1p0r8",
"path": "/hooks/order-redirect.js"
},
"timeout": 3000,
"applies_to": {
"groups": ["group_alpha", "group_beta"]
}
},
"file_version": 43,
"etag": "file:v43"
}
}
const { data } = await client.api.proxyHooks.addContainerProxyHook({
id: "container_01h2x9z8k7v6c5b4n3m2q1p0r9",
service: "my-service",
"if-match": "file:v42",
data: {
match: {
method: "POST",
path: "/api/v1/orders",
headers: { "content-type": "application/json" }
},
script: {
subdomain: "orders-mock",
execId: "01h2x9z8k7v6c5b4n3m2q1p0r8",
path: "/hooks/order-redirect.js"
},
timeout: 3000,
applies_to: { groups: ["group_alpha", "group_beta"] },
position: 0
}
});

PUT /api/v1/containers/{id}/proxy/hooks/{service}/{hookId}

Section titled “PUT /api/v1/containers/{id}/proxy/hooks/{service}/{hookId}”

Full-replace a hook, preserving its id and position. Requires If-Match. This operation is also reachable via PATCH on the same path; the SDK method below issues PUT.

NameInTypeRequiredDescription
idpathstringYesContainer ID
servicepathstringYesService name
hookIdpathstringYes26-char Crockford base32 ULID (lowercase)
if-matchheaderstringNofile:v{N} ETag precondition
NameTypeRequiredDescription
matchobjectYesRequest matcher (method, path, headers).
scriptobjectYesScript reference. path is required inside.
timeoutintegerNoExecution timeout in milliseconds (1–30000).
applies_toobjectNoScoping via groups (array, min 1).
positionintegerNo0-indexed insertion position (POST only).
{
"match": {
"method": "GET",
"path": "/api/v1/users",
"headers": { "x-api-version": "2" }
},
"script": {
"subdomain": "auth-mock",
"execId": "01h2x9z8k7v6c5b4n3m2q1p0r8",
"path": "/hooks/redirect-v2.js"
},
"timeout": 7500,
"applies_to": {
"groups": ["group_alpha"]
}
}
{
"statusCode": 200,
"message": "Hook updated successfully",
"data": {
"hook": {
"id": "01h2x9z8k7v6c5b4n3m2q1p0r9",
"position": 0,
"match": {
"method": "GET",
"path": "/api/v1/users",
"headers": { "x-api-version": "2" }
},
"script": {
"subdomain": "auth-mock",
"execId": "01h2x9z8k7v6c5b4n3m2q1p0r8",
"path": "/hooks/redirect-v2.js"
},
"timeout": 7500,
"applies_to": {
"groups": ["group_alpha"]
}
},
"file_version": 44,
"etag": "file:v44"
}
}
const { data } = await client.api.proxyHooks.updateContainerProxyHook({
id: "container_01h2x9z8k7v6c5b4n3m2q1p0r9",
service: "my-service",
hookId: "01h2x9z8k7v6c5b4n3m2q1p0r9",
"if-match": "file:v42",
data: {
match: {
method: "GET",
path: "/api/v1/users",
headers: { "x-api-version": "2" }
},
script: {
subdomain: "auth-mock",
execId: "01h2x9z8k7v6c5b4n3m2q1p0r8",
path: "/hooks/redirect-v2.js"
},
timeout: 7500,
applies_to: { groups: ["group_alpha"] }
}
});

PATCH /api/v1/containers/{id}/proxy/hooks/{service}/{hookId}/position

Section titled “PATCH /api/v1/containers/{id}/proxy/hooks/{service}/{hookId}/position”

Atomically move a hook to a new 0-indexed position within its service. Body: { position: N }. Requires If-Match.

NameInTypeRequiredDescription
idpathstringYesContainer ID
servicepathstringYesService name
hookIdpathstringYes26-char Crockford base32 ULID (lowercase)
if-matchheaderstringNofile:v{N} ETag precondition
NameTypeRequiredDescription
positionintegerYes0-indexed target position (min 0).
{
"position": 2
}
{
"statusCode": 200,
"message": "Hook moved successfully",
"data": {
"hook": {
"id": "01h2x9z8k7v6c5b4n3m2q1p0r9",
"position": 2,
"match": {
"method": "GET",
"path": "/api/v1/users"
},
"script": {
"path": "/hooks/redirect.js"
},
"timeout": 5000
},
"file_version": 45,
"etag": "file:v45"
}
}
const { data } = await client.api.proxyHooks.moveContainerProxyHook({
id: "container_01h2x9z8k7v6c5b4n3m2q1p0r9",
service: "my-service",
hookId: "01h2x9z8k7v6c5b4n3m2q1p0r9",
"if-match": "file:v44",
data: { position: 2 }
});

DELETE /api/v1/containers/{id}/proxy/hooks/{service}

Section titled “DELETE /api/v1/containers/{id}/proxy/hooks/{service}”

Remove every hook registered under a service. Requires If-Match.

NameInTypeRequiredDescription
idpathstringYesContainer ID
servicepathstringYesService name
if-matchheaderstringNofile:v{N} ETag precondition
{
"statusCode": 200,
"message": "Service hooks cleared",
"data": {
"removed": 3,
"file_version": 46,
"etag": "file:v46"
}
}
const { data } = await client.api.proxyHooks.clearContainerProxyServiceHooks({
id: "container_01h2x9z8k7v6c5b4n3m2q1p0r9",
service: "my-service",
"if-match": "file:v45"
});

DELETE /api/v1/containers/{id}/proxy/hooks/{service}/{hookId}

Section titled “DELETE /api/v1/containers/{id}/proxy/hooks/{service}/{hookId}”

Delete a single hook. Requires If-Match.

NameInTypeRequiredDescription
idpathstringYesContainer ID
servicepathstringYesService name
hookIdpathstringYes26-char Crockford base32 ULID (lowercase)
if-matchheaderstringNofile:v{N} ETag precondition
{
"statusCode": 200,
"message": "Hook removed",
"data": {
"file_version": 47,
"etag": "file:v47"
}
}
const { data } = await client.api.proxyHooks.removeContainerProxyHook({
id: "container_01h2x9z8k7v6c5b4n3m2q1p0r9",
service: "my-service",
hookId: "01h2x9z8k7v6c5b4n3m2q1p0r9",
"if-match": "file:v46"
});