API Reference 2.0

Notification

required – When the job is complete, receive the information either to an HTTP URL (Webhook) or a SNS Topic in JSON format. The request contains all the output URLs and errors if any.

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

NameTypeDefaultRequired
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

NameTypeDefaultRequired
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 typeDescription
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.