This guide walks through implementing a webhook server that satisfies the Contextual Access Webhook contract. You can write it in any language — the contract is defined by an OpenAPI 3.0 spec.
OpenAPI spec
The canonical contract is maintained in the ArcadeAI/schemas repository:
Your server needs to expose HTTP POST endpoints for each hook point you want to handle. Endpoint paths are fully configurable in the Dashboard — the defaults are shown below.
Endpoint
Hook point
Required
POST /access
Access Hook
Only if you need tool access control
POST /pre
Pre-Execution Hook
Only if you need tool request validation/modification
POST /post
Post-Execution Hook
Only if you need tool output filtering/modification
You do not need to implement all endpoints. Only implement the ones you configure in the Dashboard.
Pre-Execution Hook
When: Before each .
Request (Arcade sends to your server)
Field
Type
Description
execution_id
string
Correlates request/response across hooks
tool
object
name, toolkit, version, and optional metadata (see Tool Metadata)
inputs
object
Tool inputs (name → value)
context
object
authorization (OAuth per provider), secrets (key names only), metadata, user_id
Response (your server returns)
Field
Type
Required
Description
code
string
Yes
OK, CHECK_FAILED, or RATE_LIMIT_EXCEEDED
error_message
string
No
Shown to the agent when denying
override
object
No
inputs and/or secrets to modify the request
Post-Execution Hook
When: After tool execution.
Request
Field
Type
Description
execution_id
string
Correlates with pre-execution hook
tool
object
name, toolkit, version, and optional metadata (see Tool Metadata)
inputs
object
Tool inputs
success
boolean
Whether the tool call succeeded
output
any
The execution output (any JSON type)
execution_code
string
Status from worker
execution_error
string
Error message from tool call
context
object
Same as pre-execution hook
Response
Field
Type
Required
Description
code
string
Yes
OK, CHECK_FAILED, or RATE_LIMIT_EXCEEDED
error_message
string
No
Shown to the agent when denying
override
object
No
output to replace the response returned to the agent
Access Hook
When: When Arcade needs to know which tools a user can see. Supports batch requests.
Request
Field
Type
Description
user_id
string
User to check
toolkits
object
Map of toolkit name → toolkit info. Each toolkit contains a tools map of tool name → version info arrays. Each version info includes version, requirements, and optional metadata (see Tool Metadata)
Response
Return either an allow list or a deny list (not both):
Field
Type
Description
only
object
If present, only these tools are allowed (deny list ignored)
deny
object
Tools listed here are denied (ignored if only is present)
If you return neither field, the Arcade treats it as “no change”—all tools remain allowed at this hook.
Tool Metadata
Tools can include an optional metadata field with classification, behavioral, and custom information. Webhook servers can use this metadata to make more granular access and filtering decisions.
All metadata fields are optional and omitted from the JSON when empty, so existing webhook servers continue to work without changes.
For the full list of valid service_domains and operations values, see Add Tool Metadata.
Structure
Field
Type
Description
metadata
object | absent
Container for tool metadata. Omitted when the tool has no metadata set.
metadata.classification
object
Classification information.
metadata.classification.service_domains
string[]
Service domains this tool interfaces with (for example, "email", "calendar", "crm").
metadata.behavior
object
Behavioral characteristics.
metadata.behavior.operations
string[]
Operations this tool performs (for example, "read", "create", "update", "delete", "opaque").
metadata.behavior.read_only
boolean
Whether the tool only reads data.
metadata.behavior.destructive
boolean
Whether the tool can delete or irreversibly modify data.
metadata.behavior.idempotent
boolean
Whether repeated calls with the same inputs produce the same result.
metadata.behavior.open_world
boolean
Whether the tool can affect state outside its defined outputs.
metadata.extras
object
Arbitrary additional metadata set by the toolkit author (for example, {"IdP": "entra_id"}).
Webhook servers can use tool metadata to make more granular decisions:
Block destructive operations—Deny tools where metadata.behavior.destructive is true for certain users
Restrict by service domain—Only allow tools in the "email" domain for a particular project
Audit read vs. write—Log or rate-limit tools based on their operations array
Route by IdP—Use metadata.extras.IdP to apply provider-specific policies
Response codes (pre and post)
Code
Meaning
OK
Proceed; optional override is applied
CHECK_FAILED
Deny the operation; error_message is shown to the agent
RATE_LIMIT_EXCEEDED
Deny with rate-limit semantics
Authentication
Arcade sends one of:
Bearer:Authorization: Bearer <token> (token from extension config)
mTLS: Client certificate during TLS handshake; optional CA cert for server verification
Configure the auth method when creating your extension in the Dashboard.
Failure handling and retries
Timeout: Configurable per extension (default 5s); can be overridden per hook. On timeout, the hook’s failure mode applies (Fail closed = block, Fail open = allow).
Retries: Optional at the extension level; only for transient failures (5xx, timeout, connection error). 4xx responses are not retried.
Next steps
API Reference — Interactive Swagger documentation for the full schema
Run an extension — Try the open-source example servers as reference
How Hooks Work — Understand execution order, phases, and failure modes