Create Webhook Endpoint
curl --request POST \
--url https://api.hopnow.io/v1/customers/{customer_id}/webhook-endpoints \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"url": "<string>",
"events": [
{}
],
"description": "<string>"
}
'import requests
url = "https://api.hopnow.io/v1/customers/{customer_id}/webhook-endpoints"
payload = {
"url": "<string>",
"events": [{}],
"description": "<string>"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({url: '<string>', events: [{}], description: '<string>'})
};
fetch('https://api.hopnow.io/v1/customers/{customer_id}/webhook-endpoints', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.hopnow.io/v1/customers/{customer_id}/webhook-endpoints",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'url' => '<string>',
'events' => [
[
]
],
'description' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.hopnow.io/v1/customers/{customer_id}/webhook-endpoints"
payload := strings.NewReader("{\n \"url\": \"<string>\",\n \"events\": [\n {}\n ],\n \"description\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
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))
}HttpResponse<String> response = Unirest.post("https://api.hopnow.io/v1/customers/{customer_id}/webhook-endpoints")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"url\": \"<string>\",\n \"events\": [\n {}\n ],\n \"description\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hopnow.io/v1/customers/{customer_id}/webhook-endpoints")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"url\": \"<string>\",\n \"events\": [\n {}\n ],\n \"description\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"object": "<string>",
"url": "<string>",
"events": [
{}
],
"description": "<string>",
"secret": "<string>",
"warning": "<string>",
"created": "<string>",
"updated": "<string>",
"created_by": "<string>",
"updated_by": "<string>",
"last_used_at": "<string>",
"deleted_at": "<string>"
}Webhook Endpoints
Create Webhook Endpoint
Create a new webhook endpoint to receive event notifications
POST
/
v1
/
customers
/
{customer_id}
/
webhook-endpoints
Create Webhook Endpoint
curl --request POST \
--url https://api.hopnow.io/v1/customers/{customer_id}/webhook-endpoints \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"url": "<string>",
"events": [
{}
],
"description": "<string>"
}
'import requests
url = "https://api.hopnow.io/v1/customers/{customer_id}/webhook-endpoints"
payload = {
"url": "<string>",
"events": [{}],
"description": "<string>"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({url: '<string>', events: [{}], description: '<string>'})
};
fetch('https://api.hopnow.io/v1/customers/{customer_id}/webhook-endpoints', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.hopnow.io/v1/customers/{customer_id}/webhook-endpoints",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'url' => '<string>',
'events' => [
[
]
],
'description' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.hopnow.io/v1/customers/{customer_id}/webhook-endpoints"
payload := strings.NewReader("{\n \"url\": \"<string>\",\n \"events\": [\n {}\n ],\n \"description\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
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))
}HttpResponse<String> response = Unirest.post("https://api.hopnow.io/v1/customers/{customer_id}/webhook-endpoints")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"url\": \"<string>\",\n \"events\": [\n {}\n ],\n \"description\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hopnow.io/v1/customers/{customer_id}/webhook-endpoints")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"url\": \"<string>\",\n \"events\": [\n {}\n ],\n \"description\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"object": "<string>",
"url": "<string>",
"events": [
{}
],
"description": "<string>",
"secret": "<string>",
"warning": "<string>",
"created": "<string>",
"updated": "<string>",
"created_by": "<string>",
"updated_by": "<string>",
"last_used_at": "<string>",
"deleted_at": "<string>"
}Registers a URL that Hop posts events to, and returns the signing secret for that endpoint. Requires
write access on the webhooks scope.
The secret is returned only in this response and is never shown again. Store it before you discard the response; if you lose it, delete the endpoint and create a new one.
This endpoint does not take an Idempotency-Key. A retried request creates a second endpoint with its own secret, and both endpoints then receive every event they subscribe to.
Path Parameters
string
required
The customer’s external ID (starts with
cus_)Request Body
string
required
The URL events are posted to. Must use
https and include a host; http URLs are rejected. Normalised before storage, so a bare host gains a trailing slash and https://api.example.com comes back as https://api.example.com/: compare against the url in the response, not the string you sent, and expect the normalised form if your receiver checks the request path.array
required
Event types to subscribe to. At least one is required, and each must be one of:
payin.received, payin.returned, payout.created, payout.completed, payout.failed, transfer.completed, transfer.failed, account.created, account.updated, payout_destination.updatedAny other name is rejected. See Webhook Events for what each one carries.string
Optional description for the endpoint (maximum 255 characters)
Response
string
Webhook endpoint identifier (starts with
wh_)string
Always returns
"webhook_endpoint"string
The stored delivery URL, after normalisation
array
Subscribed event types
string
The description, or
nullstring
Signing secret: an 86-character URL-safe string, returned only on this response. Use it verbatim as the HMAC key; see Webhook Security.
string
Fixed reminder that the secret is not shown again
string
ISO 8601 timestamp when created
string
ISO 8601 timestamp when last updated
string
Identifier of the actor that created the endpoint, or
nullstring
Identifier of the actor that last updated the endpoint, or
nullstring
Reserved; always
null.string
Deletion timestamp.
null for a newly created endpoint.Errors
| Status | code | When |
|---|---|---|
422 | VALIDATION_ERROR | url is not an https URL with a host, events is empty or missing, or description is longer than 255 characters |
422 | INVALID_FIELD_VALUE | events contains a name Hop does not emit; details.field is "events", details.value lists the rejected names and details.allowed_values the accepted set |
Request Example
{
"url": "https://api.mycompany.com/webhooks/hopnow",
"events": ["payin.received", "payout.completed", "payout.failed"],
"description": "Production webhook for payment activity"
}
Response Example
{
"id": "wh_g738im3ueie9s9zexmf9cl87",
"object": "webhook_endpoint",
"url": "https://api.mycompany.com/webhooks/hopnow",
"events": ["payin.received", "payout.completed", "payout.failed"],
"description": "Production webhook for payment activity",
"secret": "example_webhook_signing_secret",
"warning": "Store this secret securely. It will not be shown again.",
"created": "2026-07-15T02:00:00Z",
"updated": "2026-07-15T02:00:00Z",
"created_by": null,
"updated_by": null,
"last_used_at": null,
"deleted_at": null
}