> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.confirm.global/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.confirm.global/_mcp/server.

# Set the registry's default webhook endpoint

PUT https://api.confirm.global/partner/v1/organizations/{ref}/webhook
Content-Type: application/json

Sets (or replaces) the fallback delivery target for this registry.

It is used for any applicant that has **no** `webhook_url` of their own —
in practice, everyone CONFIRM sourced. Applicants you sent us keep using
the URL you supplied with them; this never overrides that.

Idempotent: sending the same URL twice returns the same record. There is
exactly one endpoint per registry, so there is no endpoint ID for you to
store.

The URL is held to the same rules as a per-applicant `webhook_url`:
HTTPS, a public host that exists in DNS, no embedded credentials, 2048
characters at most. A URL that breaks a rule returns `400` with one of
the codes in the
[webhooks guide](/partner-guides/webhooks#rules-for-the-url):
`invalid_webhook_url`, `webhook_url_not_https`,
`webhook_url_forbidden_host`, `webhook_url_too_long`, or
`webhook_url_unresolvable`.


Reference: https://docs.confirm.global/partner-api/webhooks/set-org-webhook-endpoint

## Authentication

- `Authorization` header (bearer token, required) — Partner API key sent as `Authorization: Bearer cfk_...`. Keys are partner-level — one key reaches every registry linked to your partner account and nothing else. CONFIRM issues and revokes them; a key is shown exactly once at creation because only its hash is stored, and revocation takes effect on the next request. Develop against the sandbox base URL with a sandbox key, where telephony is restricted to an allowlist you provide.

## Request

### Path parameters

- `ref` (string, required) — Your registry identifier (the `external_ref` you created it with).

### Body (application/json)

This endpoint expects an object.

- `url` (string, required) — HTTPS endpoint that receives this registry's fallback deliveries.

## Response

### 201

Default endpoint created. Sending again for a registry that already has one returns **200** and replaces the URL.

- `organization_ref` (string, optional) — Your registry identifier, echoed back.
- `url` (string, optional)
- `created_at` (datetime, optional)
- `updated_at` (datetime, optional)

## Errors

### 400 Bad Request Error

The request failed validation. `code` says why: | `code` | Meaning | |---|---| | `invalid_request` | A field is missing or malformed. `details` lists each one. | | `invalid_webhook_url` | The webhook URL is empty, isn't an absolute URL, has no host, or contains credentials (`user:pass@`). | | `webhook_url_not_https` | The webhook URL doesn't use `https`. | | `webhook_url_forbidden_host` | The host is private or internal: `localhost`, a private or reserved IP address, an internal name such as `*.local` or `*.internal`, a cloud metadata endpoint, or a name that resolves to one of these. | | `webhook_url_too_long` | The webhook URL is over 2048 characters. | | `webhook_url_unresolvable` | The host doesn't exist in DNS (for example, anything under `.invalid`). | See [Rules for the URL](/partner-guides/webhooks#rules-for-the-url).

- `error` (ErrorError, required)

### 401 Unauthorized Error

Missing, malformed, or revoked API key (`error.type: authentication_error`).

- `error` (ErrorError, required)

### 404 Not Found Error

No registry is registered with that ref for your partner account (`unknown_organization_ref`).

- `error` (ErrorError, required)

### 429 Too Many Requests Error

Rate limit exceeded (`error.type: rate_limit_error`). Design target: 600 requests/min per key, burst 100/10s. Honor the `Retry-After` header.

- `error` (ErrorError, required)

## Types

### ErrorError

- `type` (enum, required) — Broad error category.
  - Allowed values: `authentication_error`, `invalid_request_error`, `not_found_error`, `conflict_error`, `rate_limit_error`, `api_error`
- `code` (string, required) — Machine-readable error code, e.g. `invalid_request`, `unknown_location_ref` or `wrong_environment`. Branch on this; the strings are contract.
- `message` (string, required) — Human-readable explanation.
- `request_id` (string, required) — Identifier for this request — the same value as the response's `X-Request-Id` header. Include it when contacting CONFIRM support.
- `details` (list of ErrorErrorDetailsItems, optional) — Present on `invalid_request` (400): one entry per field that failed validation.
- `location_ref` (string, optional) — Present on `unknown_location_ref` (404) — the reference that wasn't found.
- `organization_ref` (string, optional) — Present on `unknown_organization_ref` (404) — the reference that wasn't found — and on `email_has_account` (409) — the registry the invitation was for.
- `external_ref` (string, optional) — Present on workspace-teardown refusals (403) — the workspace you asked to delete — and on applicant errors (`unknown_candidate_ref`, `no_application_at_location`, `outcome_conflict`) — the applicant ref.
- `organization_refs` (list of string, optional) — Present on `ambiguous_location_ref` (409) — the registries the ref exists in.
- `locations` (list of ErrorErrorLocationsItems, optional) — Present on `location_refs_span_organizations` (400) — each ref you sent with the registry it belongs to.

### ErrorErrorDetailsItems

- `field` (string, required) — Dotted path to the offending field, e.g. `address.postal_code`.
- `message` (string, required) — Why that field was rejected.

### ErrorErrorLocationsItems

- `location_ref` (string, optional)
- `organization_ref` (string, optional, nullable)

## Examples

**Request**

```json
{
  "url": "https://hooks.example.com/confirm/registry/4471"
}
```

**Response**

```json
{
  "organization_ref": "cl_reg_4471",
  "url": "https://hooks.example.com/confirm/registry/4471",
  "created_at": "2024-01-15T09:30:00Z",
  "updated_at": "2024-01-15T09:30:00Z"
}
```

**SDK Code**

```python
import requests

url = "https://api.confirm.global/partner/v1/organizations/cl_reg_4471/webhook"

payload = { "url": "https://hooks.example.com/confirm/registry/4471" }
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

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

print(response.json())
```

```javascript
const url = 'https://api.confirm.global/partner/v1/organizations/cl_reg_4471/webhook';
const options = {
  method: 'PUT',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"url":"https://hooks.example.com/confirm/registry/4471"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

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

func main() {

	url := "https://api.confirm.global/partner/v1/organizations/cl_reg_4471/webhook"

	payload := strings.NewReader("{\n  \"url\": \"https://hooks.example.com/confirm/registry/4471\"\n}")

	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(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.confirm.global/partner/v1/organizations/cl_reg_4471/webhook")

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

request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"url\": \"https://hooks.example.com/confirm/registry/4471\"\n}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.put("https://api.confirm.global/partner/v1/organizations/cl_reg_4471/webhook")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"url\": \"https://hooks.example.com/confirm/registry/4471\"\n}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('PUT', 'https://api.confirm.global/partner/v1/organizations/cl_reg_4471/webhook', [
  'body' => '{
  "url": "https://hooks.example.com/confirm/registry/4471"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.confirm.global/partner/v1/organizations/cl_reg_4471/webhook");
var request = new RestRequest(Method.PUT);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"url\": \"https://hooks.example.com/confirm/registry/4471\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["url": "https://hooks.example.com/confirm/registry/4471"] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.confirm.global/partner/v1/organizations/cl_reg_4471/webhook")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "PUT"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```