Guide: Sell a dataset
A dataset is a different unit of sale from an API call — it’s a file (CSV, Parquet, JSONL, ZIP) a buyer downloads once, not a parameterized live query. But it rides the exact same rails: under the hood a dataset is an API relay whose origin returns a download link instead of inline data. Same x402 payment, same on-chain splitter, same free sample — no new storage or settlement.
So the flow is: buyer pays once → the relay returns a (short-lived) download URL → buyer downloads the file directly.
The easy way — create_dataset (connector)
If you’ve connected in Claude, one tool lists a dataset:
create_dataset(
name, slug,
download_url, # a link to the file, OR an endpoint that returns a presigned URL on payment
price_usd, # price per download
networks, # CAIP-2 ids, e.g. ["eip155:8453"]
pay_to, # your payout wallet
sample_rows?, # a few example rows — shown as the FREE preview
columns_schema?, # OR a JSON Schema of one row
format?, # csv | tsv | parquet | jsonl | json | zip | gzip
license?, # e.g. "CC-BY-4.0"
description?,
public_listing?, # default true
join_card?, # STRONGLY ADVISED — which columns buyers can JOIN on (see below)
# — synthetic datasets only (see "Selling synthetic datasets" below) —
synthetic?, # true if the data is synthetic
synthetic_method?, # how it was generated, e.g. "CTGAN", "SDV", "DP-SGD"
synthetic_source?, # the real distribution/source it models
synthetic_fidelity?, # statistical-similarity note/metrics
synthetic_privacy? # privacy guarantee, e.g. "epsilon=1.0 DP"
)
Then publish_endpoint. That’s it. In chat:
“I have a CSV at
https://…/gdp.csv. Sell it for $2/download, payout to0x…. Columns are country, year, gdp — here are three sample rows: …”
Claude calls create_dataset with your sample_rows as the preview, then
publishes. The buyer sees the columns + your sample rows for free, pays $2, and
gets the download link.
The preview (this is what sells it)
A dataset’s sample shows the file, not the link — columns + a few rows. Your
sample_rows are a curated teaser shown as-is (or pass columns_schema and we
synthesize a fake preview row). Buyers and agents evaluate the shape before paying
— exactly the data-sample
feature, applied to files.
Declare your join handles (this is what makes it fusable)
Buyers rarely want your file alone — they merge it with data they already hold. A join card tells their agent which columns to join on, in your own words:
"join_card": {
"row_represents": "one country-year",
"join_keys": [
{"column": "country", "description": "ISO 3166-1 alpha-3 code"},
{"column": "year", "description": "calendar year, integer"}
]
}
Optional, ~1 minute, and it earns the ⧉ Fusion-ready badge plus join-handle
search visibility — search_marketplace(joinable_on=…) only surfaces carded
listings, so a card puts you inside agents’ fusion plans. Full details:
Join cards — including how to walk the buyer flow for your
own listing (find your fusion partners, verify a real match rate, and quote
it in your description).
Hosting & the download link
You host the file; we deliver it. One link is enough — any size up to 512 MB, public or private:
- A link to the file (the normal case). The relay streams the bytes to
the buyer — the file never buffers in relay memory, your origin URL stays
hidden, and buyers get a proper
Content-Dispositionfilename. Private file? Add an origin auth header (auth_type=bearer+auth_value) at create/update — the relay injects it server-side; the credential is encrypted at rest and never exposed. Oversized files (>512 MB) are refused with an explicit error — never silently truncated. - A tiny “issue link” endpoint returning a short-lived presigned URL —
an OPTIONAL optimization when you want the bytes to bypass our pipe (huge
files, your own CDN economics). Set
freshness_critical=trueon these listings: signed URLs expire, so the relay must never serve one from its last-good cache.
Buyers through the connector don’t pull the file into their agent’s context:
a paid call_endpoint returns the relay URL + a one-time pickup key
(Idempotency-Key) — fetching the URL with that key streams the file against
the receipt already paid, no second charge.
A minimal presigned-URL endpoint (S3/R2), ~15 lines:
# FastAPI example — returns a 10-minute presigned GET for your object
import boto3
from fastapi import FastAPI
app = FastAPI()
s3 = boto3.client("s3") # or Cloudflare R2 via its S3-compatible endpoint
@app.get("/dataset/gdp")
def issue_link():
url = s3.generate_presigned_url(
"get_object",
Params={"Bucket": "my-bucket", "Key": "gdp.csv"},
ExpiresIn=600,
)
return {"download_url": url, "expires_in": 600}
Point download_url at that endpoint. On payment the relay calls it and returns
the {download_url, …} to the buyer.
Manual / programmatic (REST or MCP create tools)
A dataset is just an API relay with delivery: "download". You can also create it
via create_api_relay / POST /dashboard/endpoints/api with:
method: "GET",origin_url: your link/issue-endpoint,delivery: "download",dataset_format,dataset_license,- and a declared sample:
example: {"output": [ …sample rows… ]}(withprotection: "real"to show your rows, orsyntheticto fabricate a preview).
See field details in Publishing and MCP tools.
Formats — Parquet first for analytics
dataset_format is a machine-readable hint so a buyer’s agent picks the right
loader. Known values: csv, tsv, parquet, jsonl, ndjson, json, arrow,
zip, gzip (an unrecognized value still works but is flagged at publish).
- Prefer Parquet for analytical/ML datasets — columnar, compressed, and loads straight into pandas/Polars/DuckDB. CSV is the universal fallback.
- Offer multiple representations of the same data as separate listings when it helps buyers: a small JSON inline API relay for single lookups and a Parquet/CSV download for the full set. Buyers pick what fits their pipeline.
- Time series sell best in a tidy
entity × period × valueshape (one row per entity-period), which maps cleanly onto Parquet/DuckDB — don’t bury the time axis inside nested objects.
Selling synthetic datasets
A synthetic dataset preserves a real source’s statistical shape without exposing real records — useful for ML training under data scarcity, pipeline testing, and sharing the shape of sensitive (health/financial) data. It’s more defensible than reselling public data, and rides the same download rails.
Provenance is mandatory. Set synthetic: true and declare how it was made, so
a buyer can trust it. Publish flags a synthetic dataset that’s missing
provenance (and blocks it if the deployment requires complete metadata):
create_dataset(
…, format="parquet", license="CC-BY-4.0",
synthetic=true,
synthetic_method="CTGAN", # required: the generation method
synthetic_source="internal claims DB", # required: the real source it models
synthetic_fidelity="KS<0.05 across columns", # recommended
synthetic_privacy="epsilon=1.0 differential privacy" # recommended
)
Listings carry dataset_synthetic: true + the dataset_provenance block prominently
so buyers always know they’re getting synthetic data and on what basis. (The platform
sells synthetic data and enforces its provenance — it does not generate it; you
produce it with your own tooling.)
Synthetic isn’t dataset-only. The same dataset_synthetic + dataset_provenance
fields apply to a live API relay too — e.g. a “generate a synthetic record per
call” endpoint. Set them on create_api_relay (not just create_dataset); the
provenance contract is enforced for any synthetic endpoint, download or live. Buyers
find all of it with search_marketplace(type="synthetic") (or ?type=synthetic
on /discover.json).
What the buyer experiences
A buyer (human or agent) calls it like any endpoint — e.g. via the connector
call_endpoint (full walkthrough: Buying a dataset)
— pays once, and gets the link:
{ "ok": true, "delivery": "download",
"download_url": "https://…signed…", "price_usd": "2.00",
"receipt": { "tx_hash": "0x…" } }
Listings tag datasets with delivery: "download" + dataset_format +
dataset_license (and dataset_synthetic + dataset_provenance for synthetic
data) so the marketplace presents them as files, not live APIs.
The DS-ready checklist (this is what ranks)
Listings that give a data scientist everything they need to say yes carry a
▣ DS-ready badge and rank first in search_marketplace and the
marketplace grid. The criteria (also returned as completeness.missing on
every listing, and as a quality_next hint when you create/update):
- Description — what the data is, coverage, cadence.
- Codebook — a
descriptionper column in the output schema (withenumvalues for categorical codes).class: pmeans nothing without “edible (e) or poisonous (p)”. - ≥3 sample rows — one row proves nothing about shape or variance.
- License — e.g.
"CC-BY-4.0". Datasets without one stall at procurement.
What buyers can’t find (sell against demand)
Zero-result searches and explicit asks land on the public
requested-data board — GET /seek/board (or the site’s /seek-data page).
Before inventing a listing, check what buyers are already asking for; asks
carry the format and the price they’d pay.
Pricing notes
- Price is per download (each paid call returns one link).
- A protocol fee applies on top, with a small flat floor — see Rate card. For a dataset you’ll typically price well above the floor, so the fee is ~10%.
- Versioning: re-publish or add a new slug for a new snapshot; buyers re-buy the new version. (First-class hosted/versioned datasets are a future enhancement.)