Heroku Audit Trail Log Ingestion via API Polling
This guide explains how to configure RunReveal to poll Heroku Enterprise audit trail events (e.g., app creation, destruction, add-on management, collaborator changes, team membership updates) using the Heroku Platform API.

Prerequisites
- Heroku Enterprise account access
You need a Heroku Enterprise organization with audit trail capabilities. - Heroku API token with organization access
Token must have read permissions for your enterprise organization’s audit trail. - RunReveal account with permissions to add sources and view logs (admin/editor)
Ability to add sources and view logs.
Step 1: Create Heroku Source in RunReveal
- Navigate to Sources in RunReveal
- Look for *Heroku source tile
- Provide a descriptive Source Name (e.g., “Heroku” or “Heroku Audit Prod”)
- Add your Heroku Enterprise Account ID and generated API Token to the tile from the steps below.
Step 2: Obtain Your Enterprise Account ID
The Enterprise Account ID is tied to your Heroku Enterprise organization identifier.
Finding Your Enterprise Account ID:
Method 1: Heroku CLI
# Install Heroku CLI if not already installed
npm install -g heroku
# Login to your account
heroku login
# List organizations you have access to
heroku orgs
# Example output:
# your-company-name (enterprise)Method 2: API Request to return Enterprise Account Names and IDs
# Using your API token (see Step 3 below)
curl -n https://api.heroku.com/enterprise-accounts \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.heroku+json; version=3"Step 3: Generate Heroku API Token
You need a Heroku API token with audit trail access permissions. The token needs to be created by a user with Enterprise Admin permissions and will have the prefex ”HRKU-”. You can validate the token works by calling the api endpoints for audit trail events from Heroku.
Creating a Heroku API Token via CLI:
# Login to Heroku
heroku login
# Create a new authorization with audit permissions
heroku authorizations:create --description "RunReveal Audit Trail"
# Example output:
# Client: <client-id>
# ID: <auth-id>
# Description: RunReveal Audit Trail
# Scope: global
# Token: <your-api-token>Important: Copy the token immediately after creation - it won’t be shown again.
Required Permissions
Your API token must have access to:
- Organization audit events:
readscope - Enterprise account access: Must be a member of the enterprise organization
Step 4: Validate Data Collection
- Return to RunReveal and open your source tile for Heroku page
- Confirm that events are being collected (initial polling may take 5 minutes)
- Search in Explorer or use Native AI Chat to inspect recent Heroku audit events
- Look for the
heroku_logstable with your source ID filter
Note: RunReveal polls for new Heroku audit events every 5 minutes. Historical audit events are available based on your Heroku Enterprise plan retention period.
Testing Your Configuration
Validate your credentials before saving in RunReveal:
# Test API token and enterprise access
curl -n https://api.heroku.com/enterprise-accounts/YOUR_ENTERPRISE_ACCOUNT_ID/events \
-H "Authorization: Bearer YOUR_ENTERPRISE_API_TOKEN" \
-H "Accept: application/vnd.heroku+json; version=3"
# Should return recent audit events JSONSchema
The following columns are exposed for this source. RunReveal applies schema normalization across all sources, ensuring uniform field names and data types for cross-source queries and reusable detection logic.
Table: heroku_audit_logs (52 columns)
heroku_audit_logs (52 columns)| Column | Type |
|---|---|
workspaceID | String |
sourceID | String |
sourceType | String |
sourceTTL | UInt32 |
receivedAt | DateTime(3) |
id | String |
eventTime | DateTime(3) |
eventName | String |
eventID | String |
srcIP | String |
srcASCountryCode | String |
srcASNumber | UInt32 |
srcASOrganization | String |
srcCity | String |
srcConnectionType | String |
srcISP | String |
srcLatitude | Float64 |
srcLongitude | Float64 |
srcUserType | String |
dstIP | String |
dstASCountryCode | String |
dstASNumber | UInt32 |
dstASOrganization | String |
dstCity | String |
dstConnectionType | String |
dstISP | String |
| Column | Type |
|---|---|
dstLatitude | Float64 |
dstLongitude | Float64 |
dstUserType | String |
actor | Map(String, String) |
tags | Map(String, String) |
resources | Array(String) |
serviceName | String |
enrichments | Array(Tuple(data Map(String, String), name String, provider String, type String, value String)) |
readOnly | Bool |
rawLog | String |
herokuId | String |
herokuAction | String |
herokuCreatedAt | DateTime(3) |
herokuType | String |
herokuActorId | String |
herokuActorEmail | String |
herokuAppId | String |
herokuAppName | String |
herokuTeamId | String |
herokuTeamName | String |
herokuOwnerId | String |
herokuOwnerEmail | String |
herokuEnterpriseAccountId | String |
herokuEnterpriseAccountName | String |
herokuRequestIpAddress | String |
herokuData | String |