Empathy Ledger API

Access stories, media, galleries, and storyteller profiles from your organization. Build custom experiences or drop in our embed widget for instant integration.

Quick Start

Get your API key from your dashboard (Storyteller → Developer tab, or Organization → Settings → API). Then make your first request:

Fetch your storiesbash
curl -H "X-API-Key: el_org_your_key_here" \
  https://www.empathyledger.com/api/v2/stories

Authentication

Every request requires an API key. Pass it via either header:

Option A: X-API-Key headerbash
X-API-Key: el_org_your_key_here
Option B: Authorization headerbash
Authorization: Bearer el_org_your_key_here

Key Types

TypePrefixScope
Organizationel_org_All published content within the organization
Storytellerel_st_Only the storyteller's own content (all statuses)
Siteel_site_Content with explicit syndication consent

Endpoints

GET/api/v2/stories

List stories scoped by API key

Query Parameters

pagenumberPage number (default: 1)
limitnumberResults per page (default: 20, max: 100)
projectIduuidFilter by project
themestringFilter by theme name
storytellerIduuidFilter by storyteller
Example responsejson
{
  "data": [
    {
      "id": "abc-123",
      "title": "My Story",
      "excerpt": "A brief summary...",
      "themes": ["healing", "identity"],
      "status": "published",
      "publishedAt": "2026-03-01T00:00:00Z",
      "imageUrl": "https://...",
      "storyteller": {
        "id": "def-456",
        "displayName": "Jane Smith",
        "avatarUrl": "https://..."
      },
      "detailUrl": "/api/v2/stories/abc-123"
    }
  ],
  "pagination": { "page": 1, "limit": 20, "total": 42, "hasMore": true }
}
GET/api/v2/stories/:id

Get a single story with full content

Example responsejson
{
  "data": {
    "id": "abc-123",
    "title": "My Story",
    "content": "<p>Full HTML content...</p>",
    "excerpt": "A brief summary...",
    "themes": ["healing"],
    "storyteller": { "id": "def-456", "displayName": "Jane Smith", "bio": "..." }
  }
}
GET/api/v2/media

List media assets (photos, video, audio)

Query Parameters

pagenumberPage number
limitnumberResults per page
galleryIduuidFilter by gallery
projectIduuidFilter by project
typestringFilter by type: image, video, audio
storytellerIduuidFilter by uploader
Example responsejson
{
  "data": [
    {
      "id": "med-789",
      "title": "Community Gathering",
      "url": "https://cdn.../photo.jpg",
      "thumbnailUrl": "https://cdn.../thumb.jpg",
      "contentType": "image/jpeg",
      "dimensions": { "width": 1920, "height": 1080 }
    }
  ]
}
GET/api/v2/galleries

List galleries with metadata and storytellers

Query Parameters

pagenumberPage number
limitnumberResults per page
projectIduuidFilter by project
tagstringFilter by cultural theme/significance
Example responsejson
{
  "data": [
    {
      "id": "gal-101",
      "title": "Country Visit",
      "slug": "country-visit",
      "coverImage": "https://...",
      "mediaAssetCount": 24,
      "storytellers": [{ "displayName": "Elder Grace", "role": "curator" }],
      "mediaUrl": "/api/v2/media?galleryId=gal-101"
    }
  ]
}
GET/api/v2/storytellers

List storyteller profiles

Query Parameters

pagenumberPage number
limitnumberResults per page
Example responsejson
{
  "data": [
    {
      "id": "st-001",
      "displayName": "Jane Smith",
      "avatarUrl": "https://...",
      "bio": "Community advocate...",
      "culturalBackground": ["Kalkadoon"],
      "storyCount": 5
    }
  ]
}
GET/api/v2/transcripts

List transcripts

Query Parameters

pagenumberPage number
limitnumberResults per page
storyIduuidFilter by story
Example responsejson
{
  "data": [
    {
      "id": "tr-001",
      "title": "Interview Transcript",
      "storyId": "abc-123",
      "content": "Full transcript text...",
      "wordCount": 1240
    }
  ]
}
GET/api/v2/projects

List projects accessible via API key

Query Parameters

pagenumberPage number
limitnumberResults per page
Example responsejson
{
  "data": [
    {
      "id": "proj-001",
      "name": "Oonchiumpa",
      "code": "ACT-ON",
      "description": "Community storytelling project...",
      "status": "active"
    }
  ]
}

Embed Widget

Drop a single script tag and HTML element onto any page to display Empathy Ledger content. No build tools or frameworks required.

Story List

Display latest storieshtml
<script src="https://www.empathyledger.com/embed/widget.js" defer></script>
<div data-empathy-ledger
     data-type="stories"
     data-api-key="el_org_your_key"
     data-limit="4">
</div>

Single Story

Display one storyhtml
<div data-empathy-ledger
     data-type="story"
     data-api-key="el_org_your_key"
     data-id="story-uuid-here">
</div>

Photo Gallery

Display gallery photoshtml
<div data-empathy-ledger
     data-type="gallery"
     data-api-key="el_org_your_key"
     data-id="gallery-uuid-here">
</div>

Storyteller Profile

Display a profile cardhtml
<div data-empathy-ledger
     data-type="storyteller"
     data-api-key="el_org_your_key"
     data-id="storyteller-uuid-here">
</div>
SPA support: Call window.EmpathyLedger.init() after dynamically adding widget elements to re-scan and initialize them.

Rate Limits & Errors

Rate limits are per API key. Check the response headers for your current usage:

HeaderDescription
X-RateLimit-LimitMax requests per hour
X-RateLimit-RemainingRemaining requests this hour
Retry-AfterSeconds to wait (on 429)

Error Codes

CodeMeaning
401Missing or invalid API key
403Key expired, domain not allowed, or content is culturally restricted
404Resource not found or not accessible with this key
429Rate limit exceeded — wait and retry
500Internal error — contact support

Cultural Safety

Sacred and restricted content is never returned by the API.

Content flagged as sacred or restricted by storytellers or cultural advisors is automatically filtered from all API responses. If you attempt to access a specific resource that is culturally protected, you will receive a 403 response. This protection cannot be overridden by any API key type.