| Developer Portal

Webhooks

The Firstup platform allows you to subscribe to webhooks to notify you when a variety of interactions or events happen. Webhook subscriptions are configured using the Partner API and this page provides more info about each event that can be subscribed to.

This guide covers:

Creating a Subscription

Webhook subscriptions are configured using the Webhooks Endpoints. When creating a subscription you must provide a url you wish to receive webhooks at, and a list of events you wish to receive webhooks for. The access token used when creating a subscription must also have the webhooks.write auth scope.

POST /v2/webhooks/subscriptions HTTP/1.1
Host: https://partner.socialchorus.com
Content-Type: application/json
Authorization: Bearer ACCESS_TOKEN

{
  "url": "https://example.com/endpoint",
  "authorization_header": "foobar"
  "events": [
    { "name": "content_published" },
    { "name": "content_archived" }
  ]
}

A successful subscription creation request will result in a 201 Created response and will include details about the subscription record in the response body.

The Webhook Deliveries section outlines how deliveries will be sent to your subscription's url.

The Event List section lists all the events you can subscribe to.

The authorization_header property of a subscription (in the request body above) is an optional value you can provide that will be included in the Authorization header of every request sent to your subscription url. This is useful for cases where you wish to avoid exposing your webhook url to the web without some form of authorization. Our system considers the value of authorization_header to be an arbitrary string, so whatever you put in that property is directly sent as the header value.

Successfully creating a subscription will result in a ping webhook immediately being sent to the subscription's url. Read more about Pings in Testing a Subscription.

Event List

campaign_push_message_sent
Description: When a custom push message or a content promotion campaign is kicked off.
Example Payload:
{
  "id": "b3d1d304-bee1-4541-9ae7-3dede2e2bbd4",
  "timestamp": "2020-01-01T12:00:00Z",
  "campaign_id": 8273,
  "campaign_name": "Announce Campaign: Example Content Promotion",
  "push_message": {
    "name": "content promotion push",
    "text": "Example text sent to users",
    "locale": "en",
    "deep_link": {
      "type": "content",
      "resource_id": 25120469
    }
  },
  "content_promotion": {
    "type": "content",
    "resource_id": 25120469
  },
  "name": "campaign_push_message_sent",
  "version": "1"
}
channel_archived
Description: When a channel is archived, regardless of its previous state.
Example Payload:
{
  "id": "a4d1d304-bee1-4541-9ae7-3dede2e2bba8",
  "timestamp": "2020-01-01T12:00:00Z",
  "channel_id": 31133,
  "channel_name": "My Channel",
  "name": "channel_archived",
  "version": "1"
}
channel_created
Description: When a new channel is created.
Example Payload:
{
  "id": "fc66f895-fb8c-4e4b-a74a-ac1a7093e9c8",
  "timestamp": "2020-01-01T12:00:00Z",
  "channel_id": 31133,
  "channel_name": "My Channel",
  "name": "channel_created",
  "version": "1"
}
channel_published
Description: When a channel is published.
Example Payload:
{
  "id": "e9777255-7b51-49ac-8845-5dbe8a1456dd",
  "timestamp": "2020-01-01T12:00:00Z",
  "channel_id": 31133,
  "channel_name": "My Channel",
  "name": "channel_published",
  "version": "1"
}
channel_unarchived
Description: When a channel is unarchived.
Example Payload:
{
  "id": "8bdcd3c7-c600-41a3-b148-2037b94d2ce5",
  "timestamp": "2020-01-01T12:00:00Z",
  "channel_id": 31133,
  "channel_name": "My Channel",
  "name": "channel_unarchived",
  "version": "1"
}
channel_updated
Description: When a channel's details are updated. Details include information like channel name or audience, but not content within the channel.
Example Payload:
{
  "id": "f106f854-dd40-44d8-95e9-60d7db11d4d0",
  "timestamp": "2020-01-01T12:00:00Z",
  "channel_id": 31133,
  "name": "channel_updated",
  "version": "1"
}
content_archived
Description: When a content post is archived, regardless of its previous state.
Example Payload:
{
  "id": "09ae0e3a-e77c-417f-af99-763719b85072",
  "timestamp": "2020-01-01T12:00:00Z",
  "content_id": 25120469,
  "channel_ids": [16509],
  "name": "content_archived",
  "version": "1"
}
content_deleted
Description: When a content post is deleted, regardless of its previous state.
Example Payload:
{
  "id": "e9c5bc18-92ac-464c-af50-3f28f5d63603",
  "timestamp": "2020-01-01T12:00:00Z",
  "content_id": 25120469,
  "name": "content_deleted",
  "version": "1"
}
content_drafted
Description: When a content post draft is created, or a new draft is saved.
Example Payload:
{
  "id": "6fb61165-95d9-4565-9264-5f5b536822cd",
  "timestamp": "2020-01-01T12:00:00Z",
  "content_id": 25120469,
  "channel_ids": [16509],
  "name": "content_drafted",
  "version": "1"
}
content_published
Description: When a content post is published to one or more channels.
Example Payload:
{
  "id": "1936f73f-8750-461e-a511-269eb44a43a1",
  "timestamp": "2020-01-01T12:00:00Z",
  "content_id": 25120469,
  "channel_ids": [16509],
  "name": "content_published",
  "version": "1"
}
content_review_approved
Description: When a content post that required a review has been approved by an admin.
Example Payload:
{
  "id": "13229708-f99e-4016-abbf-7914dccdc644",
  "timestamp": "2020-01-01T12:00:00Z",
  "content_id": 25120469,
  "recommended_channel_ids": [13434],
  "submitter": {
    "user_id": 25730
  },
  "reviewer": {
    "user_id": 25731
  },
  "auto_approved": false,
  "name": "content_review_approved",
  "version": "1"
}
content_review_pending
Description: When a content post has been created that requires admin review before it can be published.
Example Payload:
{
  "id": "8ec3b49e-e550-4238-8bef-ac90068dd490",
  "timestamp": "2020-01-01T12:00:00Z",
  "content_id": 25120469,
  "recommended_channel_ids": [13434],
  "submitter": {
    "user_id": 25730
  },
  "name": "content_review_pending",
  "version": "1"
}
content_review_rejected
Description: When a content post that required a review has been rejected by an admin.
Example Payload:
{
  "id": "fc3a82b9-e3af-40b5-98f0-912493a77c34",
  "timestamp": "2020-01-01T12:00:00Z",
  "content_id": 25120469,
  "recommended_channel_ids": [13434],
  "submitter": {
    "user_id": 25730
  },
  "reviewer": {
    "user_id": 25731
  },
  "name": "content_review_rejected",
  "version": "1"
}
content_unpublished
Description: When a content post is unpublished from one or more channels.
Example Payload:
{
  "id": "3b4e2677-6cf8-4917-8166-8c2457396c5b",
  "timestamp": "2020-01-01T12:00:00Z",
  "content_id": 25120469,
  "name": "content_unpublished",
  "version": "1"
}
content_updated
Description: When a content post is updated.
Example Payload:
{
  "id": "e9275cd6-c39f-4308-939f-f1e6dd5339ee",
  "timestamp": "2020-01-01T12:00:00Z",
  "content_id": 25120446,
  "name": "content_updated"
  "version": "1"
}

Webhook Deliveries

Webhook events are sent by the Firstup platform to a url you give us in your subscription in the form of HTTP POST requests. We call these "Deliveries". Each webhook subscription can be configured to receive deliveries for a variety of events. Each delivery's payload (the request body) will be dependent on what event triggered the webhook but there is a basic structure that is consistent for all events, and deliveries will always be json:

{
  "delivery_id": "DELIVERY_ID",
  "subscription_id": "SUBSCRIPTION_ID",
  "program_id": "PROGRAM_ID",
  "events": [
    {
      "name": "content_published",
      "version": "1",
      "content_id": 123,
      ...
    }
  ]
}

In this example, DELIVERY_ID is a unique identifier for the delivery, SUBSCRIPTION_ID is the id of the webhook subscription record responsible for triggering this delivery, and PROGRAM_ID is your program's id.

The "events" property will contain an array including each event in this delivery. Deliveries can include one or more events, depending on whether multiple events occurred within a small time window in your program. Events are sent in batches like this for performance reasons. There will always be at least one event in a delivery, and each event object's payload will reflect the payload documented in Event List.

Deliveries to your subscription url will also have these request headers:

'Content-Type' => 'application/json',
'X-SocialChorus-Delivery' => DELIVERY_ID,
'X-SocialChorus-Subscription' => SUBSCRIPTION_ID,
'X-SocialChorus-Program' => PROGRAM_ID,
'User-Agent' => "SocialChorus-Webhooks/1.0"

Delivery Results

When you receive a webhook event, the url we send deliveries to should return a 200 OK HTTP response. Any response status in the 200-299 range will be considered a delivery success.

If your server returns anything other than a 2xx status, we'll interpret the delivery as a failure. Response statuses in the 500-599 range will result in multiple attempts to send the same delivery, up to 5 attempts or until the response provides a success status. Any other response status will result in a failure that is not retried.

If your server takes longer than 10 seconds to return a status, we'll interpret the delivery as a failure. Ideally, your server will receive and store events and respond immediately with a success response before doing any further processing.

Testing a Subscription

Especially during the setup phase, its common to need to verify that a server is receiving webhook delivery requests correctly. Yet in some cases such as uncommon events or on programs that are live, it may not be wise to trigger test events from Studio. For this reason, webhook subscriptions can be "ping"ed.

The Ping Webhook Subscription endpoint can be used to initiate a ping to any subscription:

POST /v2/webhooks/subscriptions/SUBSCRIPTION_ID/ping HTTP/1.1
Host: https://partner.socialchorus.com
Content-Type: application/json
Authorization: Bearer ACCESS_TOKEN

A ping is just a test delivery sent to the subscription url. This will result in a webhook delivery being immediately sent to your subscription's url. The event payload in that delivery will be a simple event with name "ping".

The response you'll receive from the Ping Webhook Subscription endpoint will include a few details about the delivery and subscription, including the delivery result. If the result value is "success", then we've interpreted that your server is receiving webhooks and responding correctly. If the result is "failed" or "retryable", then there's likely something still misconfigured, as a successful delivery depends on a 200 level http response.

One last note about pings: Whenever you create a webhook subscription, a ping will automatically be sent to the url provided in that subscription.