JSON API
Drive CreationDePerso from a script or an AI assistant: catalog reads, creation of monsters, items, campaigns, quests and characters, under exactly the same rules as the site.
Authentication
Generate a personal key from My space → API keys and send it in the Authorization header of every call:
curl -H "Authorization: Bearer cpk_…" https://www.creationdeperso.com/api/v1/me
The key carries your account’s rights: a player reads the catalog and manages their characters, a DM additionally forges monsters and items and writes campaigns and quests.
Rights of a key
Each key carries a list of rights chosen at creation (and editable later): <code>family.action</code> entries, or a whole family <code>family.*</code>. A right never exceeds the account’s roles: a key with <code>monsters.create</code> on an account without the DM role is still refused. <code>GET /me</code> returns the key’s rights.
| Family | Entries |
|---|---|
| Catalog | catalog.read |
| Characters | characters.read · characters.create · characters.delete |
| Forged items | items.read · items.create · items.update · items.delete · items.publish |
| Monsters | monsters.read · monsters.create · monsters.update · monsters.delete · monsters.publish |
| Campaigns | campaigns.read · campaigns.create · campaigns.update · campaigns.delete · campaigns.publish |
| Quests | quests.read · quests.create · quests.update · quests.delete · quests.publish · quests.activate |
A call outside the key’s rights answers <code>403 insufficient_scope</code> with the missing right in <code>requiredScope</code>.
Conventions
- Catalog rows are designated by their slug (<code>key</code>), never by a numeric id. Only characters, campaigns and quests, and the resources you create, carry an <code>id</code>.
- A list is wrapped in <code>{ items, total }</code> (paginated: <code>{ items, page, perPage, total }</code>, <code>perPage</code> ≤ 100).
- The <code>Accept-Language</code> header (fr by default, en, de, es) selects the language of catalog names and error messages.
- Each account gets 1,000 calls per hour (<code>X-RateLimit-*</code> headers).
Every error answers with a single envelope:
{
"error": {
"code": "validation_failed",
"message": "…",
"violations": [ { "path": "hitPoints", "message": "…" } ]
}
}
| Code | Meaning |
|---|---|
401 unauthenticated | Key missing, unknown, revoked or expired. |
403 forbidden | The account lacks the required role (e.g. DM for the forge). |
403 insufficient_scope | The key is valid but lacks this right (see “Rights of a key”). |
404 not_found | Unknown resource, or one you do not own. |
409 conflict / insufficient_credits | The resource state refuses the action (transition unavailable, item in use, insufficient forge credits). |
422 validation_failed | Invalid payload: <code>violations</code> details each faulty field. |
429 rate_limited | Hourly quota exceeded: retry after <code>Retry-After</code>. |
500 internal | Internal error: quote the response’s requestId so the incident can be found in the log. |
Maximum lengths and bounds of every field (maxLength, minimum, maximum) are declared in the OpenAPI schema: they are the site’s own rules, exceeding one answers 422. A body read with GET can be sent back as is with PUT, read-only fields included.
Catalog reads
Start by reading the catalog to learn which slugs to send. Homebrew tables (weapons, armors, equipment, attacks, monsters) are scoped to what your account may see: built-in content, approved public content and your own creations (<code>origin</code> field).
| Endpoint | Effect |
|---|---|
GET /api/v1/me | The account behind the key, its roles and credit balance. |
GET /api/v1/catalog/species | Species and lineages (<code>requiresLineage</code> says whether a lineage is mandatory). |
GET /api/v1/catalog/classes | Classes, subclasses and level-1 budgets (skills, expertise, gold, spells, package). |
GET /api/v1/catalog/backgrounds | 2024 backgrounds: granted skills, +2/+1 bonus options, origin feat. |
GET /api/v1/catalog/skills, …/feats | Skills and feats. |
GET /api/v1/catalog/spells?class=&level= | Spells, filterable by class and level (0 = cantrips). |
GET /api/v1/catalog/weapons, …/armors, …/equipment, …/specific-attacks | Weapons, armors, equipment and specific attacks visible to your account. |
GET /api/v1/catalog/monsters | Bestiary usable as templates or quest opponents. |
GET /api/v1/catalog/worlds, …/places, …/badges | Worlds, places (hierarchy via <code>parent</code>) and reward badges. |
GET /api/v1/catalog/rules | Closed vocabularies (abilities, sizes, damage types, properties, legal CRs, alignments) and rule tables. |
Forge: items and monsters (DM)
Same rules as the site’s forge: every creation debits its cost in credits (nothing is written when the balance is insufficient), content is born private and goes through moderation to become public, a monster’s challenge rating cannot sit below the estimate of its stats. Edits and deletions are free.
| Endpoint | Effect |
|---|---|
POST /api/v1/items/{type} | Forge a weapon, an armor, a piece of equipment or a specific attack (<code>type</code>: <code>weapons</code>, <code>armors</code>, <code>equipment</code>, <code>specific-attacks</code>). |
GET / PUT / DELETE /api/v1/items/{type}/{id} | Read, replace or delete one of my items (409 when an inventory or a monster uses it). |
POST /api/v1/monsters | Forge a monster: full stat block, skills (<code>{key: 1|2}</code>), attacks by weapon or specific-attack slug. |
POST /api/v1/monsters/estimate | Cost and estimated CR of a stat block, without creating anything. |
GET / PUT / DELETE /api/v1/monsters/{id} | Read (mine, built-in or public), replace or delete a monster. |
POST …/{id}/request-publication | Request publication (private → pending approval). |
curl -X POST -H "Authorization: Bearer cpk_…" -H "Content-Type: application/json" \
-d '{"name":"Gobelin des cendres","challengeRating":"1/4","armorClass":15,"hitPoints":7,
"abilities":{"str":8,"dex":14,"con":10,"int":10,"wis":8,"cha":8},
"skills":{"stealth":2},"attacks":[{"weapon":"scimitar"}]}' \
https://www.creationdeperso.com/api/v1/monsters
Campaigns and quests (DM)
The DM is always the calling account. Characters are designated by <code>id</code>: a party member must be public and claimed, a bound NPC must be one of your sheets, a guest must be public, claimed and outside the party. An edited public campaign or quest goes back to pending approval.
| Endpoint | Effect |
|---|---|
GET / POST /api/v1/campaigns | List my campaigns, create one (optional <code>world</code> slug, <code>party</code> ids). |
GET / PUT / DELETE /api/v1/campaigns/{id} | Read, replace or delete a campaign (409 when other tables adopted it). |
GET /api/v1/campaigns/{id}/quests | A campaign’s quests in play order. |
POST /api/v1/quests | Create a quest: <code>campaignId</code>, place and badge by slug, NPCs, monsters (slug + count), guests. |
GET / PUT / DELETE /api/v1/quests/{id} | Read, replace or delete a quest (409 when other tables played it). |
POST /api/v1/quests/{id}/activate | Activate the quest on a table: pins a version and opens (or resumes) the playthrough. |
POST …/{id}/request-publication | Request publication (private → pending approval). |
Characters
Creation follows the site form's rules exactly: the six scores must be a permutation of the server-issued roll (obtained from the roll endpoint and handed back as the <code>abilityRollToken</code> ticket, valid five minutes and consumed once), a lineage is required when the species has some, the background allocation must be legal, and skills, feats, spells and gear stay within the level-1 budgets. A broken rule answers 422 with the path of the offending field.
| Endpoint | Effect |
|---|---|
POST /api/v1/characters/roll-abilities | Get a server-issued ability roll: a ticket, the seed and six scores to assign. Two rolls per creation, one more while the last is hopeless; otherwise the same roll comes back under a fresh ticket, valid five minutes. |
POST /api/v1/characters | Create a level-1 character (species, lineage, class, background, scores, skills, feats, gear, spells…). |
GET /api/v1/characters, …?scope=public | My characters, or the public gallery. |
GET / DELETE /api/v1/characters/{id} | Read a visible sheet (with the derived sheet: AC, HP, rolls, attacks, grimoire); delete one of mine. |
The complete machine-readable document is served as OpenAPI.