curl --request POST \
--url https://api.posthook.io/v1/hooks \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"path": "/webhooks/reminder",
"data": {
"user_id": "123"
},
"postAt": "2026-03-14T12:00:00Z",
"postAtLocal": "2026-03-15T13:00:00",
"timezone": "America/New_York",
"postIn": "1h30m"
}
'import requests
url = "https://api.posthook.io/v1/hooks"
payload = {
"path": "/webhooks/reminder",
"data": { "user_id": "123" },
"postAt": "2026-03-14T12:00:00Z",
"postAtLocal": "2026-03-15T13:00:00",
"timezone": "America/New_York",
"postIn": "1h30m"
}
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({
path: '/webhooks/reminder',
data: {user_id: '123'},
postAt: '2026-03-14T12:00:00Z',
postAtLocal: '2026-03-15T13:00:00',
timezone: 'America/New_York',
postIn: '1h30m'
})
};
fetch('https://api.posthook.io/v1/hooks', 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.posthook.io/v1/hooks",
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([
'path' => '/webhooks/reminder',
'data' => [
'user_id' => '123'
],
'postAt' => '2026-03-14T12:00:00Z',
'postAtLocal' => '2026-03-15T13:00:00',
'timezone' => 'America/New_York',
'postIn' => '1h30m'
]),
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.posthook.io/v1/hooks"
payload := strings.NewReader("{\n \"path\": \"/webhooks/reminder\",\n \"data\": {\n \"user_id\": \"123\"\n },\n \"postAt\": \"2026-03-14T12:00:00Z\",\n \"postAtLocal\": \"2026-03-15T13:00:00\",\n \"timezone\": \"America/New_York\",\n \"postIn\": \"1h30m\"\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.posthook.io/v1/hooks")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"path\": \"/webhooks/reminder\",\n \"data\": {\n \"user_id\": \"123\"\n },\n \"postAt\": \"2026-03-14T12:00:00Z\",\n \"postAtLocal\": \"2026-03-15T13:00:00\",\n \"timezone\": \"America/New_York\",\n \"postIn\": \"1h30m\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.posthook.io/v1/hooks")
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 \"path\": \"/webhooks/reminder\",\n \"data\": {\n \"user_id\": \"123\"\n },\n \"postAt\": \"2026-03-14T12:00:00Z\",\n \"postAtLocal\": \"2026-03-15T13:00:00\",\n \"timezone\": \"America/New_York\",\n \"postIn\": \"1h30m\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "<string>",
"path": "<string>",
"domain": "<string>",
"data": {},
"postAt": "2023-11-07T05:31:56Z",
"status": "pending",
"postDurationSeconds": 123,
"createdAt": "2023-11-07T05:31:56Z",
"updatedAt": "2023-11-07T05:31:56Z",
"attempts": 123,
"failureError": "<string>",
"tryAt": "2023-11-07T05:31:56Z",
"wasNotified": true,
"sequenceData": {
"sequenceID": "<string>",
"stepName": "<string>",
"sequenceLastRunAt": "2023-11-07T05:31:56Z"
}
}
}Schedule Hook
Schedule a new hook for delivery at a specific time. Supports UTC, local-time, and relative-delay scheduling modes.
curl --request POST \
--url https://api.posthook.io/v1/hooks \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"path": "/webhooks/reminder",
"data": {
"user_id": "123"
},
"postAt": "2026-03-14T12:00:00Z",
"postAtLocal": "2026-03-15T13:00:00",
"timezone": "America/New_York",
"postIn": "1h30m"
}
'import requests
url = "https://api.posthook.io/v1/hooks"
payload = {
"path": "/webhooks/reminder",
"data": { "user_id": "123" },
"postAt": "2026-03-14T12:00:00Z",
"postAtLocal": "2026-03-15T13:00:00",
"timezone": "America/New_York",
"postIn": "1h30m"
}
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({
path: '/webhooks/reminder',
data: {user_id: '123'},
postAt: '2026-03-14T12:00:00Z',
postAtLocal: '2026-03-15T13:00:00',
timezone: 'America/New_York',
postIn: '1h30m'
})
};
fetch('https://api.posthook.io/v1/hooks', 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.posthook.io/v1/hooks",
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([
'path' => '/webhooks/reminder',
'data' => [
'user_id' => '123'
],
'postAt' => '2026-03-14T12:00:00Z',
'postAtLocal' => '2026-03-15T13:00:00',
'timezone' => 'America/New_York',
'postIn' => '1h30m'
]),
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.posthook.io/v1/hooks"
payload := strings.NewReader("{\n \"path\": \"/webhooks/reminder\",\n \"data\": {\n \"user_id\": \"123\"\n },\n \"postAt\": \"2026-03-14T12:00:00Z\",\n \"postAtLocal\": \"2026-03-15T13:00:00\",\n \"timezone\": \"America/New_York\",\n \"postIn\": \"1h30m\"\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.posthook.io/v1/hooks")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"path\": \"/webhooks/reminder\",\n \"data\": {\n \"user_id\": \"123\"\n },\n \"postAt\": \"2026-03-14T12:00:00Z\",\n \"postAtLocal\": \"2026-03-15T13:00:00\",\n \"timezone\": \"America/New_York\",\n \"postIn\": \"1h30m\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.posthook.io/v1/hooks")
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 \"path\": \"/webhooks/reminder\",\n \"data\": {\n \"user_id\": \"123\"\n },\n \"postAt\": \"2026-03-14T12:00:00Z\",\n \"postAtLocal\": \"2026-03-15T13:00:00\",\n \"timezone\": \"America/New_York\",\n \"postIn\": \"1h30m\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "<string>",
"path": "<string>",
"domain": "<string>",
"data": {},
"postAt": "2023-11-07T05:31:56Z",
"status": "pending",
"postDurationSeconds": 123,
"createdAt": "2023-11-07T05:31:56Z",
"updatedAt": "2023-11-07T05:31:56Z",
"attempts": 123,
"failureError": "<string>",
"tryAt": "2023-11-07T05:31:56Z",
"wasNotified": true,
"sequenceData": {
"sequenceID": "<string>",
"stepName": "<string>",
"sequenceLastRunAt": "2023-11-07T05:31:56Z"
}
}
}URL Resolution
When you schedule a hook, you provide apath (e.g. /webhooks/remind).
Posthook constructs the full destination URL by combining your Project Domain with this path.
Destination URL =For example, if your Project Domain isProject Domain+path
api.myapp.com and you schedule a hook with path /webhooks/payment, we will POST to https://api.myapp.com/webhooks/payment (Posthook enforces HTTPS).
Usage Patterns
- User Engagement: Schedule event reminders and abandoned cart recovery emails.
- Auto-Expiry (TTL): Schedule the deletion of temporary resources (e.g. shared links) at the moment of creation.
- Recursive Polling: Periodically check a long-running job (e.g. video encoding) until it completes.
- Debouncing: Prevent duplicate processing by verifying event freshness.
Authorizations
Body
The endpoint path for delivery.
"/webhooks/reminder"
Arbitrary JSON payload delivered with the hook.
{ "user_id": "123" }
RFC 3339 timestamp in UTC for delivery. Mutually exclusive with postAtLocal + timezone. Timestamps in the past are delivered immediately.
"2026-03-14T12:00:00Z"
ISO 8601 local datetime without offset, in YYYY-MM-DDTHH:MM:SS format (e.g. 2026-03-15T13:00:00). Must be used with timezone. Mutually exclusive with postAt.
"2026-03-15T13:00:00"
IANA Time Zone identifier (e.g. America/New_York). Required when using postAtLocal. Forbidden with postAt and postIn.
"America/New_York"
Relative delay from now as a duration string (e.g., 5m, 2h, 1d12h). Units: d (days), h (hours), m (minutes), s (seconds). Min 1s, max 365d. Mutually exclusive with postAt and postAtLocal. Cannot be used with timezone.
"1h30m"
Per-hook retry configuration. Overrides the project's default retry settings for this hook.
Show child attributes
Show child attributes
Response
Hook scheduled
Show child attributes
Show child attributes
Was this page helpful?