Flow

A notification template is changed and submitted for review. Upon submission, an outbound webhook call will be made that will notify of a pending change submission. Upon receipt of the webhook event, a review and approval process can run and then publish the template via API call.

Diagram

Enable Notification Checks for a Template

Checks need to be enabled for each template you want to require an approval workflow for.

  1. Open the notification template
  2. Click the Settings gear
  3. Navigate to the Checks tab
  4. Enable custom checks

The template’s publish button will be replaced with an option to send it for review.

After a template has been sent for review, it will enter a Read Only state where no changes can be made to the latest draft. Users can cancel the submission to restore the template to a draft state and make additional changes.

Sending a template for review emits a webhook event with type “notification:submitted”.

Webhooks

Configure a webhook in Settings → Webhooks. This webhook will be called when a notification is submitted for a review, when it was canceled and also when a notification is published. Please note: At this point we do not have a granular way to allocate webhooks so you will receive other events (message sent events) for the webhooks you add to the Settings, so filter on the event type.

Webhook Settings

Edit Webhook Dialog

Event Types

{
  "data": {
    "id": "<NOTIFICATION_ID>",
    "submission_id": <SUBMISSION_ID>
  },
  "type": "notification:submitted"
}

To see examples of other notification submission event types, review the webhook documentation.

Once you have received a notification:submitted event, you can trigger an approval workflow that runs outside of Courier. Once the workflow is complete and the template is approved to be published, see Publishing the template.

Fetching Content (Optional)

When the “notification:submitted” event is received, the content can be retrieved by calling the Notification Content API. The response can be used to include additional details or template content in your approval workflow.

GET /notifications/:notification_id/draft/content

Sample Template

Sample Template

Sample Template Response

{
  "blocks": [
    {
      "alias": "Greetings",
      "context": "This is where we greet a new user",
      "id": "block_43c114d9-9cfd-4340-808f-17e2fc7a4c87",
      "type": "text",
      "checksum": "fb60f2098fa407a4ff8d48e3e908d889",
      "content": "Hello <variable id=\"3\">{name}</variable>, Welcome to <highlight id=\"6\">Courier</highlight>!",
    },
    {
      "id": "block_f19dd58f-d32c-41b8-911c-239053d34803",
      "type": "markdown",
      "content": "Ready, <variable id=\"3\">{name}</variable>? Get started [here](http://daringfireball.net/projects/markdown/).",
      "checksum": "d06665ec3f663789db81474bc1a82fc5",
    },
    {
      "id": "block_78863d66-54f2-4032-a897-cbed3abb2538",
      "type": "quote",
      "content": "<highlight id=\"3\">Marvel</highlight> is better than DC, do you agree <variable id=\"6\">{name}</variable>?",
      "checksum": "d6e5df4e00b54703e7048cbc5276863e",
    },
    {
      "id": "block_106b5136-1bf9-4842-bff7-cbae140fd3a3",
      "type": "action",
      "content": "Share",
      "checksum": "67561c1170434dcbfd9becb827672495",
    },
    {
      "id": "block_9ec5eba6-8ab1-4938-96b0-0f6b63439619",
      "type": "list",
      "content": {
        "children": "<variable id=\"3\">{userName}</variable>",
        "parent": "<variable id=\"3\">{blogTitle}</variable> liked by"
      },
      "checksum": "a4f817cd1a363e95ce1400095937cad8",
    },
    {
      "id": "block_31500deb-de21-436f-9ae6-98f08d569148",
      "type": "template",
      "content": "\n\n<div class=\"notes\">Thanks!</div>",
      "checksum": "c1a6639e8a83a4aba68004ad1a06f124",
    }
  ],
  "channels": [
    {
      "id": "channel_f2e7b2e9-187f-40d9-9725-636d6c59833a",
      "type": "email",
      "content": {
        "subject": "New Subject"
      },
      "checksum": "96bcf212afa5cae1c7918280743aec71",
    }
  ],
  "checksum": "22d224a20345f1e3d3cf4c231243a747"
}

Checksum

We md5 hash the contents for each block, channel and notification so you could track if contents have ever changed in order to manage translations workflow as needed.

Publishing the template

Once all checks are resolved, Courier can be notified that the process is completed and release the template to be published.

PUT /notifications/:notification_id/:submission_id/checks

{
  "checks": [
    {
      "status": "RESOLVED"
    }
  ]
}

If you wish to reject a request to publish a template, see Cancel a submission. The check status can be set to FAILED or PENDING using PUT as well, which can be used for more complex state management in approval workflows.

Fetching Checks

Checks API GET endpoint

GET /notifications/:notification_id/:submission_id/checks

Example - GET /notifications/SFTYJKSF0241SVH2TWY97TTFFTQG/1630424150210/checks

{
	"checks":[
		{
			"id":"B5BYH93H4D4XRPJBMZJGB43TJEZ3", // check ID
			"status":"PENDING",
			"type":"custom",
			"updated":1630424150210
		}
	]
}

Cancel a Submission

A request to publish a template can be cancelled by deleting the submission. This will move the template back to a draft state. Checks for the submission will also be updated to a FAILED state. Once a submission has been cancelled, setting the check to RESOLVED will not publish that submission.

DELETE /notifications/:notification_id/:submission_id/checks

Submitted Keys

Submitted keys are used when you have to send a notification that was submitted for a review but maybe not ready to be published. Basically, submitted is an interim state between Draft and Published. Here’s how it works -

→ If notification was published, a submitted key send operation uses published notification contents

→ If notification was submitted for review, a submitted key send operation uses latest draft notification content

Submitted keys can be retrieved, updated or deleted from the Settings → API Keys UI.