Skip to main content
POST
Create an outbound destination

Authorizations

hookie_session
string
cookie
required

The console's sealed session cookie, set by WorkOS AuthKit. Mutating requests also require the X-Requested-With CSRF header.

Headers

Idempotency-Key
string

Makes a POST safe to retry for 24 hours: the same key, credential, path and body returns the stored response (Idempotent-Replayed: true) instead of running again. 422 if the key was used for a different request; 409 while the first is in flight.

Required string length: 1 - 255

Path Parameters

project_id
string
required

Project id (UUID) belonging to the caller workspace.

Body

application/json
name
string
required
Required string length: 1 - 80
url
string<uri>

webhook only, and required for it: an absolute https URL. http and relative URLs are rejected. Normalized through the URL parser before storing. Refused for Slack, S3, SQS and Pub/Sub, whose address is their config. A Slack incoming-webhook URL (hooks.slack.com) is refused here (400): it is a credential, stored encrypted only as a slack destination's config.webhook_url (#313).

datasetFilter
string[] | null

CAMELCASE on create - the create validator reads datasetFilter, while PATCH reads dataset_filter. Omitted or null means every dataset.

Pattern: ^[A-Za-z][A-Za-z0-9_]{0,62}$
enabled
boolean
default:true

Anything other than the literal false is treated as true.

headers
object[] | null

Custom headers sent with every delivery (DLV-7). Replaces the whole list; null clears it. Sent before Hookie's own headers, which always win. webhook only: refused for Slack, S3, SQS and Pub/Sub.

Maximum array length: 20
auth
object

Authentication (DLV-7), stored AES-256-GCM encrypted and never returned. null or {type:'none'} removes it. On PATCH, the same type with no credential keeps the stored credential (so an API key's header can be renamed without re-entering it). webhook only: refused for Slack, S3, SQS and Pub/Sub (S3 and SQS are authenticated by SigV4 from config, Pub/Sub by its service-account key).

transform
object

Payload transformation (DLV-7): data, never code. null sends Hookie's envelope {id, dataset, received_at, data}. A template is any JSON value whose string leaves may hold {{path}} placeholders, read from the envelope with the mapping engine's dotted-path reader ({{dataset}}, {{data.customer.email}}, {{$payload}} for the whole envelope); a string that is exactly one placeholder keeps the value's type, an embedded one becomes text (objects as JSON, missing as empty). A mapping builds a flat object, one key per {path, key}, as routing rules do ($submission.id and $submission.received_at are the record's id and time). At most 16 KB serialised. The body is always sent as application/json and Hookie-Signature is computed over it as sent.

alert_url
string<uri> | null

OBS-2: a public https URL (no credentials, no private or internal host) that receives one signed POST when Hookie switches this destination off for failing. Body: {type:'destination.disabled', occurred_at, destination:{id,name,url,project_id}, reason, consecutive_dead, failing_since, last_failure}; headers Hookie-Signature (the destination's signing secret, same scheme as a delivery) and Hookie-Alert: destination.disabled. Sent once, never retried, redirects not followed. null or empty removes it.

type
enum<string>
default:webhook

How a delivery leaves Hookie (DLV-13, #313, #322). webhook: the signed HTTPS POST to url (Hookie-Signature and the Standard Webhooks headers), unchanged. slack: a POST to a Slack incoming webhook with a readable message ({text, blocks}: dataset, event id, received time and the payload as pretty JSON truncated to 2,500 characters), or the destination's own template when it has a transform; it carries only Content-Type and User-Agent, no signature headers. s3: one object per event PUT to an S3-compatible bucket (AWS S3, Cloudflare R2, GCS interoperability, MinIO) at {prefix}{dataset}/{yyyy}/{mm}/{dd}/{event id}.json (dated by when the event was received, UTC), Content-Type application/json, x-amz-meta-hookie-event-id and x-amz-meta-hookie-dataset, signed with AWS SigV4; the key is the event's, so a retry or replay overwrites the same object. sqs (#322): one SendMessage per event to an Amazon SQS queue over the JSON protocol (POST to the queue URL's host, X-Amz-Target AmazonSQS.SendMessage, Content-Type application/x-amz-json-1.0, signed with AWS SigV4 for service sqs); MessageBody is the delivery body, and the message attributes event_id and dataset (String) carry the event's id and dataset. A FIFO queue (name ending .fifo) also gets MessageDeduplicationId = the event id and MessageGroupId = the dataset, so a retry or replay inside SQS's five-minute window is one message. A message over SQS's 1 MiB limit (1,048,576 bytes, body and attributes together) fails at once and is not retried. SQS's error code decides a retry: throttling (ThrottlingException, RequestThrottled, KmsThrottled) and SQS-side failures are retried, refusals (AccessDenied, QueueDoesNotExist, InvalidParameterValue, InvalidMessageContents, signature and KMS errors) are not; the code is added to the delivery's error. pubsub (#322): one publish per event, POST https://pubsub.googleapis.com/v1/projects/{project}/topics/{topic}:publish with {messages: [{data: base64(body), attributes: {event_id, dataset}}]}, authorised by an OAuth access token minted from the destination's service-account key (an RS256 JWT exchanged at https://oauth2.googleapis.com/token) and cached until 60 s before it expires, never minted per delivery. A 401 drops the cached token and is retried; a key Google refuses fails the delivery without retrying. Pub/Sub has no deduplication on publish: receivers dedupe on the event_id attribute. All of them share retries with backoff, pacing, the delivery allowance and holds, replay and the delivery log. The type is fixed at creation.

Available options:
webhook,
slack,
s3,
sqs,
pubsub
config
Slack · object

A typed destination's settings (DLV-13, #313, #322). Required on create for those types; refused for a webhook. Credentials are stored AES-256-GCM encrypted and never returned, exported or logged. On PATCH, a credential that is not sent keeps the stored one, and settings that are not sent keep their stored values. On create, the Slack variant needs webhook_url.

Response

Created. signing_secret is returned here in plaintext; it is stored AES-256-GCM encrypted and can be read back later via the secret endpoint. Every type gets a signing secret: a webhook's deliveries are signed with it, and for Slack, S3, SQS and Pub/Sub it signs only the destination's alert_url notices.

id
string
required
signing_secret
string
required

whsec_ followed by 48 hex characters.

warning
string

Present when the destination's URL is one of this project's own endpoint URLs or ingest keys and its dataset filter admits the dataset that writes to, so every event would loop back (stopped after 8 hops by Hookie-Hop). The destination is still created.

destination
object

The created destination, as GET by id returns it (#201).