---
title: "Index My Site API reference | Index My Site"
description: "Use the Index My Site API to create indexing jobs of up to 2000 URLs, check per-URL status, and read your credit balance with an API key."
canonical: "https://indexmysite.app/docs/api"
language: "en"
---

# API reference

Use the Index My Site API to create indexing jobs of up to 2000 URLs, check per-URL status, and read your credit balance with an API key.

The API gives you everything the web app does. Base URL:

```
https://indexmysite.app
```

Requests and responses use JSON. The [OpenAPI document](https://indexmysite.app/openapi.json) describes every route in a machine-readable form.

## Authentication

Create an API key in the app under **Settings**, then **Connections**. Send it as a bearer token on every request:

```
curl https://indexmysite.app/api/credits \
  -H "Authorization: Bearer $INDEXMYSITE_API_KEY"
```

Treat API keys as secrets. You can revoke a key at any time from the same settings page.

## Create a job

`POST /api/indexing/jobs`

```
{
  "urls": ["https://example.com/new-post", "https://example.com/pricing"],
  "name": "September launch"
}
```

| Field | Type | Notes |
| --- | --- | --- |
| `urls` | `string[]` | Required. 1 to 2000 public URLs. Duplicates are submitted once. |
| `name` | `string` | Optional label shown in the app and in job lists. |
| `projectId` | `string` | Optional. Files the job under one of your [projects](https://indexmysite.app/docs/projects). Omit to leave it unassigned. |

Each URL uses one credit. If your balance runs out part way through a job, the remaining URLs wait with the status `awaiting_credits` until you buy more credits or, with auto reload on, we top up automatically and continue.

Send an `Idempotency-Key` header with a unique value to make retries safe. A repeated request with the same key returns the original job instead of creating and charging a new one.

```
curl -X POST https://indexmysite.app/api/indexing/jobs \
  -H "Authorization: Bearer $INDEXMYSITE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: launch-2026-09-17" \
  -d '{"urls":["https://example.com/new-post"],"name":"September launch"}'
```

The response is `201 Created` with a `job` object: its `id`, `name`, `createdAt`, `total`, a `counts` map of URLs per status, and a `urls` array with the initial status of each URL. A repeated idempotent request returns the same job.

## List jobs

`GET /api/indexing/jobs`

Returns `{ "jobs": [...] }`, newest first. Each job has its `id`, `name`, `createdAt`, `total`, and a `counts` map of URLs per status.

## Get a job

`GET /api/indexing/jobs/:id`

Returns `{ "job": {...} }` with every URL and its status.

| Status | Meaning |
| --- | --- |
| `queued` | Just received; a credit is about to be reserved. |
| `awaiting_credits` | Waiting for credits. Buy more or turn on auto reload to continue. |
| `funded` | A credit is reserved; waiting to be sent. |
| `submitting` | Being sent for indexing. |
| `submitted` | Sent for indexing. |
| `checking` | Being checked for indexing. |
| `not_indexed` | Not indexed at the last check. Checks continue until the final check around day 14. |
| `indexed` | Indexed. Final. |
| `refunded` | Confirmed as not indexed after the final check (around day 14); the credit was returned. Final. |
| `failed` | Could not be processed; no credit used. Final. |

## Projects

Projects group jobs for one client or site. Every job object includes `projectId`, which is `null` for unassigned jobs.

`GET /api/indexing/projects`

Returns `{ "projects": [...], "nextCursor": null | string }`, 200 projects a page in a stable order. Pass `nextCursor` back as `?after=<cursor>` to fetch the next page; `nextCursor` is `null` on the last page.

`POST /api/indexing/projects` with `{ "name": "Acme Co. website" }` creates a project and returns `{ "project": {...} }`.

`GET /api/indexing/projects/:id`

Returns `{ "project": {...}, "jobs": [...] }` with the project’s 100 most recent jobs. The project’s `stats` cover every URL in the project, not only the listed jobs.

`PATCH /api/indexing/projects/:id` with `{ "name": "New name" }` renames a project and returns `{ "project": {...} }`.

Each project has `id`, `name`, `createdAt`, `total`, a `counts` map of URLs per status, and `stats`:

| Field | Meaning |
| --- | --- |
| `indexed`, `notIndexed`, `refunded`, `failed`, `pending` | Counts across every URL in the project. `pending` includes pages not indexed yet until their credit is returned. |
| `completed` | URLs from completed batches. |
| `completedIndexed` | Indexed URLs from completed batches. |
| `indexRate` | `completedIndexed / completed * 100`, rounded to two decimals, or `null` before the first finished result. Pending and failed URLs are excluded. |

Compute rates from `completedIndexed` and `completed`, not from `indexed`, which counts URLs whose batches are still running.

## Credits

`GET /api/credits`

Returns your `balance`, whether you have purchased before (`hasPurchased`), whether a card is saved (`hasPaymentMethod`), and your auto reload settings (`autoReloadEnabled`, `autoReloadAmountCents`).

## Errors

Errors return a JSON body with an `error` code and a human-readable `message`. Common cases:

| Status | Meaning |
| --- | --- |
| `400` | Invalid request, such as a malformed URL or more than 2000 URLs. |
| `401` | Missing or invalid API key. |
| `404` | Unknown job ID. |
| `429` | Too many requests. Wait and retry. |

## Rate limits

The API is limited per account to keep the service reliable for everyone. If you hit a `429`, back off and retry after a short delay.
