PathForge API
A read-only JSON API for your character data — build Discord bots, embeds, companion apps, or your own dashboards. Public endpoints respect each character's privacy settings; authenticated endpoints read your own characters with a scoped key.
https://www.pfsheet.org/api/v1Quick start
Public data needs no auth — just a character's public slug (from its share link):
curl https://www.pfsheet.org/api/v1/public/characters/{publicSlug}/summaryFor your own characters, create a key under Settings → API keys and send it as a Bearer token:
curl -H "Authorization: Bearer pf_live_..." \
https://www.pfsheet.org/api/v1/characters/{characterId}/summaryAuthentication & scopes
Keys look like pf_live_…and are shown once at creation — store them securely. A key only ever reads its owner's characters, and you can restrict a key to specific characters. Each scope unlocks a slice of data:
characters:readFull read of your characters — every section you can see (implies the narrower character scopes).
characters:summaryComputed summary: level, HP, AC, CMB, CMD, saves, initiative, speed.
characters:portraitCharacter name and portrait URL only.
discord:embedDiscord character cards for your own characters.
campaigns:readRead your campaigns. Reserved — no endpoints use it yet.
Response shape
Every response is wrapped in a consistent envelope with a request id and version:
// success
{ "data": { /* ... */ }, "meta": { "requestId": "…", "version": "v1" } }
// error
{ "error": { "code": "not_found", "message": "…" }, "meta": { "requestId": "…", "version": "v1" } }Endpoints
Public
/api/v1/healthpublicLiveness check — confirms the API is up.
Returns: { status, service, time }.
/api/v1/public/characters/{publicSlug}/summarypublicPublic character summary (public-safe values only).
Returns: Summary: name, classLine, level, race, alignment, hp, ac, cmb, cmd, saves, initiative, speed, spellcasting (roll-up: casterCount/highestLevel/slotsRemaining).
/api/v1/public/characters/{publicSlug}/statspublicPublic stats — summary plus abilities, and skills/attacks/spellcasting if the share settings allow.
Returns: Summary + abilities[] + skills[]|null + attacks[]|null + spellcasting|null (casters/slots/prepared/known/spellbook/counts).
/api/v1/public/characters/{publicSlug}/portraitpublicPublic portrait reference.
Returns: { name, portraitUrl }.
/api/v1/public/characters/{publicSlug}/opengraphpublicOpenGraph metadata for link embeds.
Returns: { title, description, image }.
Authenticated
/api/v1/characters/{characterId}/summaryscope: characters:summarySummary for one of your own characters (full values).
Returns: Summary (same shape as the public summary).
/api/v1/characters/{characterId}/statsscope: characters:readFull stats for your character — abilities, skills, attacks, spellcasting.
Returns: Summary + abilities[] + skills[] + attacks[] + spellcasting (casters/slots/prepared/known/spellbook/counts).
/api/v1/characters/{characterId}/portraitscope: characters:portraitPortrait reference for your character.
Returns: { name, portraitUrl }.
/api/v1/characters/{characterId}/sharescope: characters:readShare metadata for your character.
Returns: { visibility, publicSlug, shareUrl }.
Discord
/api/v1/discord/character-cardpublic · or scope: discord:embedDiscord character card. Use ?slug= for a public character (no auth), or ?characterId= with a key that has discord:embed.
slug(optional) — Public slug — returns the public-safe card, no auth.characterId(optional) — Your character's id — requires a key with discord:embed.
Returns: Card: name, subtitle, portraitUrl, level, hp, ac, saves, initiative, speed, topSkills[], activeBuffs[], preparedHighlights[], shareUrl.
Rate limits
Over the limit returns 429 rate_limited. Limits are a safety valve and may change.
Errors
| Status | Code | When |
|---|---|---|
| 400 | bad_request | Required query parameters are missing. |
| 401 | unauthorized | No valid API key (or session) was supplied. |
| 403 | forbidden | The key lacks the scope, or the character isn't yours. |
| 404 | not_found | No public character with that slug, or character not found. |
| 422 | invalid_character | The character data failed validation. |
| 429 | rate_limited | Too many requests in the current window. |
Privacy
Public endpoints serve only what a character's share settings expose — the same privacy model as the public sheet. Sections a viewer can't see come back nullor empty, never as raw data. Private and campaign-only characters aren't reachable through the public API at all.
Ready to build? Create an API key →