Skip to main content
This guide walks through installing the SDK, authenticating, uploading documents, and running a search — in a few minutes.
Charcoal is currently invite-only. Contact us for access.

Install the SDK

npm install charcoal
Prefer the terminal? Install the CLI instead:
npm install -g @charcoalhq/cli

Authenticate

All API requests require an API key passed as a Bearer token in the Authorization header. Set it as an environment variable:
export CHARCOAL_API_KEY="your_api_key_here"
Or pass it directly when creating the client:
import Charcoal from "charcoal";

const client = new Charcoal({ apiKey: process.env.CHARCOAL_API_KEY });
Keep your API keys secret. Do not expose them in client-side code or commit them to version control.

Managing API keys

List, create, and delete keys via the /v1/api_keys endpoints:
# List
curl https://api.withcharcoal.com/v1/api_keys \
  -H "Authorization: Bearer $CHARCOAL_API_KEY"

# Create
curl -X POST https://api.withcharcoal.com/v1/api_keys \
  -H "Authorization: Bearer $CHARCOAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Production"}'

# Delete
curl -X DELETE https://api.withcharcoal.com/v1/api_keys/1 \
  -H "Authorization: Bearer $CHARCOAL_API_KEY"
The create response includes the full key in rawKey. This is the only time the full key is returned, so store it securely.

Upload documents

Create a namespace and upload documents in a single request. Each document needs a unique id. The namespace is created automatically if it doesn’t exist.
curl -X POST https://api.withcharcoal.com/v1/namespaces/my-docs/documents \
  -H "Authorization: Bearer $CHARCOAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "documents": [
      {
        "id": "doc-1",
        "title": "Getting Started with Widgets",
        "content": "Widgets are the core building block of our platform. To create a widget, navigate to the dashboard and click New Widget.",
        "category": "tutorial"
      },
      {
        "id": "doc-2",
        "title": "Widget API Reference",
        "content": "The Widget API supports CRUD operations. Use POST /widgets to create a new widget with a name and configuration object.",
        "category": "reference"
      },
      {
        "id": "doc-3",
        "title": "Troubleshooting Widget Errors",
        "content": "If a widget fails to render, check that the configuration object includes a valid template_id. Common error: WIDGET_TEMPLATE_NOT_FOUND.",
        "category": "troubleshooting"
      }
    ],
    "schema": {
      "title": { "type": "string", "is_searchable": true },
      "content": { "type": "string", "is_searchable": true },
      "category": { "type": "string", "is_filterable": true }
    }
  }'
Response
{
  "documents_upserted": 3
}
You can upload up to 10,000 documents per request. The schema field defines which attributes are searchable (full-text indexed) and filterable. See Namespaces & Documents for the full schema reference. Search with natural language. Provide an objective (one sentence describing what you’re looking for) and context (a detailed description of your query):
curl -X POST https://api.withcharcoal.com/v1/namespaces/my-docs/search \
  -H "Authorization: Bearer $CHARCOAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "objective": "Fix a widget rendering error",
    "context": "A widget is failing to render and showing WIDGET_TEMPLATE_NOT_FOUND. I need to understand what causes this and how to fix it."
  }'
Response
{
  "session_id": "sess_abc123",
  "status": "completed",
  "documents_scanned": 3,
  "queries_executed": 2,
  "synthesis": "The WIDGET_TEMPLATE_NOT_FOUND error occurs when the widget configuration object is missing a valid template_id. Check that your configuration includes a template_id that corresponds to an existing template.",
  "results": [
    {
      "finding": "Widget rendering failures are caused by missing or invalid template_id in the configuration object",
      "id": "doc-3",
      "excerpts": [
        "If a widget fails to render, check that the configuration object includes a valid template_id. Common error: WIDGET_TEMPLATE_NOT_FOUND."
      ]
    }
  ]
}

Streaming

For real-time progress updates, set stream: true to receive server-sent events:
curl -X POST https://api.withcharcoal.com/v1/namespaces/my-docs/search \
  -H "Authorization: Bearer $CHARCOAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "objective": "Fix a widget rendering error",
    "context": "A widget is failing to render and showing WIDGET_TEMPLATE_NOT_FOUND.",
    "stream": true
  }'
event: status
data: {"message": "Searching documents..."}

event: status
data: {"message": "Analyzing 3 documents..."}

event: session_result
data: {"session_id": "sess_abc123", "status": "completed", "synthesis": "...", "results": [...]}
See Search for the full details on streaming, filters, and multi-turn sessions. Narrow results using attribute filters on fields marked is_filterable:
curl -X POST https://api.withcharcoal.com/v1/namespaces/my-docs/search \
  -H "Authorization: Bearer $CHARCOAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "objective": "Find tutorial content",
    "context": "Show me all tutorial documents.",
    "filters": {"category": "tutorial"}
  }'
See the Filters guide for the full filter syntax.

Next steps

Namespaces & Documents

How documents are organized and schematized.

Search

Streaming, multi-turn sessions, and the search lifecycle.

CLI

Manage Charcoal from your terminal.

API Reference

Full endpoint documentation.