> ## Documentation Index
> Fetch the complete documentation index at: https://docs.autosend.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Update Webhook

> Updates a webhook's URL, subscribed events, active state, or metadata. The signing secret is immutable — create a new webhook to rotate it.

<Note>
  This endpoint accepts a **project API key** (`AS_` prefix). The signing secret is immutable — create a new webhook to rotate it. Supplying a `secret` field returns a `400` error.
</Note>

<RequestExample>
  ```bash cURL theme={null}
  curl --request PUT \
    --url https://api.autosend.com/v1/webhooks/60d5ec49f1b2c72d9c8b1234 \
    --header 'Authorization: Bearer AS_your-api-key' \
    --header 'Content-Type: application/json' \
    --data '{
    "events": ["email.delivered", "email.opened", "email.clicked"],
    "isActive": false
  }'
  ```

  ```python Python theme={null}
  import requests

  webhook_id = "60d5ec49f1b2c72d9c8b1234"
  url = f"https://api.autosend.com/v1/webhooks/{webhook_id}"

  headers = {
      "Authorization": "Bearer AS_your-api-key",
      "Content-Type": "application/json"
  }

  payload = {
      "events": ["email.delivered", "email.opened", "email.clicked"],
      "isActive": False
  }

  response = requests.put(url, json=payload, headers=headers)
  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const webhookId = '60d5ec49f1b2c72d9c8b1234';

  fetch(`https://api.autosend.com/v1/webhooks/${webhookId}`, {
    method: 'PUT',
    headers: {
      'Authorization': 'Bearer AS_your-api-key',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      events: ['email.delivered', 'email.opened', 'email.clicked'],
      isActive: false
    })
  })
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error('Error:', error));
  ```

  ```php PHP theme={null}
  <?php

  $webhookId = '60d5ec49f1b2c72d9c8b1234';
  $url = "https://api.autosend.com/v1/webhooks/{$webhookId}";

  $data = [
      'events' => ['email.delivered', 'email.opened', 'email.clicked'],
      'isActive' => false
  ];

  $ch = curl_init($url);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'Authorization: Bearer AS_your-api-key',
      'Content-Type: application/json'
  ]);

  $response = curl_exec($ch);
  curl_close($ch);

  echo $response;
  ?>
  ```

  ```go Go theme={null}
  package main

  import (
      "bytes"
      "encoding/json"
      "fmt"
      "io"
      "net/http"
  )

  func main() {
      webhookID := "60d5ec49f1b2c72d9c8b1234"
      url := "https://api.autosend.com/v1/webhooks/" + webhookID

      payload := map[string]interface{}{
          "events":   []string{"email.delivered", "email.opened", "email.clicked"},
          "isActive": false,
      }

      jsonData, _ := json.Marshal(payload)

      req, _ := http.NewRequest("PUT", url, bytes.NewBuffer(jsonData))
      req.Header.Set("Authorization", "Bearer AS_your-api-key")
      req.Header.Set("Content-Type", "application/json")

      client := &http.Client{}
      resp, err := client.Do(req)
      if err != nil {
          fmt.Println("Error:", err)
          return
      }
      defer resp.Body.Close()

      body, _ := io.ReadAll(resp.Body)
      fmt.Println(string(body))
  }
  ```

  ```java Java theme={null}
  import java.io.OutputStream;
  import java.net.HttpURLConnection;
  import java.net.URL;
  import java.nio.charset.StandardCharsets;

  public class UpdateWebhook {
      public static void main(String[] args) {
          try {
              String webhookId = "60d5ec49f1b2c72d9c8b1234";
              URL url = new URL("https://api.autosend.com/v1/webhooks/" + webhookId);
              HttpURLConnection con = (HttpURLConnection) url.openConnection();

              con.setRequestMethod("PUT");
              con.setRequestProperty("Authorization", "Bearer AS_your-api-key");
              con.setRequestProperty("Content-Type", "application/json");
              con.setDoOutput(true);

              String jsonInputString = "{\n" +
                  "  \"events\": [\"email.delivered\", \"email.opened\", \"email.clicked\"],\n" +
                  "  \"isActive\": false\n" +
                  "}";

              try (OutputStream os = con.getOutputStream()) {
                  byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8);
                  os.write(input, 0, input.length);
              }

              int status = con.getResponseCode();
              System.out.println("Response Status: " + status);

          } catch (Exception e) {
              e.printStackTrace();
          }
      }
  }
  ```

  ```ruby Ruby theme={null}
  require 'net/http'
  require 'json'
  require 'uri'

  webhook_id = '60d5ec49f1b2c72d9c8b1234'
  uri = URI("https://api.autosend.com/v1/webhooks/#{webhook_id}")

  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true

  request = Net::HTTP::Put.new(uri.request_uri)
  request['Authorization'] = 'Bearer AS_your-api-key'
  request['Content-Type'] = 'application/json'

  request.body = {
    events: ['email.delivered', 'email.opened', 'email.clicked'],
    isActive: false
  }.to_json

  response = http.request(request)
  puts response.body
  ```
</RequestExample>

<ResponseExample>
  ```json 200 Response theme={null}
  {
    "success": true,
    "message": "Webhook updated successfully",
    "data": {
      "id": "60d5ec49f1b2c72d9c8b1234",
      "organizationId": "60d5ec49f1b2c72d9c8b0000",
      "projectId": "60d5ec49f1b2c72d9c8b1111",
      "url": "https://example.com/webhooks/autosend",
      "secret": "***hidden***",
      "events": ["email.delivered", "email.opened", "email.clicked"],
      "isActive": false,
      "status": "inactive",
      "failureCount": 0,
      "lastFailedAt": null,
      "lastSuccessAt": "2026-06-12T10:00:00.000Z",
      "lastDeliveredAt": "2026-06-12T10:00:00.000Z",
      "metadata": { "team": "growth" },
      "createdAt": "2026-06-01T09:00:00.000Z",
      "updatedAt": "2026-06-12T11:00:00.000Z"
    }
  }
  ```
</ResponseExample>

***

#### Authorizations

<ParamField path="Authorizations" type="string | header" required>
  Project API key header of the form Bearer `AS_<key>`.
</ParamField>

### Path Parameters

<ParamField path="id" type="string" required>
  The unique identifier of the webhook.

  Example: `"60d5ec49f1b2c72d9c8b1234"`
</ParamField>

### Body

All fields are optional — only the fields you supply are updated.

<ParamField body="url" type="string">
  A new destination URL (must include the `http`/`https` protocol).

  Example: `"https://example.com/webhooks/autosend"`
</ParamField>

<ParamField body="events" type="string[]">
  Replaces the subscribed event list. Must contain at least one valid event.

  Example: `["email.delivered", "email.opened"]`
</ParamField>

<ParamField body="isActive" type="boolean">
  Enable or disable delivery without deleting the webhook.

  Example: `false`
</ParamField>

#### Response

<span className="text-sm">Webhook updated successfully (200)</span>

<ResponseField name="success" type="boolean">
  Indicates if the request was successful
</ResponseField>

<ResponseField name="data" type="object">
  The updated webhook object. The signing secret is always masked as `***hidden***`.

  <Expandable title="child attributes">
    <ResponseField name="data.id" type="string">
      Unique webhook identifier
    </ResponseField>

    <ResponseField name="data.url" type="string">
      The destination URL events are delivered to
    </ResponseField>

    <ResponseField name="data.events" type="string[]">
      The updated subscribed event types
    </ResponseField>

    <ResponseField name="data.isActive" type="boolean">
      Whether the webhook is currently active
    </ResponseField>

    <ResponseField name="data.status" type="string">
      Delivery status. One of `active`, `inactive`, or `disabled`
    </ResponseField>

    <ResponseField name="data.failureCount" type="integer">
      Number of consecutive delivery failures (reset to `0` when re-activating)
    </ResponseField>

    <ResponseField name="data.lastFailedAt" type="string | null">
      Timestamp of the most recent failed delivery (ISO 8601), or `null`
    </ResponseField>

    <ResponseField name="data.lastSuccessAt" type="string | null">
      Timestamp of the most recent successful delivery (ISO 8601), or `null`
    </ResponseField>

    <ResponseField name="data.lastDeliveredAt" type="string | null">
      Timestamp of the most recent delivery attempt (ISO 8601), or `null`
    </ResponseField>

    <ResponseField name="data.metadata" type="object | null">
      Arbitrary key-value metadata attached to the webhook
    </ResponseField>

    <ResponseField name="data.createdAt" type="string">
      ISO 8601 creation timestamp
    </ResponseField>

    <ResponseField name="data.updatedAt" type="string">
      ISO 8601 last-updated timestamp
    </ResponseField>
  </Expandable>
</ResponseField>

#### Error Responses

<ResponseField name="400 - Secret update not allowed" type="object">
  Returned when a `secret` field is included in the request body.

  ```json theme={null}
  {
    "success": false,
    "error": {
      "message": "Secret cannot be updated. Create a new webhook instead.",
      "code": "VALIDATION_ERROR",
    }
  }
  ```
</ResponseField>

<ResponseField name="404 - Webhook not found" type="object">
  Returned when no webhook with the given ID exists in the project.

  ```json theme={null}
  {
    "success": false,
    "error": {
      "message": "Webhook not found",
      "code": "WEBHOOK_NOT_FOUND",
    }
  }
  ```
</ResponseField>


## OpenAPI

````yaml PUT /webhooks/{id}
openapi: 3.1.0
info:
  title: AutoSend API
  description: >-
    AutoSend REST API for managing project webhooks. These endpoints accept a
    project API key (AS_ prefix) and let you subscribe to email and contact
    events, inspect delivery logs, and test deliveries.
  version: 1.0.0
servers:
  - url: https://api.autosend.com/v1
security:
  - bearerAuth: []
paths:
  /webhooks/{id}:
    put:
      summary: Update Webhook
      description: >-
        Updates a webhook's URL, subscribed events, active state, or metadata.
        The signing secret is immutable — create a new webhook to rotate it.
components: {}

````

## Related topics

- [Webhooks](/others/webhooks/introduction.md)
- [Verify Webhook Requests](/others/webhooks/verify-requests.md)
- [Event Types](/others/webhooks/event-type.md)
- [Retries and Replays](/others/webhooks/retries.md)
- [Update Automation](/api-reference/automations/update-automation.md)
