Data Extraction

Define a schema once, then extract structured data from any text —consistently, every time.

How It Works

Backbone takes a standard JSON Schema definition and uses it to extract structured output from unstructured text. You define the fields, types, and constraints — Backbone returns validated, schema-conformant JSON.

The workflow is: define schema → commit version → send text → receive structured output.

Schema Management

Before you can extract anything, you need a schema. Schemas live inside projects and support full version control.

Creating a Schema

Schemas have a name, optional description, and a JSON Schema definition:

{
  "type": "object",
  "properties": {
    "company": { "type": "string" },
    "invoice_number": { "type": "string" },
    "total": { "type": "number" },
    "line_items": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "description": { "type": "string" },
          "quantity": { "type": "integer" },
          "price": { "type": "number" }
        }
      }
    }
  },
  "required": ["company", "invoice_number"]
}

Version Control

Every time you change your schema, you create a new version. Versions are immutable —this gives you a full audit trail of every change.

You can:

  • Commit new versions with a change description
  • Deactivate versions you don't want used anymore
  • Re-activate a historical version (creates a new version as a copy, preserving the audit trail)
  • Pin extractions to a specific version for reproducibility

Each new version auto-increments the version number and updates the latest label.

Labels

Labels are named pointers to specific schema versions. They decouple your application code from version numbers, enabling controlled rollouts.

How Labels Work

Every schema gets a latest label automatically, updated on each new version. You create custom labels for deployment stages:

LabelPoints toPurpose
latestv5 (auto)Always the newest version
productionv3What your API consumers use
stagingv5What you're testing

Your application resolves schemas by ID + label —when you're ready to promote, just move the label pointer.

Managing Labels

POST /api/v1/projects/{projectId}/schemas/{schemaId}/labels

Create a label:

{
  "name": "production",
  "schemaVersionId": "version-uuid"
}

Update a label to point to a different version:

PUT /api/v1/projects/{projectId}/schemas/{schemaId}/labels/{labelName}

{
  "schemaVersionId": "new-version-uuid"
}

Label names must be lowercase alphanumeric with hyphens (e.g., production, staging, v2-rollback). The system latest label cannot be deleted.

Resolving Schemas

GET /api/v1/projects/{projectId}/schemas/{schemaId}/resolve

Resolve a schema by ID and optional label to get the JSON Schema definition for a specific version:

Request

curl "https://backbone.manfred-kunze.dev/api/v1/projects/{projectId}/schemas/{schemaId}/resolve?label=production" \
  -H "Authorization: Bearer sk_your_api_key"
ParameterTypeRequiredDescription
labelstringNoLabel to resolve (defaults to latest)

Response:

{
  "schemaId": "uuid",
  "schemaName": "invoice-schema",
  "versionId": "uuid",
  "versionNumber": 3,
  "jsonSchema": {
    "type": "object",
    "properties": {
      "company": { "type": "string" },
      "total": { "type": "number" }
    }
  },
  "label": "production"
}

Validate Before Committing

POST /api/v1/projects/{projectId}/schemas/{schemaId}/validate

Check if a schema is valid before you commit it. Returns structured errors and warnings:

{
  "jsonSchema": {
    "type": "object",
    "properties": {
      "name": { "type": "string" }
    }
  }
}

Test Against Sample Text

POST /api/v1/projects/{projectId}/schemas/{schemaId}/test

Run an extraction against sample text without persisting the result. Great for iterating on your schema:

Request

curl -X POST https://backbone.manfred-kunze.dev/api/v1/projects/{projectId}/schemas/{schemaId}/test \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk_your_api_key" \
  -d '{
    "jsonSchema": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "email": { "type": "string" }
      }
    },
    "sampleText": "Contact Jane Smith at [email protected]",
    "model": "gpt-4o"
  }'

The response includes token usage and processing time so you can estimate costs:

{
  "success": true,
  "extractedData": { "name": "Jane Smith", "email": "[email protected]" },
  "inputTokens": 85,
  "outputTokens": 22,
  "processingDurationMs": 890,
  "modelUsed": "gpt-4o"
}

Running Extractions

Synchronous

POST /api/v1/projects/{projectId}/extractions

The standard extraction endpoint. Send text, get structured data back immediately.

Request body:

FieldTypeRequiredDescription
schemaIdstringYesSchema to use for extraction
schemaVersionIdstringNoPin to a specific version (defaults to latest active)
inputTextstringYesText to extract data from
modelstringYesPlatform model name (e.g., gpt-4o) or provider/model for BYOK

Request

curl -X POST https://backbone.manfred-kunze.dev/api/v1/projects/{projectId}/extractions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk_your_api_key" \
  -d '{
    "schemaId": "your-schema-id",
    "inputText": "Invoice #INV-2024-001 from Acme Corp. Total: $1,250.00",
    "model": "gpt-4o"
  }'

Asynchronous

POST /api/v1/projects/{projectId}/extractions/async

For large inputs, submit an extraction for background processing. You get back a 202 Accepted with a Location header to poll:

HTTP/1.1 202 Accepted
Location: /api/v1/projects/{projectId}/extractions/{id}
Retry-After: 5

Poll the Location URL until status changes from PENDING/PROCESSING to COMPLETED or FAILED.

Estimate Tokens First

POST /api/v1/projects/{projectId}/extractions/estimate

Before running an extraction, you can estimate the cost:

{
  "inputTokens": 4200,
  "estimatedOutputTokens": 350,
  "strategy": "SINGLE_SHOT"
}

The strategy field tells you which processing path will be used.

Extraction Strategies

Backbone automatically picks the best strategy based on input size:

StrategyToken RangeWhat Happens
Single-shotUnder 10K tokensEntire input processed in one LLM call
Chunked10K - 100K tokensInput split into overlapping chunks, results merged
AsyncOver 100K tokensBackground processing with polling

Re-running Extractions

POST /api/v1/projects/{projectId}/extractions/{id}/rerun

Need to retry an extraction with the same config? Hit the rerun endpoint. Creates a new extraction —the original stays untouched.

Listing and Filtering

GET /api/v1/projects/{projectId}/extractions

ParameterTypeDescription
searchstringFilter by model name
schemaVersionIdstringFilter by schema version
statusstringPENDING, PROCESSING, COMPLETED, or FAILED
pagenumberPage number (0-based)
sizenumberPage size (default: 20)

Use Cases

  • Contact extraction —names, emails, phone numbers from unstructured text
  • Invoice processing —invoice numbers, dates, amounts, line items from documents
  • Resume parsing —skills, experience, education from CVs
  • Document analysis —key fields from contracts, reports, forms
  • Data entry automation —turn free-text notes into structured database records

Was this page helpful?