curl --request PUT \
--url https://uat-api.clinkbill.com/api/webhook/endpoints/ensure \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <api-key>' \
--header 'X-Timestamp: <x-timestamp>' \
--data '
{
"url": "https://example.com/api/clink/webhook",
"events": [
"session.complete",
"order.succeeded"
],
"description": "Created through the API",
"enabled": true,
"returnSigningSecret": true,
"rotateSecretIfUnavailable": true,
"rotateSecret": false
}
'HttpResponse<String> response = Unirest.put("https://uat-api.clinkbill.com/api/webhook/endpoints/ensure")
.header("X-Timestamp", "<x-timestamp>")
.header("X-API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"url\": \"https://example.com/api/clink/webhook\",\n \"events\": [\n \"session.complete\",\n \"order.succeeded\"\n ],\n \"description\": \"Created through the API\",\n \"enabled\": true,\n \"returnSigningSecret\": true,\n \"rotateSecretIfUnavailable\": true,\n \"rotateSecret\": false\n}")
.asString();import requests
url = "https://uat-api.clinkbill.com/api/webhook/endpoints/ensure"
payload = {
"url": "https://example.com/api/clink/webhook",
"events": ["session.complete", "order.succeeded"],
"description": "Created through the API",
"enabled": True,
"returnSigningSecret": True,
"rotateSecretIfUnavailable": True,
"rotateSecret": False
}
headers = {
"X-Timestamp": "<x-timestamp>",
"X-API-KEY": "<api-key>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {
'X-Timestamp': '<x-timestamp>',
'X-API-KEY': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: 'https://example.com/api/clink/webhook',
events: ['session.complete', 'order.succeeded'],
description: 'Created through the API',
enabled: true,
returnSigningSecret: true,
rotateSecretIfUnavailable: true,
rotateSecret: false
})
};
fetch('https://uat-api.clinkbill.com/api/webhook/endpoints/ensure', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"code": 200,
"msg": "Success",
"data": {
"source": "created",
"endpoint": {
"id": "whk_xxxxx",
"url": "https://example.com/api/clink/webhook",
"events": [
"session.complete",
"order.succeeded"
],
"enabled": true,
"signingSecret": "whsec_xxxxx",
"maskedSigningSecret": "whsec_...abcd",
"description": "Created through the API",
"createdAt": 1782112780956,
"updatedAt": 1782113780956
},
"signingSecretAvailable": true,
"signingSecretUnavailableReason": "EXISTING_SECRET_NOT_RETURNABLE",
"nextAction": "CALL_ROTATE_SECRET_OR_RETRY_ENSURE_WITH_ROTATE_SECRET_IF_UNAVAILABLE"
}
}{
"code": 123,
"msg": "<string>",
"data": "<unknown>"
}{
"code": 123,
"msg": "<string>",
"data": "<unknown>"
}Ensure Webhook Endpoint
Create or update a webhook endpoint by URL. This endpoint is designed for idempotent setup flows where applications need to safely create or reconcile a webhook endpoint. For existing endpoints, Clink does not return the stored plaintext signing secret unless the secret is rotated.
curl --request PUT \
--url https://uat-api.clinkbill.com/api/webhook/endpoints/ensure \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <api-key>' \
--header 'X-Timestamp: <x-timestamp>' \
--data '
{
"url": "https://example.com/api/clink/webhook",
"events": [
"session.complete",
"order.succeeded"
],
"description": "Created through the API",
"enabled": true,
"returnSigningSecret": true,
"rotateSecretIfUnavailable": true,
"rotateSecret": false
}
'HttpResponse<String> response = Unirest.put("https://uat-api.clinkbill.com/api/webhook/endpoints/ensure")
.header("X-Timestamp", "<x-timestamp>")
.header("X-API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"url\": \"https://example.com/api/clink/webhook\",\n \"events\": [\n \"session.complete\",\n \"order.succeeded\"\n ],\n \"description\": \"Created through the API\",\n \"enabled\": true,\n \"returnSigningSecret\": true,\n \"rotateSecretIfUnavailable\": true,\n \"rotateSecret\": false\n}")
.asString();import requests
url = "https://uat-api.clinkbill.com/api/webhook/endpoints/ensure"
payload = {
"url": "https://example.com/api/clink/webhook",
"events": ["session.complete", "order.succeeded"],
"description": "Created through the API",
"enabled": True,
"returnSigningSecret": True,
"rotateSecretIfUnavailable": True,
"rotateSecret": False
}
headers = {
"X-Timestamp": "<x-timestamp>",
"X-API-KEY": "<api-key>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {
'X-Timestamp': '<x-timestamp>',
'X-API-KEY': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: 'https://example.com/api/clink/webhook',
events: ['session.complete', 'order.succeeded'],
description: 'Created through the API',
enabled: true,
returnSigningSecret: true,
rotateSecretIfUnavailable: true,
rotateSecret: false
})
};
fetch('https://uat-api.clinkbill.com/api/webhook/endpoints/ensure', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"code": 200,
"msg": "Success",
"data": {
"source": "created",
"endpoint": {
"id": "whk_xxxxx",
"url": "https://example.com/api/clink/webhook",
"events": [
"session.complete",
"order.succeeded"
],
"enabled": true,
"signingSecret": "whsec_xxxxx",
"maskedSigningSecret": "whsec_...abcd",
"description": "Created through the API",
"createdAt": 1782112780956,
"updatedAt": 1782113780956
},
"signingSecretAvailable": true,
"signingSecretUnavailableReason": "EXISTING_SECRET_NOT_RETURNABLE",
"nextAction": "CALL_ROTATE_SECRET_OR_RETRY_ENSURE_WITH_ROTATE_SECRET_IF_UNAVAILABLE"
}
}{
"code": 123,
"msg": "<string>",
"data": "<unknown>"
}{
"code": 123,
"msg": "<string>",
"data": "<unknown>"
}Authorizations
Your secret API key obtained from the Clink dashboard (Developers section)
Headers
Current timestamp in milliseconds since Unix epoch (required for request signing)
"1783513683000"
Body
HTTPS endpoint URL. Used as the idempotency key for this merchant.
512"https://example.com/api/clink/webhook"
Event names to subscribe to. Numeric event codes are not accepted.
1Supported webhook event name. Public API requests use event names, not numeric event codes.
order.created, order.succeeded, order.failed, refund.created, refund.succeeded, refund.failed, subscription.created, subscription.trialing, subscription.activated, subscription.incomplete_expired, subscription.past_due, subscription.cancelled, invoice.open, invoice.paid, invoice.void, order.next_action, subscription.updated.plan_changed, subscription.updated.plan_change_canceled, subscription.updated.renewed, subscription.updated.cancel_at_period_end_set, subscription.updated.cancel_at_period_end_revoked, session.complete, session.expired, dispute.created, dispute.updated, dispute.won, dispute.lost, dispute.closed, customer.verify, payment_method.added, payment_method.default_change, risk_rule.updated, agent_order.succeeded, agent_order.failed, agent_refund.succeeded, agent_refund.failed, agent_refund.approved, agent_refund.rejected, payment_method.update, purchase_instruction.created, purchase_instruction.activated, purchase_instruction.updated, purchase_instruction.cancelled, vic_device.binding_succeeded ["session.complete", "order.succeeded"]
Optional endpoint description.
512"Created through the API"
Whether the endpoint is enabled.
Whether the caller wants a plaintext signingSecret when available.
If true, rotate the existing secret when the stored secret cannot be returned as plaintext.
If true, always rotate the signing secret for an existing endpoint.