Skip to main content
A webhook tells your server when something happens in your workspace, so you stop polling. Yungle signs every request, retries failed deliveries for about two days, and can keep events for you to pull when you have no public URL.

Prerequisites

  • An API key with webhooks:write (and webhooks:read to list endpoints), or access to Settings → Webhooks in the dashboard.
  • A public https URL that accepts POST requests. Without one, use pull mode.
  • Any plan. The free plan includes one endpoint and the transfer events; paid plans include up to ten endpoints and every event.

Events

Subscribing a free workspace to a paid event returns 402 upgrade_required.

What a delivery looks like

Each delivery is a POST with a JSON body and these headers: Every body has the same envelope: id, type, createdAt and data.
What data holds for each type:
An uploader’s name, email and message in request.submitted and collection.file_uploaded are whatever they typed. Treat them as untrusted text.
When a transfer expires or is revoked, Yungle deletes its earlier transfer.ready, transfer.expiring and transfer.downloaded events, because they carry its title and recipient addresses. That is why transfer.expired carries only the id.

Set up an endpoint

1

Create the endpoint

Give it a URL and the events you want. The response includes the signing secret, and this is the only time you see it. To get a new one later, rotate it.
Store the secret where your receiver can read it, for example as YUNGLE_WEBHOOK_SECRET.
2

Verify the signature

Check every request before you trust it. v1 is the hex HMAC-SHA256, keyed with your endpoint’s secret, of the timestamp t, a dot, and the raw request body. Reject a timestamp more than five minutes from now, and compare in constant time.Both SDKs ship a helper that does exactly this:
Without an SDK, the check is a few lines:
Parse the JSON only after verifying, from the exact bytes you received. Re-serializing a parsed body changes whitespace and key order, and the signature no longer matches.
3

Answer with a 2xx within 10 seconds

Return any 2xx status as soon as the signature checks out, then do the slow work. Any other status, a redirect, or no answer within 10 seconds counts as a failed delivery and is retried.
4

Send a test event

Ask for a webhook.test event to confirm the whole path works.
Your receiver gets a body with "type": "webhook.test" and data.message set to a short sentence.

Retries and ordering

  • Retries. A failed delivery is retried after 1, 5 and 30 minutes, then after 2, 6, 12 and 24 hours: eight attempts over about 45 hours.
  • Pausing. When five deliveries in a row use up all their retries, Yungle pauses the endpoint and emails the workspace owner once. Turn it back on with PATCH /webhooks/{id} and {"enabled": true}, or in the dashboard. You can also pause an endpoint yourself with {"enabled": false}.
  • At least once. The same event can arrive more than once. Deduplicate on the body’s id (or the Yungle-Event-Id header), which stays the same through every retry and redelivery.
  • No ordering. A retry can arrive after a later event. Use createdAt if order matters to you.
  • Redelivery. GET /webhooks/{id}/deliveries lists recent attempts with their status code and error. POST /webhooks/{id}/deliveries/{deliveryId}/retry sends one again with the same event id and body.
  • Rotating the secret. POST /webhooks/{id}/rotate-secret returns a new secret and replaces the old one.

Pull events instead

Create an endpoint with "url": null and Yungle keeps its events for 30 days for you to read. Use this from a cron job, a machine behind a firewall, or anywhere a public URL is more trouble than it is worth. Reading consumes nothing, so keep your own cursor. Pass the last nextCursor you saw; it comes back even when nothing is new, so you always have somewhere to resume from.

Where a webhook can be sent

Only to the public internet. The URL must use https. Every delivery resolves the host and refuses private, loopback, link-local and reserved addresses in the same step that connects, so a hostname cannot pass the check and then point somewhere else. Redirects are not followed.

Example: post to Slack when a client downloads

This receiver posts a message to a Slack channel each time someone downloads one of your transfers. It uses node:http and the SDK’s verifyWebhook.
1

Create a Slack incoming webhook

In Slack, add an incoming webhook to the channel and copy its URL.
2

Write the receiver

slack-on-download.mjs
It verifies before it parses, answers before it calls Slack so a slow Slack never counts as a failed delivery, and remembers event ids so a retry does not post twice. One visit is one event, so the channel gets one message per download, not one per file.
3

Try it locally with the CLI

Run the receiver, then let the CLI forward real events to it. You need no public URL.
The CLI prints a signing secret for the session. Start the receiver with it:
Send yourself a transfer and download it. The Slack message follows within seconds.
yungle webhooks listen creates a pull endpoint of its own, and that counts towards your endpoint limit. On the free plan, which has one endpoint, remove it in Settings → Webhooks before you add the real one. It also needs an API key with webhooks:write (yungle login --key); a browser sign-in cannot add endpoints.
4

Deploy and subscribe

Deploy the receiver at a public https URL, then create an endpoint for it subscribed to transfer.downloaded. Start the deployed receiver with that endpoint’s secret.

Next steps

Send a transfer

Create the transfers whose events you are now receiving.

Receive files

Hear about each upload request submission with request.submitted.

SDKs

Webhook methods and verification helpers in JavaScript and Python.

API reference

Every webhook endpoint, with its full schema.