API reference

POST /index

Trigger an index run against a Git workspace. Idempotent at the file level via content hash.

The indexer worker exposes a single mutating endpoint that pulls a workspace, parses it, embeds its symbols, and persists everything into your tenant rows in Supabase Postgres.

Endpoint

POST https://api.prom.codes/index
Authorization: Bearer <PROMETHEUS_WORKER_TOKEN>
Content-Type: application/json

api.prom.codes is a transparent reverse proxy (Vercel Edge runtime, Frankfurt) that forwards the request to the indexer worker on Railway. CORS preflight (OPTIONS) is handled at the proxy, hop-by-hop headers are stripped, and the upstream status and body are passed through verbatim. The same surface is reachable under https://prom.codes/api/v1/index if you prefer the main domain.

Request body

{
  "workspaceId": "01J5...uuid",
  "source": {
    "type": "git",
    "url": "https://github.com/owner/repo",
    "ref": "main",
    "auth": {
      "type": "token",
      "token": "ghp_..."
    }
  },
  "options": {
    "include": ["src/**/*.ts", "packages/**/*.{ts,tsx}"],
    "exclude": ["**/*.test.ts", "**/node_modules/**"],
    "maxFileSizeBytes": 524288
  }
}

Fields

FieldTypeRequiredNotes
workspaceIdUUIDyesPre-created workspace; tenant-scoped.
source.type"git"yesOnly Git is supported today. local, s3 planned.
source.urlstringyesHTTPS clone URL.
source.refstringnoBranch, tag, or commit SHA. Defaults to remote HEAD.
source.auth.tokenstringnoRequired for private repos.
options.includestring[]noGlob allow-list. Defaults to common code extensions.
options.excludestring[]noGlob deny-list applied after include.
options.maxFileSizeBytesintegernoSkip files larger than this. Defaults to 512 KB.

Response

{
  "ok": true,
  "runId": "01J6...uuid",
  "fileCount": 124,
  "symbolCount": 1812,
  "chunkCount": 1812,
  "embeddedCount": 1812,
  "skippedUnchanged": 0,
  "embedMs": 4220,
  "provider": "voyage",
  "model": "voyage-code-3",
  "dim": 1024,
  "region": "us"
}

skippedUnchanged reports how many files were skipped because their SHA-256 content hash matched the previously indexed version. Run POST /index twice in a row and you should see all files in the skipped count — that is the file-level idempotency contract.

Errors

StatusCodeMeaning
400INVALID_BODYSchema validation failed. Body lists the offending field.
401UNAUTHORIZEDMissing or invalid bearer token.
403FORBIDDEN_WORKSPACEToken does not own workspaceId.
404WORKSPACE_NOT_FOUNDWorkspace UUID does not exist.
422CLONE_FAILEDGit clone failed; see details.gitStderr.
500EMBED_FAILEDEmbedding provider returned an error.
502STORAGE_UNAVAILABLESupabase unreachable. Retry with backoff.