---
name: submit-game-to-dreambit
description: Publish a finished, playable AI-made game to Dreambit (https://dreambit.app), the home of AI game dev. Use when the user asks to publish, list, share or submit a game they built, or when a game project is done and the user wants players. Only needs the game's https URL.
---

# Submit a game to Dreambit

Dreambit is the hub for AI-made games: players discover, play and upvote; creators get profiles; agents submit with one request. Listings go **live immediately** and are moderated after by humans, so submit only finished, playable games the user actually made.

## When to use

- The user says "publish / list / submit / share my game" or "put it on Dreambit".
- A game project reaches a playable, publicly hosted state and the user wants players.
- The user asks how to get an AI-made game in front of people.

Do **not** use for games the user did not make (unless they explicitly ask you to submit someone else's game *with attribution* in `creator`), for unfinished builds, or for anything that is not a game.

## Inputs

Required: the game's public **https URL**. Ask for it if you don't have it — never guess.

Optional (only send what you actually know — never invent metadata):

- `url` (string (https URL), **required**) — Where the game is played. Must be https and publicly reachable; the server fetches it to verify and to read OpenGraph tags. Max 2048 chars.
- `embed_url` (string (https URL)) — Alternate URL to load inside the on-site player when it differs from `url` (for example an itch.io embed URL). Defaults to `url`.
- `title` (string) — Game title. Filled from og:title / <title> when omitted. Max 80 chars.
- `tagline` (string) — One line under the title. Filled from og:description when omitted. Max 160 chars.
- `description` (string) — Longer description shown on the listing page. Max 2000 chars.
- `thumbnail_url` (string (https URL)) — Cover image, ideally 4:3. Filled from og:image when omitted. Copied into Dreambit storage.
- `screenshots` (string[] (https URLs)) — Up to 5 screenshots, copied into Dreambit storage.
- `category` (string) — One category.
- `tags` (string[]) — Up to 5 free-form tags (slugified).
- `platforms` (string[]) — Where it runs. Defaults to ["web"].
- `ai_tools` (string[]) — What it was made with ("Made with" badges). Known values get a label; unknown tools are accepted as slugs.
- `source_code_url` (string (https URL)) — Public repo, if any.
- `creator` (object { name?, url?, x_handle? }) — Who made it, when it is not the caller. Omit when submitting your own game with a session or API key — the listing is attributed to you automatically.
- `slug` (string) — Requested URL slug (2–80 chars, [a-z0-9-]). Generated from the title when omitted; a suffix is added on collision.
- `contact_email` (string) — Reviewer contact. Never displayed.
- `notes` (string) — Notes for the human reviewers. Never displayed. Max 500 chars.

Optional API key: if the user has a Dreambit API key (`db_live_…`, created at https://dreambit.app/me/developer), send it as `Authorization: Bearer <key>`. The listing is then attributed to their account and needs no claim. Never store or print the key beyond the request.

## Steps

1. **Confirm the URL loads.** Fetch it (or ask the user to confirm it is public). Dreambit will reject URLs that are unreachable, private, or not https.
2. **Build the body.** At minimum `{"url": "<game url>"}`. Add `title`, `tagline`, `category`, `tags`, `platforms`, `ai_tools` when known. Include `ai_tools` (e.g. `["claude-code"]`) when you built it — that powers the "Made with" filter.
3. **POST** to `https://dreambit.app/api/v1/submissions` with `Content-Type: application/json`.

   ```bash
   curl -X POST https://dreambit.app/api/v1/submissions \
     -H 'Content-Type: application/json' \
     -d '{"url":"https://example.com/play"}'
   ```

4. **Handle the response.**
   - **201** → read `listing.url` (the public page) and `listing.status` (`live`, or `pending` if held for a human). Report the URL to the user. If `listing.enriched.title` is true, tell the user the title came from their page so they can correct it.
   - **409 `duplicate`** → the game is already listed. Report `existing.url`. Do **not** retry or change the URL to get around it.
   - **429 `rate_limited`** → stop. Tell the user to retry after `Retry-After` seconds. Do not loop.
   - **422 `url_unreachable`** → the page did not respond. Ask the user to check the deployment, then try once more.
   - **400** → fix the field named in `error.field` (or use `error.suggestion` for slug errors) and retry once.
   - **401 `invalid_api_key`** → the key is wrong or revoked. Drop the header (anonymous submission) or ask the user for a valid key. Never silently retry with the same key.
5. **Report** the listing URL, and mention the creator can claim it at that URL if it was submitted anonymously.

## Rules

- Only the user's own games (or explicit, attributed submissions on someone's behalf).
- Never invent titles, descriptions, categories or tools you don't know — leave them out and let the server read the page.
- Never retry a 409. Never loop on 429.
- One submission per game. If unsure whether it's already listed, `GET https://dreambit.app/api/v1/listings?q=<title>` first.
- Don't submit test builds, localhost URLs, or pages that aren't a game.

## Errors

- **400 `invalid_field`** — A field is the wrong type, too long, or an unknown enum value. `error.field` names it.
- **400 `invalid_url`** — `url` (or another URL field) is missing or not a valid https URL.
- **400 `url_not_allowed`** — The URL points at a private/internal address, a literal IP, or a non-https scheme.
- **422 `url_unreachable`** — The URL did not respond with a 2xx/3xx within 8 seconds (or redirected more than 3 times).
- **400 `slug_reserved`** — The requested slug is a reserved word. `error.suggestion` has a free alternative.
- **400 `slug_taken`** — The requested slug is already used. `error.suggestion` has a free alternative.
- **409 `duplicate`** — A listing with the same canonical URL already exists. `existing` has its slug, status and page URL. Do not retry.
- **429 `rate_limited`** — Too many submissions. Honour `Retry-After` / `error.retry_after_seconds`.
- **503 `submissions_closed`** — Submissions are temporarily closed.
- **401 `invalid_api_key`** — The Bearer key is unknown or revoked. Never falls back to anonymous — fix or drop the header.

## Also available

- MCP server (same capabilities as tools): `claude mcp add dreambit --transport http https://dreambit.app/api/mcp`
- Machine-readable docs: https://dreambit.app/llms.txt · https://dreambit.app/openapi.json · https://dreambit.app/feed.json
- Community: https://discord.gg/BrnjNAsTA3
