Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.duckie.ai/llms.txt

Use this file to discover all available pages before exploring further.

Custom Webhooks let you trigger a Duckie agent from any system that can send a JSON POST request. Use them when your source system is not one of Duckie’s built-in deployment channels, or when you need to shape a custom event payload into Duckie runs.

How Custom Webhooks Work

A Custom Webhook deployment has two parts:
PartWhat it controls
Webhook endpointThe generated URL, endpoint name, and request verification method
Payload mappingsHow fields from the incoming JSON payload become the run, messages, and metadata
When Duckie receives a valid request, it checks the deployment’s event filtering, extracts the mapped fields, creates a run, inserts the mapped run messages, and queues the selected agent.

Create a Custom Webhook Deployment

1

Create a deployment

Go to Deploy, click Create Deployment, and choose the agent that should handle the webhook.
2

Choose Custom Webhook

In the trigger selector, choose Custom Webhook.
3

Name the endpoint

Enter an Endpoint Name. This name identifies the webhook endpoint in Duckie.
4

Choose a verification method

Select how Duckie should verify incoming requests.
5

Map the payload

Paste a sample JSON payload, parse the fields, and map the payload into run fields, run messages, and optional metadata.
6

Save and copy the webhook URL

Save the deployment. Duckie shows the generated webhook URL after the endpoint is created.

Webhook URL

After you save the deployment for the first time, Duckie shows a generated URL:
https://app.duckie.ai/api/webhooks/custom/{endpointSlug}
Send JSON POST requests to this URL. Duckie reads the request body as JSON, so non-JSON payloads are rejected.

Verification Methods

Choose a verification method before sending production traffic.
MethodHow it works
HMAC SignatureDuckie computes an HMAC over the raw request body with your signing secret and compares it to a signature header.
Bearer TokenDuckie checks that the configured header value exactly matches the token you entered.
NoneDuckie skips request verification. Use only for local testing or trusted temporary traffic.
For HMAC verification, configure the signature header and algorithm. Duckie supports the algorithms available in the selector, including SHA-256, SHA-1, and SHA-512. For token verification, the default header is X-Webhook-Token. Send the token as the header value:
curl -X POST "https://app.duckie.ai/api/webhooks/custom/{endpointSlug}" \
  -H "Content-Type: application/json" \
  -H "X-Webhook-Token: YOUR_TOKEN" \
  -d '{"id":"evt_123","ticket_id":"T-123","title":"Billing question","message":"Can you help me update my invoice?"}'

Payload Mappings

Payload mappings tell Duckie how to turn your JSON payload into a run. Most mapping fields accept either:
Mapping typeExample
JSONPath$.ticket.id
TemplateTicket {{ticket.id}}: {{ticket.subject}}
JSONPath reads a value from the payload. Templates combine literal text with dot-path placeholders from the payload.

Parse a Sample Payload

Paste a sample JSON payload into Sample JSON Payload and click Parse Fields. Duckie discovers scalar fields, suggests common mappings such as IDs and messages, and makes discovered fields available in mapping dropdowns. The parser accepts normal JSON, fenced JSON snippets, and common pasted object-literal formatting such as single quotes, unquoted keys, and trailing commas.

Run Fields

Run fields are required fields written to the run.
FieldRequiredDescription
Event IDYesUnique ID for this webhook event.
Ticket IDYesStable ID for the customer issue, conversation, ticket, or object.
Ticket TitleYesShort title shown in run history.
Ticket URLNoLink back to the source system.
Source Message IDNoSource message ID used for tracking. If omitted, Duckie uses the mapped Event ID.
Example mappings:
{
  "event_id": "$.event.id",
  "ticket_id": "$.ticket.id",
  "ticket_title": "Ticket {{ticket.id}}: {{ticket.subject}}",
  "ticket_url": "https://example.com/tickets/{{ticket.id}}",
  "source_message_id": "$.message.id"
}

Run Messages

Run messages provide the conversation content the agent should respond to. Use Single message when each webhook payload contains one new message:
FieldRequiredDescription
Message BodyYesThe text the agent should process.
RoleNoFixed role or a role mapped from the payload. Defaults to customer.
User NameNoName shown for the message author. Defaults to Customer.
Source Message IDNoMessage ID from the source system.
TimestampNoMessage timestamp from the source system.
Use Conversation array when the payload contains an array of messages or comments. Set Array Path to the array, then map message fields relative to each item in that array. Example payload:
{
  "event": { "id": "evt_123", "type": "ticket.created" },
  "ticket": { "id": "T-123", "subject": "Billing question" },
  "comments": [
    {
      "id": "c_1",
      "body": "Can you help me update my invoice?",
      "sender_type": "end_user",
      "sender_name": "Alice",
      "created_at": "2026-05-29T16:30:00Z"
    },
    {
      "id": "c_2",
      "body": "Sure, I can help.",
      "sender_type": "admin",
      "sender_name": "Support",
      "created_at": "2026-05-29T16:31:00Z"
    }
  ]
}
Example conversation array mappings:
FieldMapping
Array Path$.comments
Message Body$.body
Role$.sender_type
User Name$.sender_name
Source Message ID$.id
Timestamp$.created_at
When role is mapped from the payload, Duckie normalizes common values:
Payload valuesDuckie role
customer, user, end_user, contactCustomer
agent, admin, support, teammate, operatorAgent
duckie, assistant, botDuckie
If the mapped role is missing or unrecognized, Duckie uses the fallback role selected in the deployment.

Run Metadata

Run Metadata stores optional fields on the run for context. Use it for source-specific attributes such as account ID, priority, product area, locale, plan, or tags. You can add fields manually, or click Add Parsed Fields after parsing a sample payload.
Do not send secrets, credentials, or unnecessary sensitive fields in webhook payloads. Duckie stores the raw payload and mapped metadata with the run.

Event Filtering

Event filtering lets one webhook endpoint receive multiple event types while a deployment only processes the ones you allow.
FieldDescription
Event Type PathJSONPath to the field that identifies the event type, such as $.event.type.
Allowed Event TypesComma-separated list of exact event type values, such as ticket.created, ticket.updated.
If you leave the allowed event types blank, Duckie accepts all event types for that deployment.

Request Outcomes

Duckie validates the request before it starts asynchronous processing.
OutcomeMeaning
200 with { "ok": true }The request was accepted and processing continues asynchronously.
400The request body was not valid JSON.
401Request verification failed.
404The webhook endpoint slug was not found.
429The endpoint rate limit was exceeded.
If filtering does not match, Duckie accepts the request but does not create a run for that deployment. If required mappings resolve to empty values, Duckie does not create a run for that deployment.

Test Before Going Live

  1. Create the deployment in Testing mode.
  2. Send a representative sample payload to the webhook URL.
  3. Open Analyze > Runs and review the created run.
  4. Confirm the title, ticket ID, messages, role mapping, and metadata look correct.
  5. Switch to Live mode after the mapping is validated.

Troubleshooting

ProblemWhat to check
No run appearsConfirm the deployment is active and the event type filter matches the payload.
Mapping failureCheck that required mappings resolve to non-empty values: Event ID, Ticket ID, Ticket Title, and Message Body.
Wrong message roleCheck the role mapping and fallback role.
401 UnauthorizedConfirm the signature or token header name and secret match the deployment.
400 Invalid JSON payloadSend a JSON request body with Content-Type: application/json.

Next Steps

Create Deployment

Set up a deployment

Deployment Modes

Test before live traffic

Runs

Review webhook-triggered runs