# Send a form's submissions to a webhook

Send each testimonial submitted through one form to your own server or automation tool as a signed JSON request, and test the connection.

A form's webhook sends every testimonial submitted through that form to an address you choose, such as your own server or an automation tool, as soon as it arrives. It's on Premium and Business, and the workspace owner and the project's Admins can set it up.

A form webhook sends one event, `testimonial.submitted`, and only for its own form. For approvals, edits, deletions and imports from the whole project, use a project webhook instead: [Webhooks](/help/integrations/webhooks) explains the difference. A project webhook with `testimonial.approved` ticked is told whenever you approve a testimonial yourself, an imported review as much as a form submission, with no other setting. Only a review that an import brings in already approved waits for **Include bulk imports and review sync events**.

1. **Open the form's webhook settings**

   In your project, open **Forms** under **Collect** in the sidebar and click **Edit** on the form. In the form builder, open the **Notifications** tab, scroll down to **Integrations** and click **Webhook**.

2. **Turn it on and add your URL**

   Switch on **Enable webhook**. In **Endpoint URL**, enter the address that should receive the submissions, then click **Create**.

   The address must:

   - start with `https://`;
   - be reachable on the public internet: `localhost`, private IP addresses and internal names (ending in `.local`, `.internal` or `.localhost`) are refused;
   - have no user name or password in it.

   The webhook is saved as soon as you click **Create**, separately from the rest of the form.

3. **Copy the signing secret**

   After you click **Create**, the **Signing Secret** is shown once. Click the copy button beside it and save it in your server's settings: you need it to check that each request really came from ReTestimonial. Once you leave the page, it's hidden for good.

   If you lose it, click **Regenerate** for a new one. The old secret stops working at once, and any deliveries still waiting to be sent are canceled.

4. **Send a test event**

   Click **Send Test Event**. ReTestimonial sends a sample `testimonial.submitted` request, with your form's real name and ID and a made-up testimonial, and shows the result below the button: **Success** with your server's status code and response time, or the error. Tests aren't added to the delivery log.

## What each request contains

Each submission sends one `POST` request with a JSON body:

- `event` (`testimonial.submitted`), an `id` for the delivery, `eventVersion`, `timestamp` and `sourceCategory` (`form`).
- `data.testimonial`: the testimonial as submitted, including its type, status, text, rating, author name, email, job title, company and photo, tags, and custom fields with their labels and display values.
- `data.project`: the project's ID, name and slug.
- `data.form`: the form's ID, name and slug.
- `data.submission`: the submission's ID, the answers (`responses`), whether it was low-rating feedback (`isNegativeFeedback`), and when it was started and completed.

Every request carries these headers:

- `X-Signature`: `t=<timestamp>,v1=<signature>`, an HMAC-SHA256 signature made with your signing secret. [Webhook signatures, headers and payloads](/help/integrations/verify-webhook-signatures) shows how to check it.
- `X-ReTestimonial-Event`: the event name.
- `X-ReTestimonial-Delivery` and `Idempotency-Key`: the delivery's ID. It stays the same when a delivery is retried, so you can ignore one you've already handled.

## Deliveries, retries and the log

- Your server should answer with a `2xx` status within 10 seconds. Any other answer, a timeout or a redirect counts as a failure; redirects aren't followed.
- A failed delivery is tried again after about 1 minute, 10 minutes and 1 hour, then marked as failed.
- After 15 failed attempts in a row, the webhook turns itself off and the workspace owner gets an email. Fix your server, then switch **Enable webhook** back on.
- To see every delivery, click **View delivery logs**. It opens the **Webhooks** tab of the project's **Developer** settings, where this webhook is listed as **Form:** followed by the form's name. Click **Logs** to see each delivery's status and your server's response, **Retry** one, or **Replay** the failed ones.

## Change or turn off the webhook

- **Change the URL:** edit **Endpoint URL** and click **Save**. Deliveries still waiting for the old address are canceled; you can replay them from the delivery log.
- **Turn it off:** switch off **Enable webhook**. The URL, the secret and the delivery history are kept, so you can switch it back on later. Deliveries still waiting are canceled, and submissions that arrive while it's off are never sent.
- **Plan changes:** if your plan no longer includes webhooks, the webhook is suspended and sends nothing until you upgrade again.
- **Delete it:** in the **Developer** settings, open the menu beside the webhook and choose **Delete endpoint**. Deleting the form also deletes its webhook and delivery history, and a copy of a form starts without one. See [What happens to my testimonials when I delete a form?](/help/collect/form-questions#what-happens-to-my-testimonials-when-i-delete-a-form).

Each form has one webhook, and it doesn't count toward your plan's limit of project webhooks.

## What happens next

- [Webhook signatures, headers and payloads](/help/integrations/verify-webhook-signatures): check them so your server accepts only genuine requests.
- [Set up a project webhook](/help/integrations/set-up-a-project-webhook) to get events for approvals, edits and imports too.
- [Build a collection form](/help/collect/build-a-collection-form)
