> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.paywithatoa.co.uk/llms.txt
> Use this file to discover all available pages before exploring further.

# Update Endpoint | Webhooks API

> Update endpoint via the Atoa Webhooks API, request parameters, response schema and code samples in cURL, Python, JavaScript, PHP, Go and Java.

Update an existing webhook endpoint's description, event subscriptions, or authentication credentials.

<Note>
  The endpoint URL cannot be changed after creation. To use a different URL, delete the endpoint and create a new one.
</Note>

### Authorization

Bearer `<token>`

**Path Parameters**

<ParamField path="endpointId" type="string" required>
  The unique identifier of the endpoint to update.
</ParamField>

**Request Body Schema**

<ParamField body="events" type="string[]" required>
  The complete set of event types to subscribe to. This **replaces** the existing subscriptions — any event not included is removed. At least one event is required.

  If you are adding a new event type to this endpoint, each event type supports a maximum of **3 registered endpoints** across your account. Adding an event that already has 3 other endpoints subscribed returns a `400` error. Use [List endpoints](/api-reference/Webhook/v2/listEndpoints) to check current registrations before updating.
</ParamField>

<ParamField body="description" type="string">
  Updated description for this endpoint (max 100 characters). Omit to leave the current description unchanged.
</ParamField>

<ParamField body="authentication" type="object">
  Optional. Updated authentication configuration. Two methods are supported — choose one. Fields from different methods cannot be mixed. Pass `null` explicitly to remove existing authentication. Omit the field entirely to leave authentication unchanged.

  <AccordionGroup>
    <Accordion title="Remove authentication">
      Pass `"authentication": null` to remove any existing authentication from the endpoint.
    </Accordion>

    <Accordion title="Basic Auth — username + password">
      Atoa includes an `Authorization: Basic <base64(username:password)>` header in every delivery request. Pass both fields together.

      <ParamField body="username" type="string" required>
        Username for HTTP Basic Authentication.
      </ParamField>

      <ParamField body="password" type="string" required>
        Password for HTTP Basic Authentication.
      </ParamField>
    </Accordion>

    <Accordion title="OAuth 2.0 — client credentials flow">
      Before each delivery, Atoa calls your token endpoint using the `client_credentials` grant to obtain a short-lived access token, then includes it as `Authorization: Bearer <token>` in the delivery request. Pass all three fields together.

      <ParamField body="clientId" type="string" required>
        Client ID registered with your authorisation server.
      </ParamField>

      <ParamField body="clientSecret" type="string" required>
        Client secret for the above client ID.
      </ParamField>

      <ParamField body="authUrl" type="string" required>
        Your token endpoint URL (e.g. `https://auth.your-server.com/oauth/token`). Atoa will POST to this URL to fetch an access token before each delivery.
      </ParamField>
    </Accordion>
  </AccordionGroup>
</ParamField>

**Response**

Returns the updated endpoint object. Same shape as [Create endpoint](/api-reference/Webhook/v2/createEndpoint#response).

<RequestExample>
  ```bash No Auth theme={null}
  curl --request PUT \
    --url https://api.atoa.me/api/webhook/v2/endpoints/4a124f25-fe8d-47a0-92c8-16d94cbfe24c \
    --header 'Authorization: Bearer <token>' \
    --header 'Content-Type: application/json' \
    --data '{
      "events": ["PAYMENTS_STATUS", "REFUND_STATUS", "EXPIRED_STATUS"],
      "description": "Updated production endpoint"
    }'
  ```

  ```bash Basic Auth theme={null}
  curl --request PUT \
    --url https://api.atoa.me/api/webhook/v2/endpoints/4a124f25-fe8d-47a0-92c8-16d94cbfe24c \
    --header 'Authorization: Bearer <token>' \
    --header 'Content-Type: application/json' \
    --data '{
      "events": ["PAYMENTS_STATUS", "REFUND_STATUS", "EXPIRED_STATUS"],
      "authentication": {
        "username": "your-username",
        "password": "your-password"
      }
    }'
  ```

  ```bash OAuth 2.0 theme={null}
  curl --request PUT \
    --url https://api.atoa.me/api/webhook/v2/endpoints/4a124f25-fe8d-47a0-92c8-16d94cbfe24c \
    --header 'Authorization: Bearer <token>' \
    --header 'Content-Type: application/json' \
    --data '{
      "events": ["PAYMENTS_STATUS", "REFUND_STATUS", "EXPIRED_STATUS"],
      "authentication": {
        "clientId": "your-client-id",
        "clientSecret": "your-client-secret",
        "authUrl": "https://auth.your-server.com/oauth/token"
      }
    }'
  ```

  ```bash Remove Auth theme={null}
  curl --request PUT \
    --url https://api.atoa.me/api/webhook/v2/endpoints/4a124f25-fe8d-47a0-92c8-16d94cbfe24c \
    --header 'Authorization: Bearer <token>' \
    --header 'Content-Type: application/json' \
    --data '{
      "events": ["PAYMENTS_STATUS", "REFUND_STATUS", "EXPIRED_STATUS"],
      "authentication": null
    }'
  ```

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

  endpoint_id = "4a124f25-fe8d-47a0-92c8-16d94cbfe24c"
  url = f"https://api.atoa.me/api/webhook/v2/endpoints/{endpoint_id}"

  payload = {
      "events": ["PAYMENTS_STATUS", "REFUND_STATUS", "EXPIRED_STATUS"],
      "description": "Updated production endpoint"
  }
  headers = {
      "Authorization": "Bearer <token>",
      "Content-Type": "application/json"
  }

  response = requests.request("PUT", url, json=payload, headers=headers)
  print(response.text)
  ```

  ```javascript JavaScript theme={null}
  const endpointId = "4a124f25-fe8d-47a0-92c8-16d94cbfe24c";

  const options = {
    method: 'PUT',
    headers: { Authorization: 'Bearer <token>', 'Content-Type': 'application/json' },
    body: JSON.stringify({
      events: ['PAYMENTS_STATUS', 'REFUND_STATUS', 'EXPIRED_STATUS'],
      description: 'Updated production endpoint'
    })
  };

  fetch(`https://api.atoa.me/api/webhook/v2/endpoints/${endpointId}`, options)
    .then(response => response.json())
    .then(response => console.log(response))
    .catch(err => console.error(err));
  ```

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

  $curl = curl_init();

  $endpointId = "4a124f25-fe8d-47a0-92c8-16d94cbfe24c";

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://api.atoa.me/api/webhook/v2/endpoints/{$endpointId}",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "PUT",
    CURLOPT_POSTFIELDS => json_encode([
      "events" => ["PAYMENTS_STATUS", "REFUND_STATUS", "EXPIRED_STATUS"],
      "description" => "Updated production endpoint"
    ]),
    CURLOPT_HTTPHEADER => [
      "Authorization: Bearer <token>",
      "Content-Type: application/json"
    ],
  ]);

  $response = curl_exec($curl);
  $err = curl_error($curl);

  curl_close($curl);

  if ($err) {
    echo "cURL Error #:" . $err;
  } else {
    echo $response;
  }
  ```

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

  import (
  	"fmt"
  	"strings"
  	"net/http"
  	"io"
  )

  func main() {

  	endpointId := "4a124f25-fe8d-47a0-92c8-16d94cbfe24c"
  	url := "https://api.atoa.me/api/webhook/v2/endpoints/" + endpointId

  	payload := strings.NewReader(`{
      "events": ["PAYMENTS_STATUS", "REFUND_STATUS", "EXPIRED_STATUS"],
      "description": "Updated production endpoint"
    }`)

  	req, _ := http.NewRequest("PUT", url, payload)

  	req.Header.Add("Authorization", "Bearer <token>")
  	req.Header.Add("Content-Type", "application/json")

  	res, _ := http.DefaultClient.Do(req)

  	defer res.Body.Close()
  	body, _ := io.ReadAll(res.Body)

  	fmt.Println(string(body))

  }
  ```

  ```java Java theme={null}
  HttpResponse<String> response = Unirest.put("https://api.atoa.me/api/webhook/v2/endpoints/{endpointId}")
    .header("Authorization", "Bearer <token>")
    .header("Content-Type", "application/json")
    .routeParam("endpointId", "4a124f25-fe8d-47a0-92c8-16d94cbfe24c")
    .body("{\n  \"events\": [\"PAYMENTS_STATUS\", \"REFUND_STATUS\", \"EXPIRED_STATUS\"],\n  \"description\": \"Updated production endpoint\"\n}")
    .asString();
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "id": "4a124f25-fe8d-47a0-92c8-16d94cbfe24c",
    "url": "https://your-server.com/webhooks",
    "description": "Updated production endpoint",
    "environment": "PRODUCTION",
    "events": [
      { "event": "PAYMENTS_STATUS", "label": "Payment Status" },
      { "event": "REFUND_STATUS", "label": "Refund Status" },
      { "event": "EXPIRED_STATUS", "label": "Expired Status" }
    ],
    "hasAuthentication": false,
    "authenticationType": null,
    "failureCount": 0,
    "lastDeliveredAt": "2025-06-01T12:00:00.000Z"
  }
  ```

  ```json 400 (events required) theme={null}
  {
    "name": "BAD_REQUEST",
    "message": "At least one event type is required.",
    "status": 400
  }
  ```

  ```json 400 (duplicate events) theme={null}
  {
    "name": "BAD_REQUEST",
    "message": "Duplicate event types are not allowed.",
    "status": 400
  }
  ```

  ```json 400 (capacity exceeded) theme={null}
  {
    "name": "BAD_REQUEST",
    "message": "Payment Status has reached the maximum limit of 3 endpoints per event type.",
    "status": 400
  }
  ```

  ```json 400 (POS without signing secret) theme={null}
  {
    "name": "BAD_REQUEST",
    "message": "POS Payment Status requires V2 signing. Please generate a signing secret from the dashboard to proceed.",
    "status": 400
  }
  ```

  ```json 401 theme={null}
  {
    "name": "UNAUTHORIZED",
    "message": "Unauthorized",
    "status": 401,
    "errors": "[]"
  }
  ```

  ```json 404 theme={null}
  {
    "name": "NOT_FOUND",
    "message": "Webhook not found",
    "status": 404
  }
  ```
</ResponseExample>
