rstack-data
rstack-data
The resolved.sh schema endpoint (/data/{filename}/schema) is free for buyers to call.
It's their first look at your data before committing to a purchase. This skill makes that
first look compelling — and generates the commands to apply every improvement.
Environment variables:
RESOLVED_SH_API_KEY(required) — your resolved.sh API key (aa_live_...)RESOLVED_SH_RESOURCE_ID(required) — your resource UUIDRESOLVED_SH_SUBDOMAIN(required) — your subdomain slug
Preamble (run first)
# Keep this skill up to date:
# npx skills add https://github.com/resolved-sh/rstack --skill rstack-data -g -y
# Fetch current data files
curl -sf "https://resolved.sh/listing/$RESOLVED_SH_RESOURCE_ID/data" \
-H "Authorization: Bearer $RESOLVED_SH_API_KEY" \
-o /tmp/rstack_files.json
echo "Current data files:"
cat /tmp/rstack_files.json | python3 -c "
import sys, json
d = json.load(sys.stdin)
files = d.get('files', [])
if not files:
print(' (none)')
else:
for f in files:
print(f' {f[\"filename\"]} | \${f[\"price_usdc\"]} | desc: {len(f.get(\"description\") or \"\")} chars')
"
If no files exist, ask: "You have no data files yet. Do you have datasets to sell? (A) Yes — let's upload your first one, (B) No — nothing to optimize here"
If B: respond "Nothing to do here yet. Come back when you have data files to upload." and end with DONE.
If A: jump to Upload a new file below.
For each file, also fetch its schema:
for FILENAME in $(cat /tmp/rstack_files.json | python3 -c "
import sys, json
d = json.load(sys.stdin)
for f in d.get('files', []): print(f['filename'])
"); do
echo "=== schema: $FILENAME ==="
curl -sf "https://$RESOLVED_SH_SUBDOMAIN.resolved.sh/data/$FILENAME/schema"
echo
done
Parse queryability (queryable: true/false) and existing column names for each file.
Phase 1 — Understand the data (per file with thin or missing description)
For each file where description is missing or fewer than 60 characters, ask these questions. One file at a time, one question at a time.
Q1: "Describe {filename} in plain English: what domain is it in, what does each row represent, and approximately how many rows are there?"
Q2: "What are the most important column names and what do they mean? List the 3–5 most valuable ones."
Q3: "Who is the ideal buyer? What would they do with this data? Give me a concrete use case."
Q4: "Where did this data come from — and how fresh is it? (source, collection method, update frequency)"
Phase 2 — Evaluate each file
For each file, assess:
Description quality:
- Does it mention the domain? (e.g., "DeFi", "e-commerce", "weather")
- Does it describe what a row represents?
- Does it name the key columns?
- Does it give ≥2 concrete use cases?
- Is it ≥80 chars?
Queryability:
- Is
queryable: truein the schema response? - If not: is the file a CSV or JSONL? (These should be queryable — if they're not, the file may need to be re-uploaded with proper formatting. Note this as a concern.)
- If yes: are the column names descriptive? (e.g.,
wallet_addressgood;col1bad)
Pricing fit:
- < $0.01: invalid (minimum is $0.01 via x402)
- $0.01–$0.49: x402 only — Stripe won't process. Good for high-frequency agent queries where volume matters.
- $0.50–$5.00: sweet spot — works for both x402 and Stripe. Good for AI researchers and developer buyers.
- $5.01–$25.00: human/enterprise range. Stripe path required. Needs a very strong description and provenance story to justify.
-
$25.00: premium pricing. Only works with unique, hard-to-replicate data. Flag if description doesn't justify it.
Split pricing (queryable files only):
- Does the file have both query and download access paths?
- If
query_price_usdcis not set, per-row queries cost the same as a full download (price_usdc) — which is almost always wrong for queryable files. - Flag files where
price_usdc≥ $0.50 butquery_price_usdcis not set: buyers doing per-row queries are being charged full-download prices. - Recommended pattern: low
query_price_usdc($0.01–$0.10) to drive agent query volume + higherdownload_price_usdcorprice_usdc($1–$10) for human buyers who want the full file.
Phase 3 — Generate improved descriptions
For each file needing improvement, write a description using this template:
"{Domain} dataset: {row count if known, otherwise "dataset"} of {what each row represents}. Key columns: {3–5 column names with brief descriptions}. Use cases: {2–3 specific, concrete use cases — name the exact task}. Source: {provenance}. Updated: {frequency}."
Example of a weak description:
"Transaction data with wallet info"
Example of a strong description:
"DeFi swap dataset: ~180K Uniswap v3 swap events on Base mainnet. Key columns: timestamp (unix ms), pool_address, token_in_symbol, token_out_symbol, amount_usd, wallet_address. Use cases: MEV pattern detection, wallet behavior clustering, liquidity pool performance analysis. Source: on-chain event logs via Alchemy. Updated: daily."
The description should make a buyer want to call the schema endpoint even before deciding to purchase.
Phase 4 — Generate sample queries for page showcase
For each queryable file, generate a sample query that demonstrates the data's value. The query should show a realistic buyer use case.
# Free: inspect the schema before paying
GET https://{subdomain}.resolved.sh/data/{filename}/schema
# Paid query via x402 ($0.01/query) — {description of what this returns}
GET https://{subdomain}.resolved.sh/data/{filename}/query?{filter_col}={example_val}&_select={col1},{col2},{col3}&_limit=10
# Supported filter operators:
# col=value exact match
# col__gt=n greater than
# col__lt=n less than
# col__gte=n greater than or equal
# col__lte=n less than or equal
# col__in=a,b,c set membership
# col__contains=val substring match
Use real column names from the schema. Make the example query answer a specific business question (e.g., ?wallet_address=0xabc&amount_usd__gt=1000 to find a wallet's large swaps).
Phase 5 — Generate update commands
PATCH command for each file (update description and/or split pricing):
# Replace {file_id} with the id from GET /listing/{resource_id}/data
curl -X PATCH "https://resolved.sh/listing/$RESOLVED_SH_RESOURCE_ID/data/{file_id}" \
-H "Authorization: Bearer $RESOLVED_SH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"description": "{improved description}",
"query_price_usdc": {per-row query price, e.g. 0.01 — omit to leave unchanged},
"download_price_usdc": {full file download price — omit to leave unchanged}
}'
Split pricing notes:
- Omit
query_price_usdcordownload_price_usdcentirely to leave those values unchanged. - Send
0for either field to clear the override and fall back toprice_usdcfor that access type. - If you only want to update the description, send only
{"description": "..."}.
Generate one command per file that needs updating. Show them all together so the operator can run them in sequence.
PUT command to add/update a Data section in md_content:
Fetch the current md_content first, then append or update a ## Data section:
# Check current md_content
curl -sf "https://$RESOLVED_SH_SUBDOMAIN.resolved.sh?format=json" | \
python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('md_content') or '(none)')"
Generate a ## Data section to add:
## Data
| Dataset | Description | Price |
|---------|-------------|-------|
| [{filename}](https://{subdomain}.resolved.sh/data/{filename}/schema) | {first 80 chars of description} | ${price}/query |
Free schema inspection: `GET https://{subdomain}.resolved.sh/data/{filename}/schema`
Sample query:
\`\`\`
GET https://{subdomain}.resolved.sh/data/{filename}/query?{key_col}={example_val}&_select={col1},{col2}&_limit=5
\`\`\`
Buyers pay per query via x402 USDC on Base or Stripe. Schema inspection is always free.
Show the operator the full PUT command with the updated md_content.
Phase 6 — Pricing recommendations (if applicable)
If any file's pricing looks suboptimal based on Phase 2 assessment:
- File is priced at $0.01–$0.10 but isn't queryable (download-only): "Consider re-uploading as a structured CSV/JSONL to enable querying. Per-query pricing at low prices drives 10–100x more revenue than one-time downloads of the same file."
- File is priced above $5 but description doesn't justify it: "Your pricing is in the human/enterprise range but your description doesn't explain the data's unique value. Either lower the price or strengthen the description — buyers at this price point need a compelling reason."
- File is priced below $0.50 and relies on Stripe buyers: "Note: Stripe requires a minimum of $0.50. x402 handles sub-$0.50 pricing. If you want Stripe buyers (human researchers, developers), consider pricing at $0.50+."
- Queryable file with no split pricing and
price_usdc≥ $0.50: "Consider split pricing: setquery_price_usdcto $0.01–$0.10 for per-row agent queries and keep the higherprice_usdcas the download price. Without split pricing, every query costs the full download price — most agents won't pay that."
Upload a new file
Use this when the operator has a file to upload for the first time, or needs to re-upload an existing file (e.g. to fix queryability).
Ask:
- "What is the local path to the file?" (e.g.
/tmp/agent-systems.csv) - "What price should a full download cost? (e.g.
0.50)" - "What price per query? Leave blank to use the download price for all access."
- "Describe the dataset in one sentence — this becomes the listing description."
Then generate the upload command:
# Upload / re-upload a data file
curl -X PUT "https://resolved.sh/listing/$RESOLVED_SH_RESOURCE_ID/data/{filename}" \
-H "Authorization: Bearer $RESOLVED_SH_API_KEY" \
-H "Content-Type: {content-type}" \
--data-binary @{local-path} \
-G \
--data-urlencode "price_usdc={download_price}" \
--data-urlencode "query_price_usdc={query_price}" \
--data-urlencode "download_price_usdc={download_price}" \
--data-urlencode "description={description}"
Content-type guide:
.csv→text/csv.jsonlor.ndjson→application/jsonl.json→application/json
Important: application/x-ndjson is NOT accepted — the server will return 415. You must use application/jsonl for JSONL files or they will be rejected.
Re-uploading to fix queryability: If the schema endpoint returns queryable: false for a CSV or JSONL file, the file needs to be re-uploaded. First delete the old file:
# Get the file_id from the listing
curl -sf "https://resolved.sh/listing/$RESOLVED_SH_RESOURCE_ID/data" \
-H "Authorization: Bearer $RESOLVED_SH_API_KEY" | \
python3 -c "import sys,json; [print(f['id'], f['filename']) for f in json.load(sys.stdin).get('files',[])]"
# Delete the old file
curl -X DELETE "https://resolved.sh/listing/$RESOLVED_SH_RESOURCE_ID/data/{file_id}" \
-H "Authorization: Bearer $RESOLVED_SH_API_KEY"
Then re-run the upload command above. Ensure the file is valid UTF-8 CSV with a header row, or valid JSONL (one JSON object per line).
After a successful upload, verify queryability:
curl -sf "https://$RESOLVED_SH_SUBDOMAIN.resolved.sh/data/{filename}/schema" | \
python3 -c "import sys,json; d=json.load(sys.stdin); print('queryable:', d['queryable'], '| rows:', d.get('row_count'), '| cols:', [c['name'] for c in d.get('columns',[])])"
After upload, continue to Phase 1 to optimize the description.
Completion Status
DONE — All files have strong descriptions and update commands are generated. "Run the PATCH commands above, then /rstack-audit to re-score your Data Marketplace grade."
DONE_WITH_CONCERNS — If any files are not queryable (CSV/JSONL but queryable: false): "⚠ {filename} is not queryable. This likely means the file wasn't parsed as structured data. To enable querying, delete and re-upload the file. Queryable files earn significantly more because buyers can pay $0.01/query vs. $X for a one-time download."
BLOCKED — If API key is missing or the data endpoint returns an auth error.