Replace a webhook endpoint
using System.Net.Http.Headers;var client = new HttpClient();var request = new HttpRequestMessage{ Method = HttpMethod.Put, RequestUri = new Uri("https://api.roundrobinbot.eu/v1/webhooks/example"), Headers = { { "If-Match", "example" }, { "Authorization", "Bearer <token>" }, }, Content = new StringContent("{ \"name\": \"example\", \"url\": \"example\", \"eventTypes\": [ \"example\" ] }") { Headers = { ContentType = new MediaTypeHeaderValue("application/json-patch+json") } }};using (var response = await client.SendAsync(request)){ response.EnsureSuccessStatusCode(); var body = await response.Content.ReadAsStringAsync(); Console.WriteLine(body);}package main
import ( "fmt" "strings" "net/http" "io")
func main() {
url := "https://api.roundrobinbot.eu/v1/webhooks/example"
payload := strings.NewReader("{ \"name\": \"example\", \"url\": \"example\", \"eventTypes\": [ \"example\" ] }")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("If-Match", "example") req.Header.Add("Authorization", "Bearer <token>") req.Header.Add("Content-Type", "application/json-patch+json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close() body, _ := io.ReadAll(res.Body)
fmt.Println(res) fmt.Println(string(body))
}OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json-patch+json");RequestBody body = RequestBody.create(mediaType, "{ \"name\": \"example\", \"url\": \"example\", \"eventTypes\": [ \"example\" ] }");Request request = new Request.Builder() .url("https://api.roundrobinbot.eu/v1/webhooks/example") .put(body) .addHeader("If-Match", "example") .addHeader("Authorization", "Bearer <token>") .addHeader("Content-Type", "application/json-patch+json") .build();
Response response = client.newCall(request).execute();import axios from 'axios';
const options = { method: 'PUT', url: 'https://api.roundrobinbot.eu/v1/webhooks/example', headers: { 'If-Match': 'example', Authorization: 'Bearer <token>', 'Content-Type': 'application/json-patch+json' }, data: '{ "name": "example", "url": "example", "eventTypes": [ "example" ] }'};
try { const { data } = await axios.request(options); console.log(data);} catch (error) { console.error(error);}const url = 'https://api.roundrobinbot.eu/v1/webhooks/example';const options = { method: 'PUT', headers: { 'If-Match': 'example', Authorization: 'Bearer <token>', 'Content-Type': 'application/json-patch+json' }, body: '{ "name": "example", "url": "example", "eventTypes": [ "example" ] }'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request PUT \ --url https://api.roundrobinbot.eu/v1/webhooks/example \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json-patch+json' \ --header 'If-Match: example' \ --data '{ "name": "example", "url": "example", "eventTypes": [ "example" ] }'Replaces the endpoint’s name, its URL and its subscriptions together. All three are required: an omitted eventTypes would read as “unsubscribe from everything”, and losing a subscription without being told is indistinguishable from us having stopped delivering. The URL is judged as strictly as at registration, because an edit is otherwise how an address we refuse to call gets in.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Header Parameters
Section titled “Header Parameters”The ETag from your last read of this resource, sent back exactly as you received it, quotes included. The write happens only if nothing changed in between: a stale validator is answered 412 and nothing is written. Send * to write against whatever is current on purpose. Omitting the header is 428, never an unconditional write. https://docs.roundrobinbot.eu/api/conventions/#conditional-writes
Request Body
Section titled “Request Body”Replaces the three things about an endpoint you own: its name, where we post, and what it receives.
object
Examplegenerated
{ "name": "example", "url": "example", "eventTypes": [ "example" ]}Replaces the three things about an endpoint you own: its name, where we post, and what it receives.
object
Examplegenerated
{ "name": "example", "url": "example", "eventTypes": [ "example" ]}Replaces the three things about an endpoint you own: its name, where we post, and what it receives.
object
Examplegenerated
{ "name": "example", "url": "example", "eventTypes": [ "example" ]}Responses
Section titled “Responses”OK
A registered destination: where Round Robin posts this workspace’s events, what it is subscribed to, and whether we are still calling it. Never the signing secret.
object
What the receiving system is called. Shown in the dashboard, never used for lookup.
Where we post. Always https.
What this endpoint receives: duty.changed, nobody.on_call, rotation.created, rotation.updated, rotation.deleted.
enabled or disabled. There is no revoked state: delete the endpoint instead.
Why we stopped calling: manual, delivery_failures or plan_downgrade. Absent while the endpoint is enabled.
Which secret is signing now, so your logs and ours name the same one.
The outgoing secret during a rotation’s grace window, absent at every other time.
When the outgoing secret stops signing. Until then both signatures travel in one header, so a receiver can cut over without an outage.
When the endpoint was registered.
Examplegenerated
{ "id": "example", "name": "example", "url": "example", "eventTypes": [ "example" ], "state": "example", "disabledReason": "example", "currentSecretId": "example", "currentSecretCreatedAt": "2026-04-15T12:00:00Z", "previousSecretId": "example", "previousSecretExpiresAt": "2026-04-15T12:00:00Z", "createdAt": "2026-04-15T12:00:00Z", "updatedAt": "2026-04-15T12:00:00Z"}Bad Request
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example"}Unauthorized
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example"}Payment Required
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example"}Forbidden
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example"}Not Found
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example"}Conflict
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example"}Precondition Failed
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example"}Precondition Required
object
Examplegenerated
{ "type": "example", "title": "example", "status": 1, "detail": "example", "instance": "example"}