Table of contents
Webhooks provide real-time updates about your prediction. Specify an endpoint when you create a prediction, and Replicate will send HTTP POST requests to that URL when the prediction is created, updated, and finished.
Here are some example scenarios where webhooks are useful:
Note: Webhooks are handy, but they're not strictly necessary to use Replicate, and there are other ways to receive updates. You can also poll the predictions API or use server-sent events (SSEs) to check the status of a prediction over time.
Watch: Learn more about how to use webhooks → YouTube (14 minutes).
To use webhooks, specify a webhook
URL in the request body when creating a prediction.
Here's an example using the replicate
JavaScript client:
In addition to predictions, you can also receive webhooks when fine-tuning models with the training API:
Add query params to your webhook URL to pass along extra metadata, like an internal ID you're using for a prediction. For example https://example.com/replicate-webhook?customId=123
Replicate can send an HTTP POST request to the URL you specified whenever the prediction is created, has new logs, new output, or is completed.
The request body is a prediction object in JSON format. This object has the same structure as the object returned by the get a prediction API. Here's an example of an unfinished prediction:
The prediction's status
property will have one of the following values:
starting
: the prediction is starting up. If this status lasts longer than a few seconds, then it's typically because a new worker is being started to run the prediction.processing
: the model is currently running.succeeded
: the prediction completed successfully.failed
: the prediction encountered an error during processing.canceled
: the prediction was canceled by the user.Here's an example of a Next.js webhook handler:
By default, Replicate sends requests to your webhook URL whenever there are new outputs or the prediction has finished. You can change which events trigger a webhook using the webhook_events_filter
property.
Your endpoint should respond with a 2xx status code within a few seconds, otherwise the webhook might be retried.
When Replicate sends the final webhook for a prediction (where the status is succeeded
, failed
or canceled
), we check the response status we get. If we can't make the request at all, or if we get a 4xx or 5xx response, we'll retry the webhook. We retry several times on an exponential backoff. The final retry is sent about 1 minute after the prediction completed.
We do not retry any webhooks for intermediate states.
Make webhook handlers idempotent. Identical webhooks can be sent more than once, so you'll need handle potentially duplicate information.
When Replicate sends a webhook request to your service, it does not follow redirects. If your endpoint responds with a redirect, the webhook will fail to send. Be sure to specify a webhook URL that will resolve without redirecting.
When writing the code for your new webhook handler, it's useful to be able to receive real webhooks in your development environment so you can verify your code is handling them as expected.
ngrok is a free reverse proxy tool that can create a secure tunnel to your local machine so you can receive webhooks. If you have Node.js installed, run ngrok directly from the command line using the npx
command that's included with Node.js.
The command above will generate output that looks like this:
The HTTPS URL in the output (http://3e48-20-171-41-18.ngrok.io
in the example above) is a temporary URL pointing to your local machine. Copy that URL and use it as the base of your webhook URL.
Here's an example using the replicate
JavaScript client:
Your webhook handler should now receive webhooks from Replicate. Once you've deployed your app, change the value of the webhook
URL to your production webhook handler endpoint when creating predictions.
For a real-world example of webhook handling in Next.js, check out Scribble Diffusion's codebase.
To prevent unauthorized requests, Replicate signs every webhook and its metadata with a unique key for each user or organization. You can use this signature to verify the webhook indeed comes from Replicate before you process it.
A webhook is an HTTP POST from an unknown source. Attackers can impersonate services by simply sending a fake webhook to an endpoint.
Another potential security hole is a replay attack, wherein an attacker intercepts a valid webhook payload (including the signature) and re-transmits it to your endpoint. This payload will pass signature validation, and will therefore be acted upon. To mitigate replay attacks, Replicate includes a timestamp indicating when the webhook attempt occurred.
Replicate's official JavaScript client has built-in support for verifying webhooks:
Replicate's official Go client also has built-in support for verifying webhooks:
Each webhook delivery includes three HTTP headers with additional information that you can use to verify the authenticity of the request:
webhook-id
: The unique message identifier for the webhook messages. This identifier is unique across all messages but will be the same when a webhook is being resent (e.g. retried).webhook-timestamp
: timestamp in seconds since epoch.webhook-signature
: the Base64 encoded list of signatures (space delimited).As a webhook receiver, you are responsible for constructing this signed content and performing the validation steps. To validate a webhook, the signed data must be constructed into a well-defined structure from the payload data (body), webhook-id
, and webhook-timestamp
headers.
The content to sign is composed by concatenating the id
, timestamp
, and data
, separated by the full-stop character (.
).
In code it will look something like:
In the example above, body
is the raw body of the request. The signature is sensitive to any changes, so even a small change in the body will cause the signature to be completely different. This means that you should not change the body in any way before verifying.
Replicate provides an API endpoint you can use to retrieve the signing key. The signing key is unique to your user or organization. The endpoint will return only the signing key associated with the API token and its corresponding user or organization.
For optimal performance of the webhook receiver, it is advised to locally cache the signing key. By doing so, you eliminate the need for the receiver to make a request to the Replicate API for validation every time a webhook is received.
Example cURL request:
The response will be a json object with a single key
field:
Replicate uses an HMAC with SHA-256 to sign its webhooks.
To calculate the expected signature, you should HMAC the signed_content
from above using the base64 portion of the signing secret (this is the part after the whsec_
prefix) as the key. For example given a secret whsec_C2FVsBQIhrscChlQIMV+b5sSYspob7oD
you will want to use C2FVsBQIhrscChlQIMV+b5sSYspob7oD
.
For example, this is how you can calculate the signature in Node.js:
This generated signature should match one of the ones sent in the webhook-signature
header.
The webhook-signature
header is composed of a list of space-delimited signatures and their corresponding version identifiers. The signature list is most commonly of length one, though there could be any number of signatures. For example:
Make sure to remove the version prefix and delimiter (e.g. v1,
) before verifying the signature.
Please note that to compute the signatures it's recommended to use a constant-time string comparison method in order to prevent timing attacks.
An example of how to do this in Node.js:
As mentioned above, Replicate also sends the timestamp of the attempt in the webhook-timestamp
header. You should compare the timestamp against your system timestamp and make sure it's within your tolerance in order to prevent replay attacks.