Insights Endpoints

Endpoints

An endpoint is your second product type. Where an asset returns an insight (a value, a table, or a chart), an endpoint serves raw rows of structured data — a queryable REST data feed exposed directly from your database.

This page is the management reference (seller side): creating, configuring, testing, and keying endpoints via the Management API. For the concept and lifecycle see Endpoints Overview; for the customer-facing fetch contract see Endpoint API Reference.

Doc note: this page replaces a previous speculative "insights" page that described endpoints (forecasting, streaming) that aren't part of the live API. If you're maintaining the docs, consider renaming this page's slug from insights-endpoints to something like endpoints-management — "insights" is misleading for the raw-data product. Update the cross-links in Assets and Use Cases & Examples if you do.

All routes below live on the Management API (https://api.spartera.com) under your company and use an analytics key (sk_spartera_...) in the x-api-key header.

https://api.spartera.com/companies/{company_id}/endpoints

Code blocks assume BASE_URL, COMPANY_ID, and a HEADERS dict with your x-api-key. See Python Examples for setup.


Asset or Endpoint?

You want to return...Create a...
A single value or insightCalculation Asset
A chart or graphVisualization Asset
Multiple rows of structured dataEndpoint

"What's the average air distance for an NFL quarterback?" → one number → asset. "Give me air distance per quarterback" → rows → endpoint.


The Endpoint Object

FieldRequiredDescription
nameHuman-readable name (shown in marketplace)
descriptionWhat rows the endpoint returns
connection_idWhich database connection to query
source_schema_nameSchema where the source table lives
source_table_nameTable being exposed
endpoint_schemaColumn-level config: which columns, aliases, aggregations, filters
access_methodOPEN, API_KEY, or IP (most use API_KEY)
max_records_per_requestRow cap per request (default 1,000)
rate_limit_number / rate_limit_period / rate_limit_granularityOptional per-buyer/IP rate limits
sell_in_marketplacetrue = public listing; false = direct B2B only
data_time_period_start / data_time_period_endWhen your data records begin/end
data_source_refresh_frequencyHow often the source data updates
top_questionsBuyer-facing questions the data answers (powers search relevance/SEO)

Pricing is not on the endpoint record — it's set separately via the price API (see Pricing & Publishing below).


List Endpoints

GET /companies/{company_id}/endpoints

Supports pagination, filtering, and sorting (same conventions as Assetspage, per_page, sort_field, sort_direction).

r = requests.get(f"{BASE_URL}/companies/{COMPANY_ID}/endpoints", headers=HEADERS)
for ep in r.json()["data"]:
    print(ep["endpoint_id"], ep["name"], ep["slug"])

Get an Endpoint

GET /companies/{company_id}/endpoints/{endpoint_id}

Discover Columns (Before You Configure)

Before building endpoint_schema, inspect what the source connection exposes.

GET /companies/{company_id}/connections/{connection_id}/describe

Query parameters:

ParamDefaultDescription
include_fieldstrueInclude column/field details
schemasComma-separated schemas to limit the scan
tablesComma-separated tables to limit the scan
r = requests.get(
    f"{BASE_URL}/companies/{COMPANY_ID}/connections/{CONNECTION_ID}/describe",
    headers=HEADERS,
    params={"schemas": "nfl", "tables": "passing_stats"}
)
print(r.json()["data"])

To populate a column's allowed filter values, scan it for distinct values:

POST /companies/{company_id}/endpoints/{endpoint_id}/scan_column
r = requests.post(
    f"{BASE_URL}/companies/{COMPANY_ID}/endpoints/{endpoint_id}/scan_column",
    headers=HEADERS,
    json={"column": "team", "limit": 100000}   # column required; limit default 100000
)
print(r.json()["data"]["values"])

Create an Endpoint

POST /companies/{company_id}/endpoints
payload = {
    "company_id": COMPANY_ID,
    "user_id": USER_ID,
    "name": "NFL Passing Yards by Team",
    "description": "Per-team passing yardage for the current NFL season.",
    "connection_id": CONNECTION_ID,
    "source_schema_name": "nfl",
    "source_table_name": "passing_stats",
    "access_method": "API_KEY",
    "max_records_per_request": 1000,
    "sell_in_marketplace": False,         # save as draft; publish later
    "data_source_refresh_frequency": "WEEKLY",
    "endpoint_schema": {                  # illustrative — see note below
        "columns": [
            {"name": "team",          "alias": "Team",          "visible": True},
            {"name": "passing_yards", "alias": "Passing Yards", "visible": True}
        ]
    }
}

r = requests.post(f"{BASE_URL}/companies/{COMPANY_ID}/endpoints",
                  headers=HEADERS, json=payload)
endpoint_id = r.json()["data"]["endpoint_id"]
print(f"Endpoint created: {endpoint_id}")

On endpoint_schema: the shape above is illustrative. The exact per-column keys (aliases, aggregations, filters, hidden flags, valid values) are easiest to obtain by starting from a /describe response, or by configuring columns in the dashboard's Schema Config table and reading the saved endpoint back with GET .../endpoints/{endpoint_id}. Build it there first if you're unsure of the precise structure.


Update an Endpoint

PATCH /companies/{company_id}/endpoints/{endpoint_id}

Send only the fields you want to change. Updates invalidate the marketplace cache so changes appear immediately on the product page.

requests.patch(f"{BASE_URL}/companies/{COMPANY_ID}/endpoints/{endpoint_id}",
               headers=HEADERS,
               json={"max_records_per_request": 5000,
                     "description": "Now includes 2026 season."})

Delete an Endpoint

DELETE /companies/{company_id}/endpoints/{endpoint_id}

Deleting removes the endpoint from the marketplace and invalidates its cache.


Test an Endpoint

Run the endpoint against real data with a small row count to confirm the shape buyers will receive. Free — no credits consumed.

GET /companies/{company_id}/endpoints/{endpoint_id}/test

An optional limit (default 10) controls how many sample rows come back.

r = requests.get(f"{BASE_URL}/companies/{COMPANY_ID}/endpoints/{endpoint_id}/test",
                 headers=HEADERS)
print(r.json()["data"])

Get the Public URL & Example Requests

Once configured, fetch the buyer-facing URL plus ready-made example requests (cURL, Python, JavaScript):

GET /companies/{company_id}/endpoints/{endpoint_id}/url
info = requests.get(f"{BASE_URL}/companies/{COMPANY_ID}/endpoints/{endpoint_id}/url",
                    headers=HEADERS).json()["data"]
print(info["endpoint_url"])          # e.g. https://acme.api.spartera.com/endpoints/v1/nfl-stats
print(info["example_requests"]["python"])

Endpoint Key Management

Endpoints are consumed with endpoint keys (ep_...), which are read-only and scoped to a single endpoint. Marketplace buyers get one auto-provisioned on first fetch; for direct B2B customers you mint them yourself here.

List Keys

GET /companies/{company_id}/endpoints/{endpoint_id}/keys

Returns the endpoint-type keys linked to this endpoint (masked values). Requires permission to view API keys.

Create a Key

POST /companies/{company_id}/endpoints/{endpoint_id}/keys

Requires a Data Engineer (role 3) key or above. The plain-text value is returned once, in data.plain_text_value — save it immediately.

r = requests.post(f"{BASE_URL}/companies/{COMPANY_ID}/endpoints/{endpoint_id}/keys",
                  headers=HEADERS,
                  json={"name": "Acme Corp Production",
                        "expiration_date_utc": "2026-12-31T23:59:59Z"})  # expiry optional
print(r.json()["data"]["plain_text_value"])   # ep_... — shown only now

Delete a Key

DELETE /companies/{company_id}/endpoints/{endpoint_id}/keys/{api_key_id}

→ Full key model, roles, and rotation: API Keys.


Pricing & Publishing

Pricing uses the same price API as assets:

POST /companies/{company_id}/endpoints/{endpoint_id}/prices
requests.post(f"{BASE_URL}/companies/{COMPANY_ID}/endpoints/{endpoint_id}/prices",
              headers=HEADERS, json={"price_usd": 2.00})

Publish by setting sell_in_marketplace (and the marketplace metadata) via PATCH:

requests.patch(f"{BASE_URL}/companies/{COMPANY_ID}/endpoints/{endpoint_id}",
               headers=HEADERS,
               json={"sell_in_marketplace": True,
                     "data_source_refresh_frequency": "WEEKLY"})

Publishing requires Stripe to be connected for your company (→ Quickstart Guide, Step 5). To unpublish, set sell_in_marketplace back to False.


Executing an Endpoint

There are two execution paths — don't confuse them:

RouteAuthWhoNotes
GET /companies/{company_id}/endpoints/{endpoint_id}/executeAnalytics key (sk_spartera_)You / same-companyInternal fetch with ?start=&limit=. No credits for company-owned use.
GET https://{handle}.api.spartera.com/endpoints/v1/{slug}Endpoint key (ep_)BuyersThe public, billable, customer-facing route.

For the public contract — response envelope, pagination, filtering, status codes — see Endpoint API Reference.

# Internal / same-company preview against live data
r = requests.get(f"{BASE_URL}/companies/{COMPANY_ID}/endpoints/{endpoint_id}/execute",
                 headers=HEADERS, params={"start": 0, "limit": 100})
print(r.json())

Usage Statistics

GET /companies/{company_id}/endpoints/{endpoint_id}/stats

Returns a usage summary (total_requests, unique_ips, avg_response_time_ms, rate_limit_hits, requests_by_day). Accepts a days query param (default 30).

Note: usage tracking is still being wired up — this route currently returns zeroed placeholder values until that lands.


Recommendations

GET /companies/{company_id}/endpoints/{endpoint_id}/recommendations

Public (no auth). Returns a mixed, endpoint-biased list of related endpoints and assets; any asset sharing the endpoint's connection_id surfaces as the associated analytic. Query params: limit (default 12, max 50), min_score (default 0.1, range 0.0–1.0).


HTTP Status Codes

CodeMeaning
200 OKSuccess
400 Bad RequestInvalid parameters (e.g. missing column on scan)
401 UnauthorizedMissing or invalid API key
403 ForbiddenInsufficient role/permissions (e.g. creating a key below role 3)
404 Not FoundEndpoint doesn't exist
429 Too Many RequestsRate limit exceeded

Related Pages