# Update a webhook subscription

```http
PUT https://secure.yoprint.com/v1/api/store/{team_slug}/setting/webhook_subscription/{hash_id}
```

- API version: v1
- Operation ID: `v1_public_webhook_subscription_update_put`
- Section: Team settings › [Webhook subscriptions](https://developer.yoprint.com/reference/webhook-subscriptions.md)
- Web page: https://developer.yoprint.com/reference/webhook-subscriptions/v1-webhook-subscription-update-put/
- Authentication: `Authorization: Bearer YOUR_API_KEY`

Changes a subscription's URL, name, events or status, and returns it.

`url` is required on every update, even when it doesn't change. Fields you leave out keep their values. Set `status` to `disabled` to pause deliveries and back to `active` to resume them; events that happen while it is disabled are not sent later.

## Permission

Needs the Manage Settings permission.

## Business rules

- `url` is required.
- A new `url` is checked as on create: `https://`, on a host that resolves only to public internet addresses. The subscription's current URL, sent exactly as stored, is not looked up again, so you can rename, disable or change the events of a subscription whose receiver is down.
- `status` is `active` or `disabled`.
- `enabled_events`, when sent, needs at least one name, no repeats, and replaces the list.
- The `secret`, `source` and status filters cannot be changed.

## Side effects

- A new URL receives the retries of earlier events that are still pending.
- Disabling stops new deliveries, but retries already scheduled (at most about 2 minutes ahead) still go out.

## Path parameters

- `team_slug` (string, required): Your team slug, shown as Team ID next to your API key in Profile. Example `your-team`.
- `hash_id` (string, required): The webhook subscription's `id`: a hash id from an earlier answer. Only hash ids work here; anything else answers 404 `page_not_found`. Example `V4keXwwxMQyXw7`.

## Request body

Content type `application/json`, required.

Fields:

- `url` (string, required): Where YoPrint sends events. Must be an `https://` URL on the public internet. YoPrint refuses plain `http://` URLs and any host that resolves to a non-public address (private, loopback, link-local, carrier-grade NAT, multicast or reserved). YoPrint looks up the host when you save, but does not send a test request. Use the final destination URL because redirects are not followed.
- `config` (object, optional): Accepted and validated, but not saved: status filters can only be set when the subscription is created.
- `enabled_events` (array of strings, optional): Replaces the whole list. YoPrint doesn't check the names. At least 1 item. Items must be unique.
- `name` (string, optional): A name to recognize it by.
- `status` (string, optional): `disabled` stops deliveries; `active` resumes them. One of: `"active"`, `"disabled"`.

### Example request

```bash
curl -X PUT 'https://secure.yoprint.com/v1/api/store/your-team/setting/webhook_subscription/V4keXwwxMQyXw7' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Accept: application/json' \
  -H 'X-Yoprint-Decimal-Format: exact-v1' \
  -H 'Content-Type: application/json' \
  -d '{
    "enabled_events": [
      "order.created",
      "sales_order.status_changed"
    ],
    "url": "https://example.com/yoprint/webhooks"
  }'
```

Another example: Turn deliveries back on:

```bash
curl -X PUT 'https://secure.yoprint.com/v1/api/store/your-team/setting/webhook_subscription/V4keXwwxMQyXw7' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Accept: application/json' \
  -H 'X-Yoprint-Decimal-Format: exact-v1' \
  -H 'Content-Type: application/json' \
  -d '{
    "status": "active",
    "url": "https://example.com/yoprint/webhooks"
  }'
```

## Response

`200` Successful response.

Fields:

- `data` (object, required)
  - `created_at` (string (date-time), required)
  - `disable_reason` (string | null, required): `auto_disable_too_many_errors` when YoPrint turned the subscription off because its deliveries kept failing. Otherwise null. Setting `status` back to `active` does not clear it.
  - `enabled_events` (array of strings, required): Subscribed event names, or `all` for every event.
  - `id` (string, required): The subscription id.
  - `name` (string, required)
  - `secret` (string | null, required): The secret used to sign event payloads: `whsec_` followed by 32 letters and digits. Use it to verify incoming messages. YoPrint creates it when the subscription is created and never changes it. Keep it private. Only the team owner and members whose permission group has Manage Settings can see it; for every other member it is null. It is also null for AI apps reading through YoPrint's MCP server.
  - `source` (string, required): The `source` sent when the subscription was created: the web app sends `yoprint`, YoPrint's Zapier app sends `zapier`.
  - `status` (string, required): Only `active` subscriptions receive events. One of: `"active"`, `"disabled"`.
  - `updated_at` (string (date-time), required)
  - `url` (string | null, required): The destination URL where YoPrint delivers events. On this API, this is the full URL. AI apps reading subscriptions through YoPrint's MCP server see only the origin (scheme and host, such as `https://example.com`) to protect webhook secrets.
- `status` (integer, required)
- `success` (boolean, required)

Example response:

```json
{
  "data": {
    "created_at": "2026-11-03T15:00:00+00:00",
    "disable_reason": null,
    "enabled_events": [
      "order.created",
      "sales_order.status_changed"
    ],
    "id": "V4keXwwxMQyXw7",
    "name": "Order sync",
    "secret": "whsec_YOUR_WEBHOOK_SECRET",
    "source": "yoprint",
    "status": "active",
    "updated_at": "2026-11-03T15:00:00+00:00",
    "url": "https://example.com/yoprint/webhooks"
  },
  "status": 200,
  "success": true
}
```

## Errors

- `401` The API key is missing or wrong (`unauthenticated`).
  - When: The API key is missing or wrong. Fix: Send your personal API key as `Authorization: Bearer YOUR_API_KEY`.
- `403` You are not allowed to do this. `api_access_not_in_plan`: your team's plan doesn't include API access (Pro and above, with an active subscription or trial), so every request answers this until the team upgrades. When your role lacks the permission the operation needs, the body is only `{"message": "Insufficient Permission"}`. Other refusals use the error envelope, with `unauthorized` or `user_is_not_authorized`.
  - When: Your permission group lacks Manage Settings. This 403 has a short body, `{"message": "Insufficient Permission"}`, without `success` or `error`. Fix: Ask the team owner to give your permission group Manage Settings.
- `404` Not found. `page_not_found`: the team slug is unknown, you are not a member of the team, or an id in the path is not one of this team's. `code: null`, with a message that starts "No query results for": there is no record with that id.
  - When: No webhook subscription with that id on this team (`error.code` is null and `error.message` starts "No query results"), the id is not one of this team's hash ids, or you are not a member of the team (both `page_not_found`). Fix: Use an `id` from the list operation and check the team slug.
- `422` The request was refused and changed nothing. `validation_failed` lists what to fix in `error.fields`; other codes name a business rule, explained in `error.message`. A few checks answer with only `{"message": "..."}`. An operation that calls another service (a payment provider, a carrier, an accounting app) can answer `connect_timeout` ("Please retry again") when that service does not answer in time: the change may or may not have happened there, so read the record back before you retry.
  - When: `url` is missing or not a URL, `status` is not `active` or `disabled`, `enabled_events` is empty or repeats a name, or a `status_ids` list is empty. `error.code` is `validation_failed`, and `error.fields` names each field with its messages. Fix: Fix the fields listed in `error.fields` and send the request again.
  - When: `url` is refused by the public-address check (`validation_failed`, with `error.fields.url` and `error.field_reasons.url.reason`). `not_public_address`: the URL is not `https://`, has no usable host, or its host reaches an address that is not on the public internet ("Use an https:// URL that reaches a public internet address."). `host_lookup_failed`: the host name could not be looked up ("The host name in this URL could not be looked up. Check the address, or try again in a minute."). Fix: Use an `https://` URL on a public host. For `host_lookup_failed`, check the host name, or try again in a minute if its DNS is new.

## Notes

- Turning a subscription back on leaves `disable_reason` as it was.
- To change the status filters, create a new subscription with the new `config` and delete the old one.

## Related

- [Show a webhook subscription](https://developer.yoprint.com/reference/webhook-subscriptions/v1-webhook-subscription-show.md): `GET /v1/api/store/{team_slug}/setting/webhook_subscription/{hash_id}`
- [Delete a webhook subscription](https://developer.yoprint.com/reference/webhook-subscriptions/v1-webhook-subscription-destroy.md): `DELETE /v1/api/store/{team_slug}/setting/webhook_subscription/{hash_id}`
