Skip to main content
Core.Today

Databases

A high-performance document database built on OpenSearch. Supports schema definition, CRUD, full-text search, and vector search.

Key Features

  • Schema definition: field types, indexing options, vector field configuration
  • CRUD operations: single/bulk document create, read, update, delete
  • Full-text search: OpenSearch Query DSL support (match, term, bool, range)
  • Vector search: k-NN semantic search (Pro plan and above)
  • Aggregations: terms, date_histogram, statistical aggregations

Credit Costs

Database operations deduct credits by type. Credits are automatically refunded if an operation fails.

OperationEndpointCredits
Create documentPOST /documents0.1
Get documentGET /documents/{id}0.05
Update documentPUT, PATCH /documents/{id}0.1
Delete documentDELETE /documents/{id}0.05
Bulk createPOST /documents/_bulk5.0 / 100 docs
Bulk deletePOST /documents/_bulk_delete0.05 / doc
Bulk updatePOST /documents/_bulk_update0.1 / doc
Full-text searchPOST /search0.5
AggregationPOST /aggregate1.0
Vector searchPOST /search/vector2.0

Free: Database create/delete, list, schema changes, stats, document listing, and document count (_count) do not deduct credits.

Plan Limits

Database resource limits vary by subscription plan.

ItemFreeProTeamEnterprise
Max databases15201,000
Max documents per DB10,000500,0005,000,000100,000,000
Max storage100 MB5 GB50 GB500 GB
Max document size100 KB1 MB10 MB100 MB
Max bulk operation size1001,00010,000100,000
Vector search-1,536 dims2,048 dims4,096 dims
1

Create a Database

Create a new database with a schema. The database name must be unique within the team.

Naming Rules

  • Must start with a lowercase letter
  • Only lowercase letters, digits, hyphens (-), and underscores (_) are allowed
  • 3–50 characters
  • aiapi_, db_system_, _ cannot be used as a prefix (reserved prefixes)
curl -X POST https://api.core.today/v1/databases \
  -H "X-API-Key: cdt_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "products",
    "display_name": "Product Catalog",
    "description": "E-commerce product database",
    "schema_fields": {
      "title": {"type": "text", "index": true},
      "description": {"type": "text", "index": true},
      "price": {"type": "float"},
      "category": {"type": "keyword"},
      "tags": {"type": "keyword"},
      "in_stock": {"type": "boolean"},
      "created_at": {"type": "date"}
    }
  }'

Example Response

{
  "database_uid": "db_abc123",
  "name": "products",
  "display_name": "Product Catalog",
  "description": "E-commerce product database",
  "team_id": "team_xyz",
  "schema_fields": {...},
  "document_count": 0,
  "created_at": "2024-12-26T10:00:00Z"
}

Supported Field Types

TypeDescriptionExample
textFull-text searchable text"Product description..."
keywordString for exact matching (filters, aggregations)"electronics"
integerInteger42
long64-bit integer9223372036854775807
float32-bit floating point19.99
double64-bit floating point3.141592653589793
booleantrue/falsetrue
dateISO 8601 date"2024-12-26T10:00:00Z"
objectNested object (indexing can be turned on/off){"key": "value"}
nestedArray of independently queryable objects[{"name": "A"}, ...]
knn_vectorEmbedding for vector search (Pro+)[0.1, 0.2, ...]

Vector Field Configuration

A field for vector search must specify dimension and space_type:

"embedding": {
  "type": "knn_vector",
  "dimension": 1536,
  "space_type": "cosinesimil"
}
2

Document CRUD

Automatic Metadata (_meta)

Every document automatically gets a _meta field:

  • _meta.created_at document creation time (ISO 8601)
  • _meta.updated_at last update time (ISO 8601)
  • _meta.created_by_api_key UID of the API key used to create it

Create Document

docs.databases.crud.createCode

Bulk Create Documents

curl -X POST https://api.core.today/v1/databases/{database_uid}/documents/_bulk \
  -H "X-API-Key: cdt_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "documents": [
      {"id": "product-001", "data": {"title": "Product 1", "price": 99.99}},
      {"id": "product-002", "data": {"title": "Product 2", "price": 149.99}},
      {"id": "product-003", "data": {"title": "Product 3", "price": 199.99}}
    ]
  }'

Response: Returns the success/failure counts and error details.

Get Document

# Get a specific document
curl https://api.core.today/v1/databases/{database_uid}/documents/{doc_id} \
  -H "X-API-Key: cdt_your_api_key"

# Get specific fields only (Field Projection)
curl "https://api.core.today/v1/databases/{database_uid}/documents/{doc_id}?_source=title,price" \
  -H "X-API-Key: cdt_your_api_key"

# List documents (pagination)
curl "https://api.core.today/v1/databases/{database_uid}/documents?size=20&from=0" \
  -H "X-API-Key: cdt_your_api_key"

# List documents - specific fields only
curl "https://api.core.today/v1/databases/{database_uid}/documents?size=20&_source=title,price" \
  -H "X-API-Key: cdt_your_api_key"

_source: Specify a comma-separated list of fields to include only those in the response. Omit it to return all fields.

Update Document

docs.databases.crud.updateCode

Delete Document

curl -X DELETE https://api.core.today/v1/databases/{database_uid}/documents/{doc_id} \
  -H "X-API-Key: cdt_your_api_key"

Bulk Delete

curl -X POST https://api.core.today/v1/databases/{database_uid}/documents/_bulk_delete \
  -H "X-API-Key: cdt_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "ids": ["product-001", "product-002", "product-003"]
  }'

Credits: 0.05 × document count. Non-existent IDs are reported as errors.

Bulk Update

curl -X POST https://api.core.today/v1/databases/{database_uid}/documents/_bulk_update \
  -H "X-API-Key: cdt_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "documents": [
      {"id": "product-001", "data": {"price": 179.99, "in_stock": false}},
      {"id": "product-002", "data": {"price": 129.99}},
      {"id": "product-003", "data": {"category": "accessories"}}
    ]
  }'

Credits: 0.1 × document count. Behaves as a partial update (PATCH); only the specified fields are updated.

Document Count

# Total document count
curl https://api.core.today/v1/databases/{database_uid}/documents/_count \
  -H "X-API-Key: cdt_your_api_key"

# Conditional count (pass JSON via the query parameter)
curl "https://api.core.today/v1/databases/{database_uid}/documents/_count?q=%7B%22term%22%3A%7B%22category%22%3A%22electronics%22%7D%7D" \
  -H "X-API-Key: cdt_your_api_key"

Free: No credits are deducted. Response: {"count": 1234}

Exclude Fields (_source_excludes)

You can exclude specific fields from the response. _source when used together, is converted into includes/excludes.

docs.databases.crud.excludeCode
3

Search

Provides powerful search using the OpenSearch Query DSL.

Full-text Search

curl -X POST https://api.core.today/v1/databases/{database_uid}/search \
  -H "X-API-Key: cdt_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "query": {
      "match": {
        "description": "wireless headphones"
      }
    },
    "size": 10,
    "from": 0,
    "_source": ["title", "price", "category"]
  }'

_source: The list of fields to include in the response. Omit it to return all fields.

Compound Search (Boolean Query)

{
  "query": {
    "bool": {
      "must": [
        {"match": {"description": "headphones"}}
      ],
      "filter": [
        {"term": {"category": "electronics"}},
        {"range": {"price": {"gte": 100, "lte": 300}}}
      ],
      "should": [
        {"term": {"in_stock": true}}
      ]
    }
  },
  "sort": [
    {"price": {"order": "asc"}}
  ],
  "highlight": {
    "fields": {"description": {}}
  }
}

Deep Pagination (search_after)

from + size exceeds 10,000, you must use search_after. Pass the last sort value of the previous result to fetch the next page.

{
  "query": {"match_all": {}},
  "sort": [
    {"_meta.created_at": {"order": "desc"}},
    {"_id": {"order": "asc"}}
  ],
  "size": 100,
  "search_after": ["2025-01-01T00:00:00Z", "product-500"]
}

Note: search_after When using it, you must specify sort, and it is recommended to include _id as a tie-breaker.

Search Response Example

{
  "total": 42,
  "hits": [
    {
      "id": "product-001",
      "score": 1.5,
      "data": {
        "title": "Wireless Headphones",
        "price": 199.99,
        ...
      },
      "highlight": {
        "description": ["High-quality <em>wireless</em> <em>headphones</em>..."]
      }
    }
  ]
}
4

Vector Search (k-NN)

Pro+

Semantic similarity search using embedding vectors. You can store and search text/image embeddings generated by AI models.

Schema with a Vector Field

{
  "name": "articles",
  "schema_fields": {
    "title": {"type": "text"},
    "content": {"type": "text"},
    "embedding": {
      "type": "knn_vector",
      "dimension": 1536,
      "space_type": "cosinesimil"
    }
  }
}

Vector Search Request

curl -X POST https://api.core.today/v1/databases/{database_uid}/search/vector \
  -H "X-API-Key: cdt_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "field": "embedding",
    "vector": [0.1, 0.2, 0.3, ...],
    "k": 10,
    "filter": {
      "term": {"category": "technology"}
    },
    "_source": ["title", "content"]
  }'

Embedding Tips

OpenAI's text-embedding-3-small (1536 dims) or Cohere's embedding models can convert text into vectors. Generate embeddings via the LLM API and store them in the database.

5

Aggregations

Provides aggregation features for data analysis.

curl -X POST https://api.core.today/v1/databases/{database_uid}/aggregate \
  -H "X-API-Key: cdt_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "query": {"match_all": {}},
    "aggregations": {
      "by_category": {
        "terms": {"field": "category", "size": 10}
      },
      "avg_price": {
        "avg": {"field": "price"}
      },
      "price_ranges": {
        "range": {
          "field": "price",
          "ranges": [
            {"to": 100},
            {"from": 100, "to": 200},
            {"from": 200}
          ]
        }
      }
    }
  }'

Aggregation Response Example

{
  "total": 1000,
  "aggregations": {
    "by_category": {
      "buckets": [
        {"key": "electronics", "doc_count": 350},
        {"key": "clothing", "doc_count": 280},
        ...
      ]
    },
    "avg_price": {"value": 149.99},
    "price_ranges": {
      "buckets": [
        {"key": "*-100.0", "doc_count": 200},
        {"key": "100.0-200.0", "doc_count": 500},
        {"key": "200.0-*", "doc_count": 300}
      ]
    }
  }
}
6

Database Management

List Databases

curl https://api.core.today/v1/databases \
  -H "X-API-Key: cdt_your_api_key"

Add Fields

You can add new fields to an existing database. The type of existing fields cannot be changed.

curl -X POST https://api.core.today/v1/databases/{database_uid}/fields \
  -H "X-API-Key: cdt_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": {
      "rating": {"type": "float"},
      "reviews_count": {"type": "integer"}
    }
  }'

Get Stats

curl https://api.core.today/v1/databases/{database_uid}/stats \
  -H "X-API-Key: cdt_your_api_key"

Delete Database

Warning: Deleting a database is irreversible. All documents are permanently deleted.

curl -X DELETE https://api.core.today/v1/databases/{database_uid} \
  -H "X-API-Key: cdt_your_api_key"

Field Value Autocomplete (Suggest)

keyword type field values via autocomplete.

curl "https://api.core.today/v1/databases/{database_uid}/suggest?field=category&prefix=ele&limit=10" \
  -H "X-API-Key: cdt_your_api_key"

# Response: {"suggestions": ["electronics", "electric-vehicles", ...]}

Free: No credits are deducted.

Saved Queries

You can save and manage frequently used search queries. All free.

docs.databases.mgmt.queriesCode

SDK Examples

JavaScript / TypeScript

import axios from 'axios';

const api = axios.create({
  baseURL: 'https://api.core.today/v1',
  headers: { 'X-API-Key': 'cdt_your_api_key' }
});

// Create a document
const doc = await api.post('/databases/db_abc123/documents', {
  id: 'product-001',
  data: { title: 'My Product', price: 99.99 }
});

// Search
const results = await api.post('/databases/db_abc123/search', {
  query: { match: { title: 'product' } },
  size: 10
});

console.log(results.data.hits);

Python

import requests

API_KEY = "cdt_your_api_key"
BASE_URL = "https://api.core.today/v1"
headers = {"X-API-Key": API_KEY}

# Create a document
response = requests.post(
    f"{BASE_URL}/databases/db_abc123/documents",
    headers=headers,
    json={
        "id": "product-001",
        "data": {"title": "My Product", "price": 99.99}
    }
)

# Search
results = requests.post(
    f"{BASE_URL}/databases/db_abc123/search",
    headers=headers,
    json={
        "query": {"match": {"title": "product"}},
        "size": 10
    }
)

for hit in results.json()["hits"]:
    print(hit["data"]["title"])

Error Responses

When a request fails, the following error responses are returned. If an operation that deducted credits fails, the credits are automatically refunded.

402 — Insufficient Credits

{
  "detail": "Insufficient credits. Required: 0.50, Available: 0.12"
}

404 — Database or Document Not Found

{
  "detail": "Database not found"
}
// or
{
  "detail": "Document not found"
}

400 — Validation Failed

{
  "detail": "Database with name 'products' already exists"
}
// or
{
  "detail": "Invalid query: Query type 'script' is not allowed"
}
// or
{
  "detail": "Pagination limit exceeded: from (9990) + size (20) = 10010 exceeds maximum of 10000. Use search_after for deep pagination."
}

403 — Plan Limit

{
  "detail": "Vector search is not available in your plan"
}
// or
{
  "detail": "Maximum number of databases (1) reached for your plan"
}
R

Reseller: Per-customer Data Isolation

When a team with reseller mode enabled sends an X-Customer-Id header to the public document endpoints, all document reads/writes/searches within a single database are automatically isolated to that end-customer. You do not need to create a separate DB per customer.

How It Works

  • Writes: On create/bulk-create/update, the document is automatically tagged with that customer.
  • Reads & search: Get/search/count/vector search are automatically filtered to that customer's documents.
  • Cross-access blocked: Getting/deleting another customer's document returns 404 (existence is not revealed either).
  • Without the header: for reseller teams the request is rejected with 400 (customer_scope_required) — isolation never silently turns off. To manage the entire dataset directly, send an explicit X-Customer-Scope: all header. Non-reseller teams are unaffected.

Applicable endpoints: /databases/{uid}/documents (and /_bulk), /documents/{doc_id}, /documents/_count, /search, /search/vector.

Isolation guarantee: One customer's data is never exposed to another. If a non-reseller team sends this header, it is ignored.

Reserved field prefix _ — differs from the naming rule

Document field names starting with an underscore (_) are system-reserved and are automatically stripped from the document body (so internal fields such as the customer tag cannot be spoofed). This is a database name prefix rule (forbidding aiapi_, db_system_, _ as the start of a DB name) described earlier, but a different rule. The former applies to a document's field keys, the latter to the DB's name.

Example — same DB, two customers' document sets isolated from each other

docs.databases.reseller.exampleCode

Best Practices

  • Schema design: Use the keyword type for fields frequently used in search, and the text type for fields that need full-text search.
  • Bulk operations: When processing multiple documents, use the /_bulk endpoints.
  • Pagination: from + size can go up to 10,000. Beyond that, use search_after together with sort.
  • Filter vs query: Put exact value matching in filter, and searches that need scoring in query.
  • Vector search: Set the vector dimension to match your embedding model; using it together with filters is more efficient.