Back to Docs

JSON Tables

Learn about JSON Tables - our premium hosted data backend with 10x faster performance and no rate limits.

JSON Tables

JSON Tables is a premium hosted data backend for customers who outgrow Google Sheets but don’t need the complexity of Airtable or a full database. It provides the same familiar JSON API with 10x better performance, no rate limits, and higher row limits.

Why JSON Tables?

The Problem with Google Sheets at Scale

As your application grows, Google Sheets starts to show its limitations:

Challenge Google Sheets JSON Tables
Response time 2-5 seconds ~50ms
Row limit ~50K (usable) 500K+
Rate limits Google’s quotas (429 errors) Plan-based, no Google limits
Concurrent access Limited Unlimited
Formula complexity Slows everything N/A (pure data)

Same API, Zero Code Changes

The best part? JSON Tables uses the exact same API format as your Google Sheets integration. Migrating is as simple as changing your endpoint URL:

// Before (Google Sheets)
const response = await fetch('https://sheetsjson.com/api/sheets/my-account/products');

// After (JSON Tables)
const response = await fetch('https://sheetsjson.com/api/tables/my-account/products');

That’s it. Your existing code continues to work.

Getting Started

Creating a Table

  1. Navigate to Tables in your dashboard
  2. Click Create Table
  3. Enter a name and optional description
  4. Your table is ready!

Your First API Request

Once you create a table, you’ll get an API endpoint like:

GET /api/tables/your-account/products

The response format is identical to Google Sheets:

{
  "data": [
    {"_row": 1, "id": "uuid-here", "name": "Widget", "price": 29.99},
    {"_row": 2, "id": "uuid-here", "name": "Gadget", "price": 49.99}
  ],
  "meta": {
    "total": 2,
    "limit": 100,
    "offset": 0,
    "table_name": "products"
  }
}

API Reference

Endpoints

Method Endpoint Description
GET /api/tables/:account/:table List rows (paginated)
GET /api/tables/:account/:table/:id Get single row by ID
POST /api/tables/:account/:table Create row(s)
PUT /api/tables/:account/:table/:id Update a row
DELETE /api/tables/:account/:table/:id Delete a row

Query Parameters

All the familiar query parameters work:

Pagination

GET /api/tables/my-account/products?limit=25&offset=50
  • limit - Maximum rows to return (default: 100, max: 1000)
  • offset - Number of rows to skip

Sorting

GET /api/tables/my-account/products?sort=price:desc
  • sort - Field name with direction (asc or desc)
  • Supports sorting by any field in your data

Filtering

GET /api/tables/my-account/products?filter[category]=electronics&filter[available]=true
  • filter[field]=value - Filter by exact match
  • Multiple filters are combined with AND

Field Selection

GET /api/tables/my-account/products?fields=id,name,price
  • fields - Comma-separated list of fields to include
  • Reduces payload size

Creating Rows

Single Row

curl -X POST https://sheetsjson.com/api/tables/my-account/products \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer st_your_api_key" \
  -d '{"name": "New Product", "price": 39.99, "category": "electronics"}'

Response:

{
  "data": [
    {"_row": 3, "id": "uuid-here", "name": "New Product", "price": 39.99, "category": "electronics"}
  ],
  "meta": {
    "created": 1
  }
}

Bulk Insert

curl -X POST https://sheetsjson.com/api/tables/my-account/products \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer st_your_api_key" \
  -d '[
    {"name": "Product A", "price": 19.99},
    {"name": "Product B", "price": 29.99},
    {"name": "Product C", "price": 39.99}
  ]'

Response:

{
  "data": [
    {"_row": 4, "id": "uuid-1", "name": "Product A", "price": 19.99},
    {"_row": 5, "id": "uuid-2", "name": "Product B", "price": 29.99},
    {"_row": 6, "id": "uuid-3", "name": "Product C", "price": 39.99}
  ],
  "meta": {
    "created": 3
  }
}

Updating Rows

You can update by row ID (UUID) or row number:

# By UUID
curl -X PUT https://sheetsjson.com/api/tables/my-account/products/uuid-here \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer st_your_api_key" \
  -d '{"price": 34.99}'

# By row number
curl -X PUT https://sheetsjson.com/api/tables/my-account/products/3 \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer st_your_api_key" \
  -d '{"price": 34.99}'

Deleting Rows

curl -X DELETE https://sheetsjson.com/api/tables/my-account/products/uuid-here \
  -H "Authorization: Bearer st_your_api_key"

Returns 204 No Content on success.

Authentication

Tables support the same authentication methods as Sheets:

API Key (Optional)

If you enable “Require API Key” for your table:

# Header (recommended)
curl -H "Authorization: Bearer st_your_api_key" \
  https://sheetsjson.com/api/tables/my-account/products

# X-API-Key header
curl -H "X-API-Key: st_your_api_key" \
  https://sheetsjson.com/api/tables/my-account/products

# Query parameter (not recommended for production)
curl "https://sheetsjson.com/api/tables/my-account/products?api_key=st_your_api_key"

Public Access

If API key is not required, your table is publicly readable (writes always require authentication).

Table Settings

Custom API Slug

Instead of the auto-generated slug, set a memorable one:

/api/tables/my-account/my-custom-slug

Cache TTL

Configure how long responses are cached (default: 60 seconds). Lower values mean fresher data; higher values mean faster responses.

API Key Regeneration

If your API key is compromised, regenerate it in the table settings. The old key stops working immediately.

Performance Comparison

We benchmarked a table with 10,000 rows:

Operation Google Sheets JSON Tables Improvement
Read (p50) 2,100ms 48ms 44x faster
Read (p99) 4,800ms 185ms 26x faster
Write 1,200ms 92ms 13x faster
Filtered query 3,500ms 65ms 54x faster

Migrating from Google Sheets

Option 1: Fresh Start

  1. Create a new JSON Table
  2. Update your API endpoint URL (change /sheets/ to /tables/)
  3. Use the POST endpoint to populate data
  4. Done!

Option 2: Import from Sheet (Coming Soon)

We’re building a one-click import wizard that will:

  1. Read your existing Google Sheet
  2. Auto-detect column types
  3. Import all rows
  4. Generate an equivalent API endpoint

Best Practices

Schema Design

Unlike Google Sheets, JSON Tables don’t have column headers defined by a row. Define your columns in the table settings for:

  • Type validation
  • Documentation
  • Better error messages

Indexing for Filters

Filtering is fast thanks to PostgreSQL GIN indexes, but for best performance:

  • Use consistent field names (case-sensitive)
  • Avoid deeply nested objects in filters
  • Use exact matches when possible

Caching Strategy

Set cache TTL based on your data freshness needs:

  • Real-time data (stock prices): 0-10 seconds
  • Frequently updated (inventory): 30-60 seconds
  • Mostly static (product catalog): 300+ seconds

Pricing & Limits

JSON Tables are available on Pro plans and above:

Plan Tables Rows per Table Price
Free 0 $0/mo
Starter 0 $9.99/mo
Pro 3 100,000 $29/mo
Business 10 500,000 $99/mo
Enterprise Unlimited Custom Contact us

Error Codes

Code Meaning
400 Bad request (invalid JSON or parameters)
401 API key required or invalid
403 Write permission denied (upgrade needed) or row limit exceeded
404 Table or row not found
429 Rate limit exceeded
503 Table paused or in error state

FAQ

Can I use both Sheets and Tables?

Absolutely! Many customers use Sheets for content that non-technical team members edit, and Tables for high-traffic data that needs better performance.

What happens to my data?

Your data is stored in PostgreSQL with automatic backups. We never delete your data unless you explicitly request it.

Is there a way to edit data in a spreadsheet UI?

The Tables dashboard provides a basic data grid for viewing and editing rows. For bulk edits, you can export to CSV, edit in your favorite spreadsheet app, and re-import.

Can I migrate back to Google Sheets?

Yes! Export your table data as CSV anytime and import it into Google Sheets.

Next Steps

Questions? Contact our support team.

Was this page helpful? |