Get Your API Key

Create a free account to generate API keys and start building automated indexing into your workflow.

ExhibitX Developer API

Build automated book indexing into your workflow. Upload PDFs, run the AI pipeline, and download professional indexes programmatically.

Base URL
https://exhibitx-backend-production.up.railway.app/api/v1

Authentication

All API requests require an API key. Pass it via the Authorization header or the X-API-Key header.

Authorization Header
curl -X GET 'https://exhibitx-backend-production.up.railway.app/api/v1/projects' \
  -H 'Authorization: Bearer ixia_live_...' \
  -H 'Content-Type: application/json'

Create an account to generate your API key from the developer dashboard. Keys are prefixed with ixia_live_ for production and ixia_test_ for sandbox.

Quick Start

Four steps to go from a PDF to a professional index:

1

Estimate cost

BASH
curl -X POST 'https://exhibitx-backend-production.up.railway.app/api/v1/estimate' \
  -H 'X-API-Key: ixia_live_your_api_key' \
  -F 'file=@book.pdf'
2

Create project

BASH
curl -X POST 'https://exhibitx-backend-production.up.railway.app/api/v1/projects' \
  -H 'X-API-Key: ixia_live_your_api_key' \
  -F 'file=@book.pdf' \
  -F 'name=My Book Index' \
  -F 'startPage=13' \
  -F 'endPage=342' \
  -F 'extractionInstructions=Focus on key concepts and named entities'
3

Poll status

BASH
curl -X GET \
  'https://exhibitx-backend-production.up.railway.app/api/v1/projects/proj_abc123/status' \
  -H 'X-API-Key: ixia_live_your_api_key' \
  -H 'Content-Type: application/json'
4

Download index

BASH
curl -X GET \
  'https://exhibitx-backend-production.up.railway.app/api/v1/projects/proj_abc123/index' \
  -H 'X-API-Key: ixia_live_your_api_key' \
  -H 'Content-Type: application/json'

Pricing & Billing

Usage is metered by document tokens. Top up your wallet and pay per document.

PipelineRateExample (100K tokens)
Main Pipeline$0.001 / token$100.00
Legal Citation$0.0005 / token$50.00
Trim$0.0001 / token$10.00

Top up your wallet via the billing API or the dashboard. Enterprise customers can request custom rates by contacting support.

Index Types

The projectType parameter determines which indexing pipeline runs.

TypeDescriptionRate
bookStandard back-of-book index from PDF (default)$0.001/token
bulkEmbedded/large document index. Requires extractionInstructions. Skips subentries.$0.001/token
legal_locorumLegal citation index (Bluebook/OSCOLA). Configure via citationConfig.$0.0005/token
scriptureBible reference index. Configure via scriptureConfig.$0.001/token
classics_locorumClassical text citations (OCD/LSJ). Configure via citationConfig.$0.001/token
author_worksAuthor/works index for music, literature, art, film. Configure via authorWorksConfig.$0.001/token
POST

Estimate Cost

/api/v1/estimateUpload a PDF or DOCX (multipart/form-data, field: "file") to get a token count and price estimate without being charged. Optional: startPage/endPage (integers) for page range; endpointType ("pipeline" | "legal_pipeline" | "trim") for pricing tier; projectType to auto-determine rate.

Request
BASH
curl -X POST \
  'exhibitx-backend-production.up.railway.app/api/v1/estimate' \
  -H 'X-API-Key: ixia_live_your_api_key' \
  -H 'Content-Type: application/json'
Response
JSON
{
  "success": true,
  "data": {
    "tokenCount": 95420,
    "pageCount": 312,
    "endpointType": "pipeline",
    "rate": 0.001,
    "estimatedCost": 95.42,
    "currency": "USD",
    "currentBalance": 150,
    "canAfford": true
  }
}
POST

Create Project

/api/v1/projectsUpload a PDF (multipart/form-data, field: "file") and start the AI indexing pipeline. Charges wallet based on document tokens. Required: file, name. Supports all index types via projectType. See parameter reference below for page ranges, custom instructions, legal/scripture/author-works configs, and more.

Request
BASH
curl -X POST \
  'exhibitx-backend-production.up.railway.app/api/v1/projects' \
  -H 'X-API-Key: ixia_live_your_api_key' \
  -H 'Content-Type: application/json'
Response
JSON
{
  "success": true,
  "data": {
    "projectId": "proj_abc123",
    "operationId": "op_xyz789",
    "statusEndpoint": "/api/v1/projects/proj_abc123/status",
    "cost": {
      "dollars": 95.42,
      "documentTokens": 95420,
      "ratePerToken": 0.001,
      "remainingBalanceDollars": 54.58
    }
  }
}

Create Project Parameters

All parameters are sent as multipart form fields. JSON objects must be stringified.

Required

ParameterTypeDescription
fileFilePDF file to index
namestringProject name

Page Range

ParameterTypeDescription
startPageintegerFirst PDF page to index (auto-detected if omitted)
endPageintegerLast PDF page to index (last page if omitted)
hasPreamblestring"true" if book has roman-numeral preamble pages
preambleStartPageintegerFirst preamble page (absolute PDF page)
preambleEndPageintegerLast preamble page (absolute PDF page)
hasEndnotesstring"true" if book has endnotes
endnoteLocationstring"end_of_book" or "end_of_chapter"
endnotePageRangesJSONArray of start/end ranges for endnote pages
excludedPageRangesJSONPage ranges to skip (e.g., image-only pages)

Index Type & Model

ParameterTypeDescription
projectTypestring"book" (default), "bulk", "legal_locorum", "scripture", "classics_locorum", "author_works"
modelTierstring"standard" (default) or "premium"

Extraction Control

ParameterTypeDescription
extractionGranularitystring"default", "detailed", or "highly_detailed"
extractionInstructionsstringCustom AI guidance (e.g., "Focus on legal terminology")
contextualSubentryMinMentionsintegerMin mentions for subentry generation (default: 5)
maxSubentryDepthintegerSubentry nesting depth: 1-3 (default: 1)

Paragraph IDs

ParameterTypeDescription
useParagraphIdsstring"true" to use paragraph IDs instead of page numbers
paragraphIdPatternstringRegex pattern (e.g., "C\\d*P\\d+")
paragraphIdLocationstring"left", "right", or "inline"

Special Index Configurations (JSON strings)

ParameterFieldsUsed With
scriptureConfigbibleVersion, namingConvention, canons[]scripture
citationConfigcitationSystem, jurisdictions[], includeCategories[], customCitationRuleslegal_locorum, classics_locorum
authorWorksConfigsubjectDomain, includeMetadataauthor_works
GET

Check Status

/api/v1/projects/{projectId}/statusPoll the indexing pipeline status.

Request
BASH
curl -X GET \
  'exhibitx-backend-production.up.railway.app/api/v1/projects/proj_abc123/status' \
  -H 'X-API-Key: ixia_live_your_api_key' \
  -H 'Content-Type: application/json'
Response
JSON
{
  "success": true,
  "data": {
    "operationId": "op_xyz789",
    "status": "in_progress",
    "currentPhase": "Phase 10: Synthesis Generation",
    "progressPercent": 67,
    "startedAt": "2025-01-15T10:30:00Z",
    "updatedAt": "2025-01-15T10:45:00Z"
  }
}
GET

Download Index

/api/v1/projects/{projectId}/indexDownload the completed index as structured JSON.

Request
BASH
curl -X GET \
  'exhibitx-backend-production.up.railway.app/api/v1/projects/proj_abc123/index' \
  -H 'X-API-Key: ixia_live_your_api_key' \
  -H 'Content-Type: application/json'
Response
JSON
{
  "success": true,
  "data": {
    "metadata": {
      "projectId": "proj_abc123",
      "totalTerms": 847,
      "totalSubentries": 234
    },
    "terms": [
      {
        "termId": "t1",
        "name": "carbon emissions",
        "pages": [
          12,
          45,
          46,
          47,
          89
        ],
        "synthesis": "Carbon emissions refer to...",
        "crossReferences": [
          {
            "type": "see_also",
            "targetTermName": "greenhouse gases"
          }
        ]
      }
    ]
  }
}
GET

Export Files

/api/v1/projects/{projectId}/export/downloadDownload formatted export files. Formats: docx, rtf, txt, latex, csv, cdxf, markdown.

Request
BASH
curl -X GET \
  'exhibitx-backend-production.up.railway.app/api/v1/projects/proj_abc123/export/download' \
  -H 'X-API-Key: ixia_live_your_api_key' \
  -H 'Content-Type: application/json'
Response
JSON
{
  "success": true,
  "message": "Binary file download"
}
GET

List Projects

/api/v1/projectsRetrieve a paginated list of your projects with term counts and status.

Request
BASH
curl -X GET \
  'exhibitx-backend-production.up.railway.app/api/v1/projects' \
  -H 'X-API-Key: ixia_live_your_api_key' \
  -H 'Content-Type: application/json'
Response
JSON
{
  "success": true,
  "data": [
    {
      "project_id": "proj_abc123",
      "name": "Climate Policy Analysis",
      "status": "completed",
      "term_count": 847,
      "created_at": "2025-01-15T10:30:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 50,
    "total": 23,
    "total_pages": 1,
    "has_more": false
  }
}
PATCH

Rename Project

/api/v1/projects/{projectId}Rename an existing project.

Request
BASH
curl -X PATCH \
  'exhibitx-backend-production.up.railway.app/api/v1/projects/proj_abc123' \
  -H 'X-API-Key: ixia_live_your_api_key' \
  -H 'Content-Type: application/json'
 \
  -d '{
      "name": "Updated Project Name"
    }'
Response
JSON
{
  "success": true,
  "data": {
    "projectId": "proj_abc123",
    "name": "Updated Project Name"
  }
}
DELETE

Delete Project

/api/v1/projects/{projectId}Permanently delete a project and all associated data.

Request
BASH
curl -X DELETE \
  'exhibitx-backend-production.up.railway.app/api/v1/projects/proj_abc123' \
  -H 'X-API-Key: ixia_live_your_api_key' \
  -H 'Content-Type: application/json'
Response
JSON
{
  "success": true,
  "message": "Project and all associated data have been deleted"
}
POST

Trim Index

/api/v1/projects/{projectId}/trimUse AI to rank terms by importance and trim the index to a target count.

Request
BASH
curl -X POST \
  'exhibitx-backend-production.up.railway.app/api/v1/projects/proj_abc123/trim' \
  -H 'X-API-Key: ixia_live_your_api_key' \
  -H 'Content-Type: application/json'
 \
  -d '{
      "targetTermCount": 500
    }'
Response
JSON
{
  "success": true,
  "data": {
    "operationId": "op_trim_123",
    "currentTermCount": 847,
    "targetTermCount": 500,
    "cost": {
      "dollars": 9.54,
      "remainingBalanceDollars": 45.04
    }
  }
}
GET

Check Balance

/api/v1/billing/balanceCheck your current wallet balance and token rates.

Request
BASH
curl -X GET \
  'exhibitx-backend-production.up.railway.app/api/v1/billing/balance' \
  -H 'X-API-Key: ixia_live_your_api_key' \
  -H 'Content-Type: application/json'
Response
JSON
{
  "success": true,
  "data": {
    "balanceDollars": 150,
    "walletTokens": 100000,
    "rates": {
      "pipeline": {
        "ratePerToken": 0.001
      },
      "legal_pipeline": {
        "ratePerToken": 0.0005
      },
      "trim": {
        "ratePerToken": 0.0001
      }
    }
  }
}
POST

Top Up Wallet

/api/v1/billing/topupCreate a Stripe checkout session to add funds to your wallet.

Request
BASH
curl -X POST \
  'exhibitx-backend-production.up.railway.app/api/v1/billing/topup' \
  -H 'X-API-Key: ixia_live_your_api_key' \
  -H 'Content-Type: application/json'
 \
  -d '{
      "amount_dollars": 100
    }'
Response
JSON
{
  "success": true,
  "data": {
    "checkoutUrl": "https://checkout.stripe.com/c/pay/cs_live_...",
    "amountDollars": 100,
    "walletTokens": 66667
  }
}
GET

Billing History

/api/v1/billing/historyRetrieve a paginated list of billing events.

Request
BASH
curl -X GET \
  'exhibitx-backend-production.up.railway.app/api/v1/billing/history' \
  -H 'X-API-Key: ixia_live_your_api_key' \
  -H 'Content-Type: application/json'
Response
JSON
{
  "success": true,
  "data": {
    "events": [
      {
        "eventId": "evt_123",
        "endpointType": "pipeline",
        "documentTokens": 95420,
        "amountDollars": 95.42,
        "status": "completed",
        "createdAt": "2025-01-15T10:30:00Z"
      }
    ],
    "pagination": {
      "page": 1,
      "total": 5
    }
  }
}
GET

Usage Statistics

/api/v1/usageGet aggregated usage statistics for a date range.

Request
BASH
curl -X GET \
  'exhibitx-backend-production.up.railway.app/api/v1/usage' \
  -H 'X-API-Key: ixia_live_your_api_key' \
  -H 'Content-Type: application/json'
Response
JSON
{
  "success": true,
  "data": {
    "statistics": {
      "total_requests": 1247,
      "successful_requests": 1230
    },
    "billing": {
      "totalSpendDollars": 523.4,
      "totalDocumentTokensProcessed": 523400
    }
  }
}

Read API

Read-only endpoints for accessing project data, terms, and syntheses.

Projects

Access and list your indexing projects

GET

Get Project

/api/v1/projects/{projectId}Get detailed information about a specific project including statistics.

Request
BASH
curl -X GET \
  'exhibitx-backend-production.up.railway.app/api/v1/projects/proj_abc123' \
  -H 'X-API-Key: ixia_live_your_api_key' \
  -H 'Content-Type: application/json'
Response
JSON
{
  "success": true,
  "data": {
    "project_id": "proj_abc123",
    "name": "Climate Policy Analysis",
    "book_title": "Global Climate Governance",
    "book_author": "Dr. Jane Smith",
    "status": "completed",
    "term_count": 847,
    "mention_count": 3254,
    "synthesis_count": 312,
    "cross_reference_count": 156,
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-16T14:22:00Z"
  }
}

Terms

Retrieve terms, page references, and relationships

GET

List Terms

/api/v1/projects/{projectId}/termsGet all terms in a project with their page references and relationships.

Request
BASH
curl -X GET \
  'exhibitx-backend-production.up.railway.app/api/v1/projects/proj_abc123/terms' \
  -H 'X-API-Key: ixia_live_your_api_key' \
  -H 'Content-Type: application/json'
Response
JSON
{
  "success": true,
  "data": [
    {
      "term_id": "term_xyz789",
      "standardized_term": "carbon emissions",
      "user_edit": null,
      "page_refs": "12, 45-47, 89",
      "mention_count": 23,
      "has_synthesis": true,
      "parent_id": null,
      "children_count": 3
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 50,
    "total": 847,
    "total_pages": 17,
    "has_more": true
  }
}
GET

Get Term Details

/api/v1/projects/{projectId}/terms/{termId}Get detailed information about a specific term including mentions and relationships.

Request
BASH
curl -X GET \
  'exhibitx-backend-production.up.railway.app/api/v1/projects/proj_abc123/terms/term_xyz789' \
  -H 'X-API-Key: ixia_live_your_api_key' \
  -H 'Content-Type: application/json'
Response
JSON
{
  "success": true,
  "data": {
    "term_id": "term_xyz789",
    "standardized_term": "carbon emissions",
    "user_edit": null,
    "page_refs": "12, 45-47, 89",
    "mentions": [
      {
        "page": 12,
        "context": "...reducing carbon emissions through policy..."
      },
      {
        "page": 45,
        "context": "...global carbon emissions have increased..."
      }
    ],
    "synthesis": "Carbon emissions refer to the release of carbon dioxide...",
    "parent": null,
    "children": [
      {
        "term_id": "child_1",
        "name": "industrial emissions"
      },
      {
        "term_id": "child_2",
        "name": "transportation emissions"
      }
    ],
    "cross_references": [
      {
        "term_id": "xref_1",
        "name": "greenhouse gases"
      }
    ]
  }
}

Syntheses

AI-generated explanations for each term

GET

List Syntheses

/api/v1/projects/{projectId}/synthesesGet AI-generated synthesis explanations for all terms in a project.

Request
BASH
curl -X GET \
  'exhibitx-backend-production.up.railway.app/api/v1/projects/proj_abc123/syntheses' \
  -H 'X-API-Key: ixia_live_your_api_key' \
  -H 'Content-Type: application/json'
Response
JSON
{
  "success": true,
  "data": [
    {
      "synthesis_id": "syn_abc123",
      "term_id": "term_xyz789",
      "term_name": "carbon emissions",
      "synthesis_text": "Carbon emissions in this work refer to the release of CO2...",
      "model_used": "gpt-4o",
      "created_at": "2025-01-15T12:00:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 50,
    "total": 312,
    "total_pages": 7,
    "has_more": true
  }
}

Rate Limits

Rate limits depend on your plan. Limits are applied per API key.

PlanPer MinutePer Day
Free601,000
Pro30010,000
Enterprise1,000Unlimited

Rate limit headers are included in every response: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.

Error Codes

All errors follow a consistent JSON format:

Error Response Format
{
  "success": false,
  "error": "Human-readable error message",
  "code": "ERROR_CODE"
}
StatusMeaningCommon Cause
400Bad RequestMissing or invalid parameters
401UnauthorizedMissing or invalid API key
402Payment RequiredInsufficient wallet balance
403ForbiddenAPI key lacks required scope
404Not FoundProject or resource does not exist
409ConflictIndex not yet ready for download
429Rate LimitedToo many requests; retry after X-RateLimit-Reset
500Server ErrorInternal error; contact support if persistent