Developer API
Integrate Amalgadon board building and sharing into your own tools.
Overview
The Amalgadon API lets you create board builds programmatically and link users directly into the builder with a board pre-loaded. All endpoints are unauthenticated and free to use under the Terms of Service.
Base URL:
https://www.amalgadon.com
Card data is sourced from hearthstonejson.com. You can use POST /api/encode with card names rather than internal card IDs — the API resolves names for you so your integration does not depend on Hearthstone internals.
Rate Limits
Write endpoints are rate-limited per IP using a fixed window counter. Read-only endpoints have no limit.
| Endpoint | Limit | Window |
|---|---|---|
POST /api/encode | 30 requests | 60 seconds |
POST /api/share | 30 requests | 60 seconds |
GET /api/cards | Unlimited | — |
GET /api/lookup | Unlimited | — |
When a limit is exceeded the response status is 429 with body {"error":"Rate limit exceeded"}.
GET /api/cards
Returns the full Battlegrounds card database used by the site.
/api/cardsNo parameters. No authentication required.
Response
{
"minions": [
{
"id": "BG21_002",
"dbfId": 69448,
"name": "Murloc Tidecaller",
"text": "Whenever a friendly Murloc is summoned, gain +1 Attack.",
"attack": 1,
"health": 2,
"techLevel": 1,
"races": ["MURLOC"],
"goldenCardId": "BG21_002_G"
}
// ...
],
"heroes": [
{
"id": "BG_HERO_01",
"dbfId": 53264,
"name": "Patches the Pirate",
"heroPowerText": "Give a friendly minion +2/+1.",
"armor": 5
}
// ...
],
"trinkets": [
{
"id": "BG30_MagicItem_901",
"dbfId": 102847,
"name": "Rock Buddy",
"text": "After you play a minion, give it +2/+2.",
"tier": "lesser"
}
// ...
],
"spells": [
{
"id": "BG_Spell_001",
"dbfId": 99001,
"name": "Tavern Tipper",
"cost": 1,
"techLevel": 1
}
// ...
],
"cacheTimestamp": 1713475200000
}BG21_002) are the internal Hearthstone identifiers from hearthstonejson.com. For most integrations you can pass card names to POST /api/encode instead and let the API resolve them — this is more readable and resilient to minor ID changes across patches.GET /api/lookup
Resolves a card name or ID to its full card details and, where available, a link to the card's detail page on this site. Useful for building autocomplete UIs or validating card names before calling POST /api/encode.
/api/lookupQuery parameters
| Parameter | Required | Description |
|---|---|---|
q | Yes | Card name (fuzzy-matched) or exact card ID. |
type | No | Restrict to a specific card type: minion, hero, trinket, or spell. |
Examples
GET /api/lookup?q=Murloc+Tidecaller GET /api/lookup?q=Brann&type=minion GET /api/lookup?q=BG21_002
Success response — 200
{
"results": [
{
"id": "BG21_002",
"name": "Murloc Tidecaller",
"type": "minion",
"fuzzy": false,
"text": "Whenever a friendly Murloc is summoned, gain +1 Attack.",
"attack": 1,
"health": 2,
"techLevel": 1,
"races": ["MURLOC"],
"goldenCardId": "BG21_002_G",
"detailUrl": "https://www.amalgadon.com/minion/murloc-tidecaller"
}
]
}type is omitted and a trinket name is shared across tiers, both the lesser and greater variants are returned as separate entries — each with a distinct id and tier field. Use the type=trinket filter and check the returned tier to distinguish them.Error responses
| Status | When |
|---|---|
| 400 | Missing or empty q, or unrecognised type value. |
| 404 | No card matched the query. |
POST /api/encode
The primary integration endpoint. Accepts a human-readable board description, resolves card names to IDs, encodes the board, creates a shareable permalink, and returns all the URLs you need to link users into the builder.
/api/encodeRequest body
| Field | Type | Required | Description |
|---|---|---|---|
hero | string | No | Card name or card ID of the hero. |
slots | SlotInput[] | Yes | 1–7 slot entries (null for empty slots). |
lesserTrinket | string | null | No | Card name or card ID of the lesser trinket. |
greaterTrinket | string | null | No | Card name or card ID of the greater trinket. |
title | string | No | Build title. Max 100 characters. |
description | string | No | Build notes. Max 2000 characters. |
SlotInput object
| Field | Type | Required | Description |
|---|---|---|---|
name | string | name or id | Minion card name (recommended). Fuzzy-matched. |
id | string | name or id | Hearthstone card ID fallback. |
golden | boolean | No | Whether the minion is golden. |
taunt | boolean | No | Whether the minion has Taunt. |
reborn | boolean | No | Whether the minion has Reborn. |
divineShield | boolean | No | Whether the minion has Divine Shield. |
name or id is required per slot. If name is provided it is always tried first. Name matching is case-insensitive and tolerates minor typos (fuzzy match). When a fuzzy match is used, the resolved block in the response will include "fuzzy": true — always log this during development to catch unexpected matches.lesserTrinket is restricted to the lesser pool, and greaterTrinket to the greater pool — so the correct version is always matched even when names overlap. The tier field in the resolved block confirms which was matched.Example request
POST /api/encode
Content-Type: application/json
{
"hero": "Patches the Pirate",
"slots": [
{ "name": "Murloc Tidecaller", "golden": false },
{ "name": "Sellemental", "golden": true },
{ "name": "Brann Bronzebeard", "taunt": true },
null,
null,
null,
null
],
"lesserTrinket": "Rock Buddy",
"title": "Murloc Tempo",
"description": "Early curve into Murlocs with Brann for value."
}Success response — 200
{
"code": "pABCDEFGHIJKL...",
"remixUrl": "https://www.amalgadon.com/?remix=pABCDEFGHIJKL...",
"shareUrl": "https://www.amalgadon.com/build/abc123",
"embedUrl": "https://www.amalgadon.com/embed/abc123",
"resolved": {
"hero": { "name": "Patches the Pirate", "id": "BG_HERO_01", "fuzzy": false },
"slots": [
{ "name": "Murloc Tidecaller", "id": "BG21_002", "fuzzy": false },
{ "name": "Sellemental", "id": "BG20_204", "fuzzy": false },
{ "name": "Brann Bronzebeard", "id": "BG_CFM_312","fuzzy": false },
null,
null,
null,
null
],
"lesserTrinket": { "name": "Rock Buddy", "id": "BG30_MagicItem_901", "fuzzy": false, "tier": "lesser" },
"greaterTrinket": null
}
}Error responses
| Status | When |
|---|---|
| 400 | Malformed JSON, missing required fields, wrong types. |
| 422 | One or more card names or IDs could not be resolved. See unresolved array. |
| 429 | Rate limit exceeded. |
A 422 response includes an unresolved array listing every field that failed resolution so you can address all problems in one cycle:
{
"error": "Could not resolve some cards",
"unresolved": [
{ "field": "slots[2]", "input": "Brann Bronzeberd" },
{ "field": "lesserTrinket", "input": "Rok Buddy" }
]
}Deep-link formats
Once you have a build code or short ID you can construct any of the following URLs to send users to the right place.
| URL | Behaviour |
|---|---|
/?remix=<code> | Opens the builder with the board pre-loaded. The user can edit it freely without affecting the original share. |
/build/<id> | Read-only permalink page for a shared build. Includes upvote/downvote and a Remix button. |
/embed/<id> | Minimal view suitable for embedding in an <iframe>. |
/embed/<id>?hideTitle=1 | Embed view with the build title hidden. |
/build/<id> and /embed/<id> require the 6-character short ID from POST /api/share (or the shareUrl / embedUrl fields from POST /api/encode). /?remix=<code> takes the full build code.Embedding example
<iframe src="https://www.amalgadon.com/embed/abc123" width="700" height="220" style="border: none; border-radius: 8px;" title="Hearthstone Battlegrounds board" ></iframe>
Error reference
All error responses share the same shape:
{
"error": "Human-readable message",
// Optional — present on 422 responses only:
"unresolved": [{ "field": "...", "input": "..." }]
}| Status | Meaning |
|---|---|
| 200 | Success. |
| 400 | Bad request — malformed JSON or invalid field values. |
| 422 | Unprocessable — request was valid but one or more cards could not be resolved. |
| 429 | Rate limit exceeded — retry after 60 seconds. |
| 502 | Upstream error — card data could not be fetched from hearthstonejson.com. |