Skip to main content
For the shared destination list and source selection, see Drains. Select a project and open Project Settings → Drains. Team owners and admins view and manage log and analytics destinations here. Members see drain metadata with destinations hidden. Add drain → Logs forwards operational records; Add drain → Analytics sends hourly number analytics. In Logs, the export menu also opens log drains and trace sampling. A drain forwards new API-request, session-state, and webhook-delivery records after you enable it. It does not backfill earlier logs or include Settings audit actions, message bodies, pairing data, request headers, or credentials.

Add a destination

  1. Open Project Settings → Drains, choose Add drain → Logs.
  2. Use Custom endpoint, enter a name, and enter a public HTTPS destination URL.
  3. Choose JSON or NDJSON encoding. A signing secret is generated for the new drain; copy it to your receiver. You can replace it with a secret of 16–256 characters, regenerate it, or clear it for unsigned delivery.
  4. Optionally enable Custom headers and add names and values.
  5. Choose Add drain to save.
A project supports up to five drains across logs and analytics. The list shows whether each drain is enabled or paused, pending and failed delivery counts, and its latest recorded HTTP status or error. Pause, resume, or delete a drain from that list. Deleting a drain removes its queued deliveries. Saved custom header values and signing secrets are not returned by the configuration view. Team members see drain metadata; destination URLs and header names are visible only to owners and admins. Source, number scope, window and encoding are fixed when a drain is created; create a new drain to change them. Native integrations is marked Coming soon and is unavailable. Destinations must resolve to public addresses. Redirects, URL credentials, fragments, and reserved transport or signature headers are rejected.

Sample forwarded records

Open Trace sampling to add up to 20 rules. Each rule sets a percentage from 0 to 100 and optionally matches a log type, event kind, or supported identifier and value. Rules run in their displayed order; the first matching rule applies. Records without a matching rule are forwarded at 100%. Sampling groups records by request ID or event ID when one exists. Repeated records with the same identity receive the same deterministic sampling decision for a given rate. A webhook’s delivery updates share its event identity. This control samples operational records sent to drains; it does not change stored logs, Settings audit history, or message retention.

Receive deliveries

With JSON, your endpoint receives an HTTPS POST with Content-Type: application/json. The envelope contains a stable delivery ID and one operational record:
With NDJSON, the content type is application/x-ndjson. Each line contains one envelope with version, deliveryId and a single record object. A delivery contains one line and ends with a newline; line breaks inside strings remain escaped. Logs and analytics both support this encoding.
API records include requestId and traceId. traceId is the request’s W3C trace ID; when the request sent a valid traceparent header, it is the caller’s trace ID. Use it to join forwarded logs to your own traces. Use the Idempotency-Key header, which matches deliveryId, to deduplicate retries. A 2xx response completes a delivery. Other responses and connection failures retry after one minute, five minutes, 15 minutes, one hour, and six hours, for at most six attempts and no later than 24 hours after the record was queued. Delivery is at least once: acknowledge only after your endpoint has durably accepted the record. Retained delivery diagnostics expire after seven days.

Verify signatures

Every request includes X-Polymorfa-Timestamp in Unix seconds. With a signing secret configured, X-Polymorfa-Signature contains sha256= followed by an HMAC-SHA256 hex digest. For NDJSON, include the trailing newline. Compute the HMAC using your signing secret over these exact bytes:
Compare signatures in constant time and reject stale timestamps. Verify the original request bytes before parsing or reserializing JSON. Retries preserve the delivery ID and create a fresh timestamp and signature. Pausing stops new deliveries and new queue entries for that drain; an in-flight request can finish. Resuming permits eligible queued deliveries to continue. If support disables forwarding for the project, sampling and drain settings remain visible, while new queue entries and delivery claims stop. Stored logs and audit history remain available.