INDIEPRIME

Developers and agents

For AI agents and scripts

Everything on IndiePrime works over plain JSON. One key, one request, one live game page. Nothing to scrape and no forms to click.

Quick start

  1. Create an API key

    Sign in and open your studio. Press Create key. Copy the key once. It starts with ipk_. You cannot see it again.

  2. Create a listing

    Send one POST. Creators join for $10 once. Non-member games are saved as drafts until the creator joins. The response includes payment_required and checkout_url. The creator opens that link, signs in with the same account, and joins once. Membership covers additional games. The bundle includes 2,000 Asset Yard credits. API keys cannot make payments.

    curl -X POST https://indieprime.com/api/v1/games \
      -H "Authorization: Bearer ipk_YOUR_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "title": "Neon Drift",
        "tagline": "Race a comet through a neon city.",
        "genres": ["racing", "arcade"],
        "cover_url": "https://you.github.io/neon-drift/cover.png",
        "play_url": "https://you.github.io/neon-drift/",
        "play_mode": "embed",
        "price_cents": 0,
        "status": "published"
      }'
    import requests
    
    resp = requests.post(
        "https://indieprime.com/api/v1/games",
        headers={"Authorization": "Bearer ipk_YOUR_KEY"},
        json={
            "title": "Neon Drift",
            "tagline": "Race a comet through a neon city.",
            "genres": ["racing", "arcade"],
            "cover_url": "https://you.github.io/neon-drift/cover.png",
            "play_url": "https://you.github.io/neon-drift/",
            "play_mode": "embed",
            "price_cents": 0,
            "status": "published",
        },
        timeout=30,
    )
    resp.raise_for_status()
    print(resp.json()["game"]["url"])
    const res = await fetch("https://indieprime.com/api/v1/games", {
      method: "POST",
      headers: {
        "Authorization": "Bearer ipk_YOUR_KEY",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        title: "Neon Drift",
        tagline: "Race a comet through a neon city.",
        genres: ["racing", "arcade"],
        cover_url: "https://you.github.io/neon-drift/cover.png",
        play_url: "https://you.github.io/neon-drift/",
        play_mode: "embed",
        price_cents: 0,
        status: "published",
      }),
    });
    const data = await res.json();
    if (!res.ok) throw new Error(JSON.stringify(data));
    console.log(data.game.url);
  3. Upload a web build (optional)

    Zip your HTML5 build with index.html at the top. Send the raw zip as the body. Up to 100 MB. The game page then gets a PLAY NOW button.

    curl -X PUT https://indieprime.com/api/v1/games/neon-drift/build \
      -H "Authorization: Bearer ipk_YOUR_KEY" \
      -H "Content-Type: application/zip" \
      --data-binary @build.zip
    import requests
    
    with open("build.zip", "rb") as f:
        resp = requests.put(
            "https://indieprime.com/api/v1/games/neon-drift/build",
            headers={
                "Authorization": "Bearer ipk_YOUR_KEY",
                "Content-Type": "application/zip",
            },
            data=f,
            timeout=300,
        )
    resp.raise_for_status()
    print(resp.json())
    import { readFile } from "node:fs/promises";
    
    const zip = await readFile("build.zip");
    const res = await fetch("https://indieprime.com/api/v1/games/neon-drift/build", {
      method: "PUT",
      headers: {
        "Authorization": "Bearer ipk_YOUR_KEY",
        "Content-Type": "application/zip",
      },
      body: zip,
    });
    console.log(res.status, await res.json());

Copy this prompt into your agent

Paste this into Claude, ChatGPT, Cursor or any agent that can make HTTP requests. Fill in the brackets.

Read https://indieprime.com/llms.txt and follow it.
Then list my game on IndiePrime.

Game name: [YOUR GAME NAME]
Where it lives: [LINK TO YOUR GAME PAGE OR WEB BUILD]
My API key: [ipk_ KEY FROM https://indieprime.com/studio]

Rules:
- Use POST /api/v1/games with the Authorization: Bearer header.
- Write a tagline under 160 characters and a plain description.
- Every URL must use https.
- Set status to published.
- If the API returns 422, read the "fields" object, fix those fields and try again.
- When you finish, print the public game URL.

Listing schema

Send these fields as JSON to create or update a game. Only title is required. Every URL must be https. Store links must be on that store's own domain.

FieldTypeRequiredRules
titlestringyesThe name of the game.
slugstringnoThe address: /g/slug. Made from the title if you skip it. Lowercase letters, numbers and hyphens.
taglinestringnoMax 160 characters.
descriptionstringnoMax 8000 characters. Line breaks are kept.
developer_namestringnoYou or your studio.
made_withstringnoEngine or tools, for example Godot.
genresstring[]noMax 5. Allowed values: action adventure arcade card casual horror idle management platformer puzzle racing roguelike rpg shooter simulation space sports stealth strategy survival tactics tower-defense visual-novel voxel educational multiplayer
tagsstring[]noMax 8 free-form tags.
cover_urlhttps URLnoA 16:9 image works best.
screenshotshttps URL[]noUp to 8 images.
play_urlhttps URLnoWhere the game plays in a browser.
play_modestringnoembed plays on the page. external opens a new tab. none shows no play button.
price_centsintegerno0 to 100000. Zero means free. US dollars in cents.
pay_what_you_wantbooleannoLet the player pick the price.
pay_urlhttps URLnoYour own checkout link. IndiePrime has a 10% revenue share.
downloadsobjectnoKeys: windows mac linux android . Values are https URLs.
storesobjectnoKeys: steam ios google_play amazon itch epic gog microsoft humble other . Values are https URLs on the store's own domain.
statusstringnopublished or draft.
{
  "title": "Neon Drift",
  "slug": "neon-drift",
  "tagline": "Race a comet through a neon city.",
  "description": "Drift, boost and outrun the storm.\nNew tracks every week.",
  "developer_name": "Comet Club",
  "made_with": "Godot",
  "genres": ["racing", "arcade"],
  "tags": ["neon", "short runs"],
  "cover_url": "https://you.github.io/neon-drift/cover.png",
  "screenshots": ["https://you.github.io/neon-drift/s1.png"],
  "play_url": "https://you.github.io/neon-drift/",
  "play_mode": "embed",
  "price_cents": 499,
  "pay_what_you_want": false,
  "pay_url": "https://buy.stripe.com/your-link",
  "downloads": {"windows": "https://you.itch.io/neon-drift/win.zip"},
  "stores": {"steam": "https://store.steampowered.com/app/123456"},
  "status": "published"
}

Endpoints

Base URL: https://indieprime.com. Send your key as Authorization: Bearer ipk_....

MethodPathWhat it does
GET/api/v1/gamesSearch and list games. Query: q, genre, platform, price, sort, page, per_page. Public.
GET/api/v1/games/{slug}Read one game. Public.
POST/api/v1/gamesCreate a game. Returns 201 and {"game": {...}}.
PATCH/api/v1/games/{slug}Change some fields of your game. Returns 200.
DELETE/api/v1/games/{slug}Delete your game.
PUT/api/v1/games/{slug}/buildUpload a web build. Body is the raw zip. Header Content-Type: application/zip. Max 100 MB.
POST/api/v1/importSend {"url": "https://..."}. Get back a suggestion object you can review and post.
GET/api/v1/mineList your own games, drafts included.
POST/api/v1/keysCreate an API key. Body {"name": "my agent"}. The secret shows once.
GET/api/v1/keysList your keys. Only a prefix is shown.
DELETE/api/v1/keys/{id}Revoke a key.

Machine-readable files

FileFor
/llms.txtA short guide written for language models.
/api/v1/openapi.jsonThe full OpenAPI description. Point a tool generator at it.
/.well-known/indieprime.jsonDiscovery file. Lists the API base URL and the docs.

Errors

A bad request returns 422. The body has a short error and a fields object. Each key is a field name. Nested fields use dots, like stores.steam. Fix those fields and send the request again.

HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
  "error": "Some fields need a fix.",
  "fields": {
    "title": "Title is required.",
    "stores.steam": "Steam links must be on store.steampowered.com.",
    "downloads.windows": "Use an https link."
  }
}

Rate limits

  • 30 writes per minute per account. Writes are POST, PUT, PATCH and DELETE.
  • Reads of public games have no set limit. Be kind and cache what you can.
  • If you go over, wait a minute and try again.

MCP and tool-use friendly

Predictable JSON

Every response is JSON. Success returns the object. Failure returns error and, for bad input, fields. No HTML surprises.

Safe to retry

Updates go to a slug, so sending the same PATCH twice gives the same game. An agent can repeat a step without making a duplicate.

Self-describing

Use /api/v1/openapi.json to generate tools for an MCP server or a function-calling agent in minutes.

One key per agent

Make a key for each agent. Revoke it in your studio when the job is done.