Audio Started
curl --request POST \
--url https://your-webhook.com/audio.started \
--header 'Content-Type: application/json' \
--header 'magic-hour-event-signature: <magic-hour-event-signature>' \
--header 'magic-hour-event-timestamp: <magic-hour-event-timestamp>' \
--data '
{
"type": "audio.started",
"payload": {
"id": "cuid-example",
"name": "Example Name",
"status": "complete",
"type": "VOICE_GENERATOR",
"created_at": "2023-11-07T05:31:56Z",
"enabled": true,
"credits_charged": 2,
"downloads": [
{
"url": "https://videos.magichour.ai/id/output.wav",
"expires_at": "2024-10-19T05:16:19.027Z"
}
],
"error": null
}
}
'import requests
url = "https://your-webhook.com/audio.started"
payload = {
"type": "audio.started",
"payload": {
"id": "cuid-example",
"name": "Example Name",
"status": "complete",
"type": "VOICE_GENERATOR",
"created_at": "2023-11-07T05:31:56Z",
"enabled": True,
"credits_charged": 2,
"downloads": [
{
"url": "https://videos.magichour.ai/id/output.wav",
"expires_at": "2024-10-19T05:16:19.027Z"
}
],
"error": None
}
}
headers = {
"magic-hour-event-signature": "<magic-hour-event-signature>",
"magic-hour-event-timestamp": "<magic-hour-event-timestamp>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'magic-hour-event-signature': '<magic-hour-event-signature>',
'magic-hour-event-timestamp': '<magic-hour-event-timestamp>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
type: 'audio.started',
payload: {
id: 'cuid-example',
name: 'Example Name',
status: 'complete',
type: 'VOICE_GENERATOR',
created_at: '2023-11-07T05:31:56Z',
enabled: true,
credits_charged: 2,
downloads: [
{
url: 'https://videos.magichour.ai/id/output.wav',
expires_at: '2024-10-19T05:16:19.027Z'
}
],
error: null
}
})
};
fetch('https://your-webhook.com/audio.started', 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://your-webhook.com/audio.started",
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([
'type' => 'audio.started',
'payload' => [
'id' => 'cuid-example',
'name' => 'Example Name',
'status' => 'complete',
'type' => 'VOICE_GENERATOR',
'created_at' => '2023-11-07T05:31:56Z',
'enabled' => true,
'credits_charged' => 2,
'downloads' => [
[
'url' => 'https://videos.magichour.ai/id/output.wav',
'expires_at' => '2024-10-19T05:16:19.027Z'
]
],
'error' => null
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"magic-hour-event-signature: <magic-hour-event-signature>",
"magic-hour-event-timestamp: <magic-hour-event-timestamp>"
],
]);
$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://your-webhook.com/audio.started"
payload := strings.NewReader("{\n \"type\": \"audio.started\",\n \"payload\": {\n \"id\": \"cuid-example\",\n \"name\": \"Example Name\",\n \"status\": \"complete\",\n \"type\": \"VOICE_GENERATOR\",\n \"created_at\": \"2023-11-07T05:31:56Z\",\n \"enabled\": true,\n \"credits_charged\": 2,\n \"downloads\": [\n {\n \"url\": \"https://videos.magichour.ai/id/output.wav\",\n \"expires_at\": \"2024-10-19T05:16:19.027Z\"\n }\n ],\n \"error\": null\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("magic-hour-event-signature", "<magic-hour-event-signature>")
req.Header.Add("magic-hour-event-timestamp", "<magic-hour-event-timestamp>")
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://your-webhook.com/audio.started")
.header("magic-hour-event-signature", "<magic-hour-event-signature>")
.header("magic-hour-event-timestamp", "<magic-hour-event-timestamp>")
.header("Content-Type", "application/json")
.body("{\n \"type\": \"audio.started\",\n \"payload\": {\n \"id\": \"cuid-example\",\n \"name\": \"Example Name\",\n \"status\": \"complete\",\n \"type\": \"VOICE_GENERATOR\",\n \"created_at\": \"2023-11-07T05:31:56Z\",\n \"enabled\": true,\n \"credits_charged\": 2,\n \"downloads\": [\n {\n \"url\": \"https://videos.magichour.ai/id/output.wav\",\n \"expires_at\": \"2024-10-19T05:16:19.027Z\"\n }\n ],\n \"error\": null\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://your-webhook.com/audio.started")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["magic-hour-event-signature"] = '<magic-hour-event-signature>'
request["magic-hour-event-timestamp"] = '<magic-hour-event-timestamp>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"type\": \"audio.started\",\n \"payload\": {\n \"id\": \"cuid-example\",\n \"name\": \"Example Name\",\n \"status\": \"complete\",\n \"type\": \"VOICE_GENERATOR\",\n \"created_at\": \"2023-11-07T05:31:56Z\",\n \"enabled\": true,\n \"credits_charged\": 2,\n \"downloads\": [\n {\n \"url\": \"https://videos.magichour.ai/id/output.wav\",\n \"expires_at\": \"2024-10-19T05:16:19.027Z\"\n }\n ],\n \"error\": null\n }\n}"
response = http.request(request)
puts response.read_body{
"message": "Success message from your endpoint"
}{
"message": "Error message from your endpoint"
}{
"message": "Error message from your endpoint"
}Audio Events
Audio Started
Magic Hour notifies your server when an audio project begins processing. Webhook reference for timestamp and signature headers plus JSON body for voice and audio jobs.
POST
/
audio.started
Audio Started
curl --request POST \
--url https://your-webhook.com/audio.started \
--header 'Content-Type: application/json' \
--header 'magic-hour-event-signature: <magic-hour-event-signature>' \
--header 'magic-hour-event-timestamp: <magic-hour-event-timestamp>' \
--data '
{
"type": "audio.started",
"payload": {
"id": "cuid-example",
"name": "Example Name",
"status": "complete",
"type": "VOICE_GENERATOR",
"created_at": "2023-11-07T05:31:56Z",
"enabled": true,
"credits_charged": 2,
"downloads": [
{
"url": "https://videos.magichour.ai/id/output.wav",
"expires_at": "2024-10-19T05:16:19.027Z"
}
],
"error": null
}
}
'import requests
url = "https://your-webhook.com/audio.started"
payload = {
"type": "audio.started",
"payload": {
"id": "cuid-example",
"name": "Example Name",
"status": "complete",
"type": "VOICE_GENERATOR",
"created_at": "2023-11-07T05:31:56Z",
"enabled": True,
"credits_charged": 2,
"downloads": [
{
"url": "https://videos.magichour.ai/id/output.wav",
"expires_at": "2024-10-19T05:16:19.027Z"
}
],
"error": None
}
}
headers = {
"magic-hour-event-signature": "<magic-hour-event-signature>",
"magic-hour-event-timestamp": "<magic-hour-event-timestamp>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'magic-hour-event-signature': '<magic-hour-event-signature>',
'magic-hour-event-timestamp': '<magic-hour-event-timestamp>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
type: 'audio.started',
payload: {
id: 'cuid-example',
name: 'Example Name',
status: 'complete',
type: 'VOICE_GENERATOR',
created_at: '2023-11-07T05:31:56Z',
enabled: true,
credits_charged: 2,
downloads: [
{
url: 'https://videos.magichour.ai/id/output.wav',
expires_at: '2024-10-19T05:16:19.027Z'
}
],
error: null
}
})
};
fetch('https://your-webhook.com/audio.started', 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://your-webhook.com/audio.started",
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([
'type' => 'audio.started',
'payload' => [
'id' => 'cuid-example',
'name' => 'Example Name',
'status' => 'complete',
'type' => 'VOICE_GENERATOR',
'created_at' => '2023-11-07T05:31:56Z',
'enabled' => true,
'credits_charged' => 2,
'downloads' => [
[
'url' => 'https://videos.magichour.ai/id/output.wav',
'expires_at' => '2024-10-19T05:16:19.027Z'
]
],
'error' => null
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"magic-hour-event-signature: <magic-hour-event-signature>",
"magic-hour-event-timestamp: <magic-hour-event-timestamp>"
],
]);
$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://your-webhook.com/audio.started"
payload := strings.NewReader("{\n \"type\": \"audio.started\",\n \"payload\": {\n \"id\": \"cuid-example\",\n \"name\": \"Example Name\",\n \"status\": \"complete\",\n \"type\": \"VOICE_GENERATOR\",\n \"created_at\": \"2023-11-07T05:31:56Z\",\n \"enabled\": true,\n \"credits_charged\": 2,\n \"downloads\": [\n {\n \"url\": \"https://videos.magichour.ai/id/output.wav\",\n \"expires_at\": \"2024-10-19T05:16:19.027Z\"\n }\n ],\n \"error\": null\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("magic-hour-event-signature", "<magic-hour-event-signature>")
req.Header.Add("magic-hour-event-timestamp", "<magic-hour-event-timestamp>")
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://your-webhook.com/audio.started")
.header("magic-hour-event-signature", "<magic-hour-event-signature>")
.header("magic-hour-event-timestamp", "<magic-hour-event-timestamp>")
.header("Content-Type", "application/json")
.body("{\n \"type\": \"audio.started\",\n \"payload\": {\n \"id\": \"cuid-example\",\n \"name\": \"Example Name\",\n \"status\": \"complete\",\n \"type\": \"VOICE_GENERATOR\",\n \"created_at\": \"2023-11-07T05:31:56Z\",\n \"enabled\": true,\n \"credits_charged\": 2,\n \"downloads\": [\n {\n \"url\": \"https://videos.magichour.ai/id/output.wav\",\n \"expires_at\": \"2024-10-19T05:16:19.027Z\"\n }\n ],\n \"error\": null\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://your-webhook.com/audio.started")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["magic-hour-event-signature"] = '<magic-hour-event-signature>'
request["magic-hour-event-timestamp"] = '<magic-hour-event-timestamp>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"type\": \"audio.started\",\n \"payload\": {\n \"id\": \"cuid-example\",\n \"name\": \"Example Name\",\n \"status\": \"complete\",\n \"type\": \"VOICE_GENERATOR\",\n \"created_at\": \"2023-11-07T05:31:56Z\",\n \"enabled\": true,\n \"credits_charged\": 2,\n \"downloads\": [\n {\n \"url\": \"https://videos.magichour.ai/id/output.wav\",\n \"expires_at\": \"2024-10-19T05:16:19.027Z\"\n }\n ],\n \"error\": null\n }\n}"
response = http.request(request)
puts response.read_body{
"message": "Success message from your endpoint"
}{
"message": "Error message from your endpoint"
}{
"message": "Error message from your endpoint"
}Headers
A 64-character hexadecimal HMAC-SHA256 signature. Use the complete webhook secret, not an API key, to sign the timestamp header, a period, and the exact raw request body.
Example:
"3e771b50c..."
Unix time in seconds for this delivery attempt. Reject missing or invalid timestamps; a five-minute window before or after the current time is recommended to limit replay.
Example:
"1730742038"
Body
application/json
Body
Response
Success
Success
Example:
"Success message from your endpoint"
Was this page helpful?