Deep-dive on the Next Gen Platform. Join the Webinar!

Skip Navigation
Show nav
Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
    • .NET
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Visit the Heroku Blog

    Find news and updates from Heroku in the blog.

    Visit Blog
  • Log inorSign up
Hide categories

Categories

  • Heroku Architecture
    • Compute (Dynos)
      • Dyno Management
      • Dyno Concepts
      • Dyno Behavior
      • Dyno Reference
      • Dyno Troubleshooting
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Platform Principles
  • Developer Tools
    • Command Line
    • Heroku VS Code Extension
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery & Integration (Heroku Flow)
    • Continuous Integration
  • Language Support
    • Node.js
      • Working with Node.js
      • Troubleshooting Node.js Apps
      • Node.js Behavior in Heroku
    • Ruby
      • Rails Support
      • Working with Bundler
      • Working with Ruby
      • Ruby Behavior in Heroku
      • Troubleshooting Ruby Apps
    • Python
      • Working with Python
      • Background Jobs in Python
      • Python Behavior in Heroku
      • Working with Django
    • Java
      • Java Behavior in Heroku
      • Working with Java
      • Working with Maven
      • Working with Spring Boot
      • Troubleshooting Java Apps
    • PHP
      • PHP Behavior in Heroku
      • Working with PHP
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
    • .NET
      • Working with .NET
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Getting Started
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
      • Migrating to Heroku Postgres
    • Heroku Key-Value Store
    • Apache Kafka on Heroku
    • Other Data Stores
  • AI
    • Working with AI
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
      • Single Sign-on (SSO)
    • Private Spaces
      • Infrastructure Networking
    • Compliance
  • Heroku Enterprise
    • Enterprise Accounts
    • Enterprise Teams
    • Heroku Connect (Salesforce sync)
      • Heroku Connect Administration
      • Heroku Connect Reference
      • Heroku Connect Troubleshooting
  • Patterns & Best Practices
  • Extending Heroku
    • Platform API
    • App Webhooks
    • Heroku Labs
    • Building Add-ons
      • Add-on Development Tasks
      • Add-on APIs
      • Add-on Guidelines & Requirements
    • Building CLI Plugins
    • Developing Buildpacks
    • Dev Center
  • Accounts & Billing
  • Troubleshooting & Support
  • Integrating with Salesforce
  • Extending Heroku
  • Building Add-ons
  • Add-on APIs
  • Using Webhooks as an Add-on Partner

Using Webhooks as an Add-on Partner

English — 日本語に切り替える

Last updated May 08, 2024

Table of Contents

  • Creating a Webhook Subscription
  • Receiving webhooks
  • Introspecting deliveries
  • Introspecting events
  • Examples
  • FAQ

Heroku webhooks provide subscription to HTTP notifications when things change. Add-on Partners may track many kinds of events relating to their resources on apps, domains, builds, releases, attachments, dynos, and more.

Webhook integration requires subscribing via the Platform API and implementing endpoints to receive events. This document provides details on how to subscribe and receive notifications.

Creating a Webhook Subscription

Before you will receive any events, you subscribe via:

POST api.heroku.com/addons/<uuid>/webhooks
Accept: application/vnd.heroku+json; version=3
{
  "authorization":  "Bearer 01234567-89ab-cdef-0123-456789abcdef",
  "include":  [
    "api:app",
  ],
  "level":  "sync",
  "url":  "https://myaddon.example.com/webhooks/01234567-89ab-cdef-0123-456789abcdef"
}

Replace <uuid> with the add-on instance uuid returned during resource provisioning request.

Webhook subscription requests include these parameters:

Required

  • include - One or more event types your server will receive. For instance, api:app events provide notification for changes to app name, web url, and more. See below for event options and details.
  • level - Delivery behavior, either notify or sync. notify provides a single “fire and forget” delivery attempt, while sync attempts multiple deliveries until successful or timed out.
  • url - URL for receiver

See the Retries and limits section of the App Webhooks article to understand notification behavior. You can check the delivery status via the webhook-deliveries endpoint.

Optional

  • authorization - A secret shared with the receiver. Deliveries will set this as Authorization header to allow protection from unauthorized posting. The example uses the Bearer authentication scheme, but a string of your choice is allowed.
  • secret - Value to sign delivery with. Deliveries will set the HMAC-SHA256 of the body using this secret as the Heroku-Webhook-Hmac-SHA256 header.

If the secret is omitted, a generated value will be returned in the Heroku-Webhook-Secret header. After creation, this value is not repeated, so it must be captured at this point. Otherwise you may PATCH the webhook to update the secret later.

Partner Event Includes

As of this writing, partners may include these events in subscriptions:

  • api:addon-attachment create, destroy
  • api:addon create, destroy, update
  • api:app create, destroy, update
  • api:build create, update
  • api:collaborator create, destroy, update
  • api:domain create, destroy
  • api:dyno create
  • api:formation destroy, update
  • api:sni-endpoint create, destroy, update

Some events require additional permissions. Open a support ticket to request access to the following events:

  • api:build
  • api:dyno
  • api:formation
  • api:release

These events will be sent when updates happen to the add-on or an app it is associated with, for details see Webhook Events for Partners

Managing Subscriptions

After creating subscriptions, you may need to review or delete them.

You can request the list of webhooks on an add-on:

GET api.heroku.com/addons/<uuid>/webhooks
Accept: application/vnd.heroku+json; version=3
[{
  "addon": {
    "id":  "01234567-89ab-cdef-0123-456789abcdef",
    "name":  "acme-inc-primary-database"
  },
  "created_at":  "2015-01-01T12:00:00Z",
  "id":  "01234567-89ab-cdef-0123-456789abcdef",
  "include":  [
    "api:app",
  ],
  "level":  "sync",
  "url":  "https://myaddon.example.com/webhooks/01234567-89ab-cdef-0123-456789abcdef",
  "updated_at":  "2015-01-01T12:00:00Z",
}]

You can look up details for a particular webhook on an add-on:

GET api.heroku.com/addons/<uuid>/webhooks/<uuid>
Accept: application/vnd.heroku+json; version=3
{
  "addon": {
    "id":  "01234567-89ab-cdef-0123-456789abcdef",
    "name":  "acme-inc-primary-database"
  },
  "created_at":  "2015-01-01T12:00:00Z",
  "id":  "01234567-89ab-cdef-0123-456789abcdef",
  "include":  [
    "api:app",
  ],
  "level":  "sync",
  "url":  "https://myaddon.example.com/webhooks/01234567-89ab-cdef-0123-456789abcdef",
  "updated_at":  "2015-01-01T12:00:00Z",
}

Finally, you can delete an existing webhook from an add-on:

DELETE api.heroku.com/addons/<uuid>/webhooks/<uuid>
Accept: application/vnd.heroku+json; version=3
{
  "addon": {
    "id":  "01234567-89ab-cdef-0123-456789abcdef",
    "name":  "acme-inc-primary-database"
  },
  "created_at":  "2015-01-01T12:00:00Z",
  "id":  "01234567-89ab-cdef-0123-456789abcdef",
  "include":  [
    "api:app",
  ],
  "level":  "sync",
  "url":  "https://myaddon.example.com/webhooks/01234567-89ab-cdef-0123-456789abcdef",
  "updated_at":  "2015-01-01T12:00:00Z",
}

Receiving webhooks

When webhook events are matched, they will make a post request to your server. The Authorization header will match the authorization value from webhook creation and Heroku-Webhook-Hmac-SHA256 will contain the signature obtained from signing the body with the secret value from webhook creation. The result will be a request similar to this:

POST myaddon.com/webhooks/01234567-89ab-cdef-0123-456789abcdef
Authorization: Bearer 01234567-89ab-cdef-0123-456789abcdef
Heroku-Webhook-Hmac-SHA256: cLM15U5x+jHEkANnVasRwBw2yEHu94pXdjcT9Hajc1M=
{
  "action": "update",
  "actor": {
    "email": "user-0436@example.com",
    "id": "096370c8-f3ad-4e20-a309-fb4f06ec0a89"
  },
  "created_at": "2016-10-26T22:50:14Z",
  "id": "d472a8bb-1a3c-4f78-aad1-995e6d0022ec",
  "data": {
    "archived_at": null,
    "buildpack_provided_description": "Ruby/Rails",
    "build_stack": {
      "id": "5e854079-da33-475b-a209-77f527c0e2fb",
      "name": "cedar-14"
    },
    "created_at": "2016-10-26T22:50:14Z",
    "id": "d4714cc8-aa56-4314-817c-0c6a66ff3d41",
    "git_url": "https://git.heroku.com/sample-app-0301.git",
    "maintenance": false,
    "name": "sample-app-0301",
    "owner": {
      "email": "user-0436@example.com",
      "id": "096370c8-f3ad-4e20-a309-fb4f06ec0a89"
    },
    "region": {
      "id": "7044c05a-0873-42c2-abbe-6841c5481ba7",
      "name": "us"
    },
    "organization": null,
    "space": null,
    "released_at": "2016-10-26T22:50:14Z",
    "repo_size": 1048576,
    "slug_size": null,
    "stack": {
      "id": "5e854079-da33-475b-a209-77f527c0e2fb",
      "name": "cedar-14"
    },
    "updated_at": "2016-10-26T22:50:14Z",
    "web_url": "https://sample-app-0301.herokuapp.com/"
  },
  "previous_data": {
  },
  "published_at": null,
  "resource": "app",
  "sequence": null,
  "updated_at": "2016-10-26T22:50:14Z",
  "version": "application/vnd.heroku+json; version=3",
  "webhook_metadata": {
    "attempt": {
      "id": "8a44f820-2354-489d-9a11-a793cbf49979"
    },
    "delivery": {
      "id": "d244009a-670f-4340-88e9-789a4f9002d5"
    },
    "event": {
      "id": "d472a8bb-1a3c-4f78-aad1-995e6d0022ec",
      "include": "api:app"
    },
    "webhook": {
      "id": "01234567-89ab-cdef-0123-456789abcdef"
    }
  }
}

You should always respond with a 200 series status code to indicate delivery success. We will ignore the body of the response, so 204 with an empty body is ideal:

204 No Content

Introspecting deliveries

You can list what we have (or had) enqueued to deliver to you via:

GET api.heroku.com/addons/<uuid>/webhook-deliveries/<uuid>
Accept: application/vnd.heroku+json; version=3
[
  {
    "created_at": "2015-01-01T12:00:00Z",
    "event": {
      "id": "01234567-89ab-cdef-0123-456789abcdef"
    },
    "id": "01234567-89ab-cdef-0123-456789abcdef",
    "status": "pending",
    "updated_at": "2015-01-01T12:00:00Z",
    "webhook": {
      "id": "01234567-89ab-cdef-0123-456789abcdef"
    }
  }
]

By looking at status, which will be one of failure, pending or success and checking the most recent updated_at value you can check to see how many deliveries are queued and how successful delivery has been.

Introspecting events

Examples

When subscribing, you may include one or more include values. Here are some concrete examples of specific includes you might use and what to expect from each.

App Webhooks

To keep track of app details, such as app name changes, subscribe to api:app events via:

POST api.heroku.com/addons/:uuid/webhooks
Accept: application/vnd.heroku+json; version=3
{
  "authorization":  "Bearer 01234567-89ab-cdef-0123-456789abcdef",
  "include":  [
    "api:app",
  ],
  "level":  "sync",
  "url":  "https://myaddon.com/webhooks/01234567-89ab-cdef-0123-456789abcdef"
}

The response would look something like this:

200 OK
Heroku-Webhook-Secret: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789ab
{
  "addon": {
    "id": "01234567-89ab-cdef-0123-456789abcdef",
    "name": "acme-inc-primary-database"
  },
  "created_at": "2015-01-01T12:00:00Z",
  "id": "01234567-89ab-cdef-0123-456789abcdef",
  "include": [
    "release"
  ],
  "level": "notify",
  "updated_at": "2015-01-01T12:00:00Z",
  "url": "example"
}

For subsequent formation changes, you would receive something like:

POST myaddon.com/webhooks/01234567-89ab-cdef-0123-456789abcdef
Authorization: Bearer 01234567-89ab-cdef-0123-456789abcdef
Heroku-Webhook-Hmac-SHA256: cLM15U5x+jHEkANnVasRwBw2yEHu94pXdjcT9Hajc1M=
{
  "action": "update",
  "actor": {
    "email": "user-0436@example.com",
    "id": "096370c8-f3ad-4e20-a309-fb4f06ec0a89"
  },
  "created_at": "2016-10-26T22:50:14Z",
  "id": "d472a8bb-1a3c-4f78-aad1-995e6d0022ec",
  "data": {
    "archived_at": null,
    "buildpack_provided_description": "Ruby/Rails",
    "build_stack": {
      "id": "5e854079-da33-475b-a209-77f527c0e2fb",
      "name": "cedar-14"
    },
    "created_at": "2016-10-26T22:50:14Z",
    "id": "d4714cc8-aa56-4314-817c-0c6a66ff3d41",
    "git_url": "https://git.heroku.com/sample-app-0301.git",
    "maintenance": false,
    "name": "sample-app-0301",
    "owner": {
      "email": "user-0436@example.com",
      "id": "096370c8-f3ad-4e20-a309-fb4f06ec0a89"
    },
    "region": {
      "id": "7044c05a-0873-42c2-abbe-6841c5481ba7",
      "name": "us"
    },
    "organization": null,
    "space": null,
    "released_at": "2016-10-26T22:50:14Z",
    "repo_size": 1048576,
    "slug_size": null,
    "stack": {
      "id": "5e854079-da33-475b-a209-77f527c0e2fb",
      "name": "cedar-14"
    },
    "updated_at": "2016-10-26T22:50:14Z",
    "web_url": "https://sample-app-0301.herokuapp.com/"
  },
  "previous_data": {
  },
  "published_at": null,
  "resource": "app",
  "sequence": null,
  "updated_at": "2016-10-26T22:50:14Z",
  "version": "application/vnd.heroku+json; version=3",
  "webhook_metadata": {
    "attempt": {
      "id": "8a44f820-2354-489d-9a11-a793cbf49979"
    },
    "delivery": {
      "id": "d244009a-670f-4340-88e9-789a4f9002d5"
    },
    "event": {
      "id": "d472a8bb-1a3c-4f78-aad1-995e6d0022ec",
      "include": "api:app"
    },
    "webhook": {
      "id": "01234567-89ab-cdef-0123-456789abcdef"
    }
  }
}

You should respond with a 200 series status code to indicate delivery success. We will ignore the body of the response, so in most cases you should respond something like this:

204 No Content

Release Webhooks

To keep track of app releases, you can subscribe to api:release events via:

POST api.heroku.com/addons/:uuid/webhooks
Accept: application/vnd.heroku+json; version=3
{
  "authorization":  "Bearer 01234567-89ab-cdef-0123-456789abcdef",
  "include":  [
    "api:release",
  ],
  "level":  "sync",
  "url":  "https://myaddon.com/webhooks/01234567-89ab-cdef-0123-456789abcdef"
}

The response would look something like this:

200 OK
Heroku-Webhook-Secret: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789ab
{
  "addon": {
    "id": "01234567-89ab-cdef-0123-456789abcdef",
    "name": "acme-inc-primary-database"
  },
  "created_at": "2015-01-01T12:00:00Z",
  "id": "01234567-89ab-cdef-0123-456789abcdef",
  "include": [
    "release"
  ],
  "level": "notify",
  "updated_at": "2015-01-01T12:00:00Z",
  "url": "example"
}

For subsequent formation changes, you would receive something like:

POST myaddon.com/webhooks/01234567-89ab-cdef-0123-456789abcdef
Authorization: Bearer 01234567-89ab-cdef-0123-456789abcdef
Heroku-Webhook-Hmac-SHA256: cLM15U5x+jHEkANnVasRwBw2yEHu94pXdjcT9Hajc1M=
{
  "action": "create",
  "actor": {
    "email": "heroku-postgresql@addons.heroku.com",
    "id": "f87b5e7e-4631-46cc-9912-9fcdbbb6c985"
  },
  "created_at": "2016-10-26T22:50:29Z",
  "id": "b6a68e77-8c13-41c8-b30c-b50cca7a608a",
  "data": {
    "addon_plan_names": [
      "heroku-postgresql:essential-0"
    ],
    "app": {
      "id": "44dc9c7a-771c-4a9e-bfe9-a8dbc1c55f4d",
      "name": "sample-app-0339"
    },
    "created_at": "2016-10-26T22:50:29Z",
    "description": "Update DATABASE by heroku-postgresql",
    "status": "succeeded",
    "id": "5f1463a4-0210-43ba-b906-52599e246482",
    "slug": null,
    "updated_at": "2016-10-26T22:50:29Z",
    "user": {
      "email": "heroku-postgresql@addons.heroku.com",
      "id": "f87b5e7e-4631-46cc-9912-9fcdbbb6c985"
    },
    "version": 3,
    "current": true
  },
  "previous_data": {
  },
  "published_at": null,
  "resource": "release",
  "sequence": null,
  "updated_at": "2016-10-26T22:50:29Z",
  "version": "application/vnd.heroku+json; version=3",
  "webhook_metadata": {
    "attempt": {
      "id": "8a44f820-2354-489d-9a11-a793cbf49979"
    },
    "delivery": {
      "id": "d244009a-670f-4340-88e9-789a4f9002d5"
    },
    "event": {
      "id": "b6a68e77-8c13-41c8-b30c-b50cca7a608a",
      "include": "api:release"
    },
    "webhook": {
      "id": "01234567-89ab-cdef-0123-456789abcdef"
    }
  }
}

You should respond with a 200 series status code to indicate delivery success. We will ignore the body of the response, so in most cases you should respond something like this:

204 No Content

Formation Webhooks (extra permission required)

To keep track of the quantity and size of running dynos that are attached to an add-on instance, subscribe to api:formation events via:

POST api.heroku.com/addons/:uuid/webhooks
Accept: application/vnd.heroku+json; version=3
{
  "authorization":  "Bearer 01234567-89ab-cdef-0123-456789abcdef",
  "include":  [
    "api:formation",
  ],
  "level":  "sync",
  "url":  "https://myaddon.com/webhooks/01234567-89ab-cdef-0123-456789abcdef"
}

The response would look something like this:

200 OK
Heroku-Webhook-Secret: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789ab
{
  "addon": {
    "id": "01234567-89ab-cdef-0123-456789abcdef",
    "name": "acme-inc-primary-database"
  },
  "created_at": "2015-01-01T12:00:00Z",
  "id": "01234567-89ab-cdef-0123-456789abcdef",
  "include": [
    "release"
  ],
  "level": "notify",
  "updated_at": "2015-01-01T12:00:00Z",
  "url": "example"
}

For subsequent formation changes, you would receive something like:

POST myaddon.com/webhooks/01234567-89ab-cdef-0123-456789abcdef
Authorization: Bearer 01234567-89ab-cdef-0123-456789abcdef
Heroku-Webhook-Hmac-SHA256: cLM15U5x+jHEkANnVasRwBw2yEHu94pXdjcT9Hajc1M=
{
  "action": "update",
  "actor": {
    "email": "user-0297@example.com",
    "id": "2530e242-a531-4d37-99ab-d8997e2335d0"
  },
  "created_at": "2016-10-26T22:49:29Z",
  "id": "89d9e649-1ecf-464e-a15d-86c15365fc40",
  "data": {
    "app": {
      "id": "b225a8d2-1602-42c3-a1a2-98c3c266cc0d",
      "name": "sample-app-0197"
    },
    "command": "ruby server.rb",
    "created_at": "2016-10-26T22:49:29Z",
    "id": "13f27e47-df06-48a1-92be-f521babd9060",
    "type": "web",
    "quantity": 0,
    "size": "1X",
    "updated_at": "2016-10-26T22:49:29Z"
  },
  "previous_data": {
    "quantity": 1
  },
  "published_at": null,
  "resource": "formation",
  "sequence": null,
  "updated_at": "2016-10-26T22:49:29Z",
  "version": "application/vnd.heroku+json; version=3",
  "webhook_metadata": {
    "attempt": {
      "id": "8a44f820-2354-489d-9a11-a793cbf49979"
    },
    "delivery": {
      "id": "d244009a-670f-4340-88e9-789a4f9002d5"
    },
    "event": {
      "id": "89d9e649-1ecf-464e-a15d-86c15365fc40",
      "include": "api:formation"
    },
    "webhook": {
      "id": "01234567-89ab-cdef-0123-456789abcdef"
    }
  }
}

You should respond with a 200 series status code to indicate delivery success. We will ignore the body of the response, so in most cases you should respond something like this:

204 No Content

FAQ

Are collaborator webhooks sufficient to mirror user access of our add-on with the Heroku app?

No. For apps owned by enterprise and team accounts, you also would need to track user roles. We do not expose this functionality as a webhook yet. See this article for a polling-based approach.

Note that mirroring permissions is usually only necessary if you are giving access to your add-on via an additional authentication beyond the Heroku-provided Add-on SSO.

Keep reading

  • Add-on APIs

Feedback

Log in to submit feedback.

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure
  • .NET

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing
  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Github
  • LinkedIn
  • © 2025 Salesforce, Inc. All rights reserved. Various trademarks held by their respective owners. Salesforce Tower, 415 Mission Street, 3rd Floor, San Francisco, CA 94105, United States
  • heroku.com
  • Legal
  • Terms of Service
  • Privacy Information
  • Responsible Disclosure
  • Trust
  • Contact
  • Cookie Preferences
  • Your Privacy Choices