Examples
To setup your webhook URL:
{
"notification": {
"type": "http",
"url": "https://yourserver/api/coconut/webhook"
}
}
Get notified via SNS (Simple Notification Service) from AWS:
{
"notification": {
"type": "sns",
"region": "us-east-1",
"topic_arn": "arn:...",
"credentials": {
"access_key_id": "xxx",
"secret_access_key": "xxx"
}
}
}
Structure of the JSON payload:
{
"job_id": "DQbYa9WvYQYiLN",
"event": "job.completed",
"metadata": false,
"data": {
"type": "job",
"status": "job.completed",
"progress": "100%",
"id": "DQbYa9WvYQYiLN",
"created_at": "2021-02-16 09:37:33 +0000",
"completed_at": "2021-02-16 09:37:55 +0000",
"input": {
"status": "input.transferred"
},
"outputs": [
{
"key": "mp4:trailer",
"type": "video",
"format": "mp4:240p::quality=2",
"url": "http://cdn.coconut.co/trailer.mp4",
"status": "video.encoded"
},
{
"key": "mp4",
"type": "video",
"format": "mp4:::quality=4",
"url": "http://cdn.coconut.co/video.mp4",
"status": "video.encoded"
},
{
"key": "jpg:reg",
"type": "image",
"format": "jpg:400x",
"urls": [
"http://cdn.coconut.co/thumb_01.jpg",
"http://cdn.coconut.co/thumb_02.jpg",
"http://cdn.coconut.co/thumb_03.jpg",
"http://cdn.coconut.co/thumb_04.jpg",
"http://cdn.coconut.co/thumb_05.jpg",
"http://cdn.coconut.co/thumb_06.jpg",
"http://cdn.coconut.co/thumb_07.jpg",
"http://cdn.coconut.co/thumb_08.jpg",
"http://cdn.coconut.co/thumb_09.jpg",
"http://cdn.coconut.co/thumb_10.jpg"
],
"status": "image.created"
},
{
"key": "jpg:sq",
"type": "image",
"format": "jpg:400x400",
"urls": [
"http://cdn.coconut.co/thumb_sq_01.jpg",
"http://cdn.coconut.co/thumb_sq_02.jpg",
"http://cdn.coconut.co/thumb_sq_03.jpg",
"http://cdn.coconut.co/thumb_sq_04.jpg"
],
"status": "image.created"
}
]
}
}
HTTP Notification (Webhook)
Parameters
Name | Type | Default | Required |
---|---|---|---|
type Type must be http . | string | http | Yes |
url HTTP URL that will receive the POST request. | string | Yes | |
params The parameters that will be sent a query string. Useful to add custom information like internal ID. |
hash | No | |
metadata Receive metadata in the JSON payload. See example. |
bool | false | No |
events Receive a notification for each event. See example. |
bool | false | No |
SNS Notification
Parameters
Name | Type | Default | Required |
---|---|---|---|
type Type must be sns . | string | sns | Yes |
credentials Keys to authenticate against AWS SNS. | hash | Yes | |
access_key_id The AWS Access Key Id. |
string | Yes | |
secret_access_key The AWS Secret Access Key. |
string | Yes | |
region The bucket region. By default, we find the right region automatically. Supported regions are: us-east-2 us-east-1 us-west-1 us-west-2 af-south-1 ap-east-1 ap-south-1 ap-northeast-3 ap-northeast-2 ap-southeast-1 ap-southeast-2 ap-northeast-1 ca-central-1 cn-north-1 cn-northwest-1 eu-central-1 eu-west-1 eu-west-2 eu-south-1 eu-west-3 eu-north-1 . |
string | Yes | |
topic_arn The topic arn. |
string | Yes | |
params Will populate the SNS message attributes. Useful to add custom information like internal ID. |
hash | No | |
metadata Receive metadata in the JSON payload. See example. |
bool | false | No |
events Receive a notification for each event. See example. |
bool | false | No |
Custom parameters
Let's say you have videos attached to a Post in your application. When creating the coconut job, simply add the post_id to the notification params so you will know the notification is related to the given post id when your application will receive it.
{
"notification": {
"type": "http",
"url": "https://yourserver/api/coconut/webhook",
"params": {
"post_id": 1234
}
}
}
Metadata
You can receive the metadata of the source and output videos as well by using the parameter metadata.
{
"notification": {
"type": "http",
"url": "https://yourserver/api/coconut/webhook",
"metadata": true
}
}
Example of a notification with metadata enabled:
{
"job_id": "bH6aSkWMEEPu2h",
"event": "job.completed",
"metadata": true,
"data": {
"type": "job",
"status": "job.completed",
"progress": "100%",
"id": "bH6aSkWMEEPu2h",
"created_at": "2021-02-16 09:31:56 +0000",
"completed_at": "2021-02-16 09:32:55 +0000",
"input": {
"status": "input.transferred",
"metadata": {
"streams": [
{
"index": 0,
"codec_name": "h264",
"codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
"profile": "High",
"codec_type": "video",
"codec_time_base": "1/60",
"codec_tag_string": "avc1",
"codec_tag": "0x31637661",
"width": 854,
"height": 480,
"coded_width": 864,
"coded_height": 480,
"has_b_frames": 2,
"sample_aspect_ratio": "1280:1281",
"display_aspect_ratio": "16:9",
"pix_fmt": "yuv420p",
"level": 31,
"chroma_location": "left",
"refs": 1,
"is_avc": "true",
"nal_length_size": "4",
"r_frame_rate": "30/1",
"avg_frame_rate": "30/1",
"time_base": "1/15360",
"start_pts": 323,
"start_time": "0.021029",
"duration_ts": 922624,
"duration": "60.066667",
"bit_rate": "865345",
"bits_per_raw_sample": "8",
"nb_frames": "1802",
"disposition": {
"default": 1,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
},
"tags": {
"language": "und",
"handler_name": "VideoHandler"
}
},
{
"index": 1,
"codec_name": "aac",
"codec_long_name": "AAC (Advanced Audio Coding)",
"profile": "LC",
"codec_type": "audio",
"codec_time_base": "1/48000",
"codec_tag_string": "mp4a",
"codec_tag": "0x6134706d",
"sample_fmt": "fltp",
"sample_rate": "48000",
"channels": 6,
"channel_layout": "5.1",
"bits_per_sample": 0,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/48000",
"start_pts": 0,
"start_time": "0.000000",
"duration_ts": 2880512,
"duration": "60.010667",
"bit_rate": "64505",
"max_bit_rate": "64505",
"nb_frames": "2813",
"disposition": {
"default": 1,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
},
"tags": {
"language": "und",
"handler_name": "SoundHandler"
}
}
],
"format": {
"filename": "http://aws-us-east-1-media.coconut.co.s3.amazonaws.com/16/09/5470583642b55cb7f33dbed749c5d67e/0",
"nb_streams": 2,
"nb_programs": 0,
"format_name": "mov,mp4,m4a,3gp,3g2,mj2",
"format_long_name": "QuickTime / MOV",
"start_time": "0.000000",
"duration": "60.067000",
"size": "7047204",
"bit_rate": "938579",
"probe_score": 100,
"tags": {
"major_brand": "isom",
"minor_version": "512",
"compatible_brands": "isomiso2avc1mp41",
"title": "Big Buck Bunny, Sunflower version",
"artist": "Blender Foundation 2008, Janus Bager Kristensen 2013",
"composer": "Sacha Goedegebure",
"encoder": "Lavf57.25.100",
"comment": "Creative Commons Attribution 3.0 - http://bbb3d.renderfarming.net",
"genre": "Animation"
}
}
}
},
"outputs": [
{
"key": "mp4",
"type": "video",
"format": "mp4",
"url": "http://cdn.coconut.co/test.mp4",
"status": "video.encoded",
"metadata": {
"streams": [
{
"index": 0,
"codec_name": "h264",
"codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
"profile": "Constrained Baseline",
"codec_type": "video",
"codec_time_base": "1/60",
"codec_tag_string": "avc1",
"codec_tag": "0x31637661",
"width": 854,
"height": 480,
"coded_width": 864,
"coded_height": 480,
"has_b_frames": 0,
"sample_aspect_ratio": "1280:1281",
"display_aspect_ratio": "16:9",
"pix_fmt": "yuv420p",
"level": 30,
"chroma_location": "left",
"refs": 1,
"is_avc": "true",
"nal_length_size": "4",
"r_frame_rate": "30/1",
"avg_frame_rate": "30/1",
"time_base": "1/15360",
"start_pts": 0,
"start_time": "0.000000",
"duration_ts": 923648,
"duration": "60.133333",
"bit_rate": "1022440",
"bits_per_raw_sample": "8",
"nb_frames": "1804",
"disposition": {
"default": 1,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
},
"tags": {
"language": "und",
"handler_name": "VideoHandler"
}
},
{
"index": 1,
"codec_name": "aac",
"codec_long_name": "AAC (Advanced Audio Coding)",
"profile": "LC",
"codec_type": "audio",
"codec_time_base": "1/44100",
"codec_tag_string": "mp4a",
"codec_tag": "0x6134706d",
"sample_fmt": "fltp",
"sample_rate": "44100",
"channels": 2,
"channel_layout": "stereo",
"bits_per_sample": 0,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/44100",
"start_pts": 0,
"start_time": "0.000000",
"duration_ts": 2646441,
"duration": "60.010000",
"bit_rate": "106895",
"max_bit_rate": "128000",
"nb_frames": "2586",
"disposition": {
"default": 1,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
},
"tags": {
"language": "und",
"handler_name": "SoundHandler"
}
}
],
"format": {
"filename": "http://cdn.coconut.co/test.mp4",
"nb_streams": 2,
"nb_programs": 0,
"format_name": "mov,mp4,m4a,3gp,3g2,mj2",
"format_long_name": "QuickTime / MOV",
"start_time": "0.000000",
"duration": "60.134000",
"size": "8540028",
"bit_rate": "1136133",
"probe_score": 100,
"tags": {
"major_brand": "isom",
"minor_version": "512",
"compatible_brands": "isomiso2avc1mp41",
"title": "Big Buck Bunny, Sunflower version",
"artist": "Blender Foundation 2008, Janus Bager Kristensen 2013",
"composer": "Sacha Goedegebure",
"encoder": "Lavf58.29.100",
"comment": "Creative Commons Attribution 3.0 - http://bbb3d.renderfarming.net",
"genre": "Animation"
}
}
}
},
{
"key": "httpstream",
"type": "httpstream",
"format": "httpstream",
"urls": [
],
"status": "httpstream.packaged"
},
{
"key": "jpg:320x",
"type": "image",
"format": "jpg:320x",
"urls": [
"http://cdn.coconut.co/jpg/thumbs_01.jpg",
"http://cdn.coconut.co/jpg/thumbs_02.jpg",
"http://cdn.coconut.co/jpg/thumbs_03.jpg",
"http://cdn.coconut.co/jpg/thumbs_04.jpg",
"http://cdn.coconut.co/jpg/thumbs_05.jpg",
"http://cdn.coconut.co/jpg/thumbs_06.jpg",
"http://cdn.coconut.co/jpg/thumbs_07.jpg"
],
"status": "image.created"
}
]
}
}
Event changes & overall progress
You can receive notifications where specific events occur via the boolean parameter events.
Here is the list of events:
Event type | Description |
---|---|
job.completed |
When the job is completed and successful. |
job.failed |
When the job is completed but contains at least one failed process. |
input.transferred |
When the input file is transferred to Coconut. All the output jobs are then created. Note that if the input transfer fails, you will receive a job.failed immediately. |
output.completed |
The output has been processed successfully and uploaded to your storage. |
output.failed |
An error occurred with the output creation. |
Because of our distributed architecture, you may sometimes receive the notification with event job.completed before (video|image|httpstream).*. You can safely ignore any notifications coming after job.completed.
Usage example:
{
"notification": {
"type": "http",
"url": "https://yourserver/api/coconut/webhook",
"events": true,
"metadata": true
}
}
Here are some examples:
Input file is transferred to Coconut:
{
"job_id": "fS506AhviYQoJI",
"event": "input.transferred",
"metadata": true,
"progress": "20%",
"data": {
"status": "input.transferred",
"metadata": {
"streams": [
{
"index": 0,
"codec_name": "h264",
"codec_long_name": "H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10",
"profile": "High",
"codec_type": "video",
"codec_time_base": "1/60",
"codec_tag_string": "avc1",
"codec_tag": "0x31637661",
"width": 854,
"height": 480,
"coded_width": 864,
"coded_height": 480,
"has_b_frames": 2,
"sample_aspect_ratio": "1280:1281",
"display_aspect_ratio": "16:9",
"pix_fmt": "yuv420p",
"level": 31,
"chroma_location": "left",
"refs": 1,
"is_avc": "true",
"nal_length_size": "4",
"r_frame_rate": "30/1",
"avg_frame_rate": "30/1",
"time_base": "1/15360",
"start_pts": 323,
"start_time": "0.021029",
"duration_ts": 922624,
"duration": "60.066667",
"bit_rate": "865345",
"bits_per_raw_sample": "8",
"nb_frames": "1802",
"disposition": {
"default": 1,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
},
"tags": {
"language": "und",
"handler_name": "VideoHandler"
}
},
{
"index": 1,
"codec_name": "aac",
"codec_long_name": "AAC (Advanced Audio Coding)",
"profile": "LC",
"codec_type": "audio",
"codec_time_base": "1/48000",
"codec_tag_string": "mp4a",
"codec_tag": "0x6134706d",
"sample_fmt": "fltp",
"sample_rate": "48000",
"channels": 6,
"channel_layout": "5.1",
"bits_per_sample": 0,
"r_frame_rate": "0/0",
"avg_frame_rate": "0/0",
"time_base": "1/48000",
"start_pts": 0,
"start_time": "0.000000",
"duration_ts": 2880512,
"duration": "60.010667",
"bit_rate": "64505",
"max_bit_rate": "64505",
"nb_frames": "2813",
"disposition": {
"default": 1,
"dub": 0,
"original": 0,
"comment": 0,
"lyrics": 0,
"karaoke": 0,
"forced": 0,
"hearing_impaired": 0,
"visual_impaired": 0,
"clean_effects": 0,
"attached_pic": 0,
"timed_thumbnails": 0
},
"tags": {
"language": "und",
"handler_name": "SoundHandler"
}
}
],
"format": {
"filename": "http://aws-us-east-1-media.coconut.co.s3.amazonaws.com/16/09/9e6d3b5a1c805d1e707c3fc024b1aa58/0",
"nb_streams": 2,
"nb_programs": 0,
"format_name": "mov,mp4,m4a,3gp,3g2,mj2",
"format_long_name": "QuickTime / MOV",
"start_time": "0.000000",
"duration": "60.067000",
"size": "7047204",
"bit_rate": "938579",
"probe_score": 100,
"tags": {
"major_brand": "isom",
"minor_version": "512",
"compatible_brands": "isomiso2avc1mp41",
"title": "Big Buck Bunny, Sunflower version",
"artist": "Blender Foundation 2008, Janus Bager Kristensen 2013",
"composer": "Sacha Goedegebure",
"encoder": "Lavf57.25.100",
"comment": "Creative Commons Attribution 3.0 - http://bbb3d.renderfarming.net",
"genre": "Animation"
}
}
}
}
}
An output just processed:
{
"job_id": "bH6aSkWMEEPu2h",
"event": "output.completed",
"metadata": false,
"data": {
"type": "image",
"status": "image.created",
"progress": "25%",
"key": "jpg:320x",
"urls": [
"http://cdn.coconut.co/jpg/thumbs_01.jpg",
"http://cdn.coconut.co/jpg/thumbs_02.jpg",
"http://cdn.coconut.co/jpg/thumbs_03.jpg",
"http://cdn.coconut.co/jpg/thumbs_04.jpg",
"http://cdn.coconut.co/jpg/thumbs_05.jpg",
"http://cdn.coconut.co/jpg/thumbs_06.jpg",
"http://cdn.coconut.co/jpg/thumbs_07.jpg"
]
}
}
Video output failed:
{
"job_id": "cPb0ddjrFrdhuw",
"event": "output.failed",
"progress": "75%",
"metadata": false,
"data": {
"type": "video",
"key": "webm",
"error": "error msg"
}
}
Receiving webhooks server-side
To receive webhooks, you just need to write the code listening to POST requests and return a 2XX HTTP code. In case of error, we retry 3 times with 5 minutes interval before giving up.
Get started without writing any code by using our webhook inspector.
Exposing localhost to the Internet
While developing on your machine, your web app is not public and is thus not accessible by the Coconut servers. To make your local app reachable, we suggest to use ngrok.
Let's setup a small sinatra app to handle incoming webhooks:
# server.rb
require "sinatra"
require "json"
post "/webhooks/coconut" do
hook = JSON.parse(request.body.read)
p hook["data"]["outputs"]
end
If you are a PHP guy, you might be interested in this sample code:
<?php
$body = file_get_contents("php://input");
$webhook = json_decode($body, true);
print_r($webhook["data"]["outputs"]);
?&rt;
Secure a webhook
To secure the webhook, we suggest to generate a temporary unique token for each job you create. Once the job is done, you invalidate the token and nobody will be able to replay the webhook.