Start a Dataset API
A live, priced API people and agents pay for in about 30 seconds, written as one file: a Source, a Mapping and a price.
Open in
You need Node 20 and a GitHub account. The first deploy answers at once on companyfacts.apis.dev; your own domain is one line.
Start the folder
Terminal $ npx apis.dev init dataset-api ✓ wrote definition.ts:a Dataset API next: npx apis.dev dev initwrites the file this track builds, so every step after it runs as printed.Write the file
definition.ts import { define, secret } from 'apis.dev' /** Any company by its domain,with its headcount and sector. */ export default define({ name: 'companyfacts', domain: 'companyfacts.apis.dev', sources: { // Source: the API you resell firms: { origin: 'https: //firms.example.com', key: secret('FIRMS_KEY') }, }, Company: { // Noun: the shape you promise domain: { type: 'url!#', from: 'firms', map: 'website' }, // Mapping employees: { type: 'number? ', from: 'firms', map: 'headcount' }, sector: { type: 'string? ', from: 'firms', map: 'industry' }, }, offer: { 'Company.get': 0.002, 'Company.search': 0.005 }, // Offer: the price }) firmsanswers{ website,; eachheadcount, industry } mappicks one, and!#makesdomainthe key. The comment above the file is its pitch on every Interface, andsecret('FIRMS_KEY')reads the credential you set withnpx apis.dev secrets set FIRMS_KEY.Try it locally
Terminal $ npx apis.dev dev ✓ firms answered in 212 ms; their field → your field:website → domain "acme.com" headcount → employees 240 industry → sector "Software" ✓ every Interface on http: //localhost: 8787, against your Test twin reloads on every save devasks the Source once and prints the record it maps, then serves every Interface on localhost against your Test twin.Publish it
Terminal $ npx apis.dev deploy ✓ signed in with GitHub ✓ definition.ts:companyfacts on companyfacts.apis.dev ✓ Stripe connected: each Customer pays into your own account ✓ 1 Noun, 2 Verbs, 1 Source, 2 prices Company get, search Company.get 0.002 a call Company.search 0.005 a call ✓ published v1 to https: //companyfacts.apis.dev: 11 Interfaces REST /companies/ {domain}, /companies? sector= CLI npx companyfacts MCP /mcp SDK npm i companyfacts, pip install companyfacts Docs /docs OpenAPI /openapi.json llms.txt /llms.txt agents.json /.well-known/ agents.json Pricing /pricing Landing site / Developer portal /dashboard ✓ Test key: companyfacts_test_NNTTj83hyuMNRNk85nzuQNW8h8y3wu33c155 The first run signs you in with GitHub and connects Stripe to your own account. Your product answers at once on
https:, with each Verb, each price and each Interface printed, and a Test key. Set//companyfacts.apis.dev domainto a domain of your own and deploy again to move every Interface there; deploy checks it once by a TXT record.Call it with the Test key
Request curl https://companyfacts.apis.dev/ companies/ acme.com \ -H "Authorization: Bearer $COMPANYFACTS_KEY" Response HTTP/1.1 200 OK X-Cost:price= 0.002, currency= "USD" X-Request-Id: req_3cd59a9a1ede10c5bf21 { "domain": "acme.com", "employees": 240, "sector": "Software" } Request curl https://companyfacts.apis.dev/ mcp \ -H "Authorization: Bearer $COMPANYFACTS_KEY" \ --json '{ "jsonrpc": "2.0", "id": 1, "method": "tools/ call", "params": { "name": "getCompany", "arguments": { "domain": "acme.com" } } }' Response HTTP/1.1 200 OK X-Cost:price= 0.002, currency= "USD" X-Request-Id: req_f9cf5fc65654d907192f { "jsonrpc": "2.0", "id": 1, "result": { "content": [ … ], "structuredContent": { "domain": "acme.com", "employees": 240, "sector": "Software" }, "_meta": { "cost": { "price": 0.002, "currency": "USD" }, "requestId": "req_f9cf5fc65654d907192f" } } } TypeScript import { Companyfacts } from 'companyfacts' const api = new Companyfacts({ key: process.env.COMPANYFACTS_KEY }) const { data, meta } = await api.getCompany('acme.com') // data:{ 'domain': 'acme.com', 'employees': 240, 'sector': 'Software' } // meta: { status: 200, cost: { 'price': 0.002, 'currency': 'USD' }, // requestId: 'req_9fd1df32ff7df11f695a' } Python import os from companyfacts import Companyfacts api = Companyfacts(key=os.environ["COMPANYFACTS_KEY"]) data, meta = api.get_company("acme.com") # data:{ "domain": "acme.com", "employees": 240, "sector": "Software" } # meta.cost: { "price": 0.002, "currency": "USD" } Terminal $ npx companyfacts login --key $COMPANYFACTS_KEY $ npx companyfacts companies get acme.com { "domain": "acme.com","employees": 240, "sector": "Software" } price 0.002 USD · req_3cd59a9a1ede10c5bf21 Call with the Test key the first run printed: its calls never bill. A Live Key answers the same, and bills.
Get paid
Stripe receipt · October 2026 · USD Company.get 100 free 0.00 Company.get 12,400 × 0.002 24.80 Company.search 1, 300 × 0.005 6.50 Company.watch 3 × 0.1 0.30 ──────────────────────────────────── Total 31.60 Paid from 50.00 of credits 31.60 Balance 18.40 Every Live call your Customers make lands on their Stripe receipt, a line per Verb, and the money lands in your own Stripe account. This is one Customer's month.
See every Interface
Every Interface, on https://companyfacts.apis.dev Every Interface, on https://companyfacts.apis.dev Interface Path REST /companies/,{domain} /companies?sector= CLI npx companyfactsMCP /mcpSDK npm i companyfacts,pip install companyfactsDocs /docsOpenAPI /openapi.jsonllms.txt /llms.txtagents.json /.well-known/agents.json Pricing /pricingLanding site /Developer portal /dashboardChange the price
definition.ts offer: { 'Company.get': 0.002, 'Company.search': 0.005 }, offer: { 'Company.get': 0.003, 'Company.search': 0.005 },Terminal $ npx apis.dev deploy ✓ definition.ts:1 Noun, 2 Verbs, 1 Source, 2 prices ✓ published v2 to https: //companyfacts.apis.dev: every Interface at once The price on three Interfaces The price on three Interfaces Interface At 0.002 At 0.003 priceinX-Costprice=0.002 price=0.003 /pricing"price":0.002 "price":0.003 /llms.txt($0.002)($0.003)Publish again, and all three move at once: the price in your docs is the price on the reply. A higher price is a breaking change: each Key keeps the Version it first called until it sends
Api-Version.Ask for one nobody has
GET companyfacts.apis.dev/companies/nobody.example.comRequest curl https://companyfacts.apis.dev/ companies/ nobody.example.com \ -H "Authorization: Bearer $COMPANYFACTS_KEY" Response HTTP/1.1 404 Not Found Content-Type:application/ problem+json X-Cost: price= 0, currency= "USD" X-Request-Id: req_84326ad21bc488454616 { "type": "https: //companyfacts.apis.dev/ docs/ errors#not_found", "title": "Not Found", "status": 404, "detail": "No Company has domain nobody.example.com.", "code": "not_found", "instance": "req_84326ad21bc488454616" } TypeScript import { Companyfacts } from 'companyfacts' const api = new Companyfacts({ key: process.env.COMPANYFACTS_KEY }) const { error, meta } = await api.getCompany('nobody.example.com') // error:{ status: 404, code: 'not_found' } // meta.cost: { price: 0, currency: 'USD' } Response HTTP/1.1 404 Not Found Content-Type:application/ problem+json X-Cost: price= 0, currency= "USD" X-Request-Id: req_84326ad21bc488454616 { "type": "https: //companyfacts.apis.dev/ docs/ errors#not_found", "title": "Not Found", "status": 404, "detail": "No Company has domain nobody.example.com.", "code": "not_found", "instance": "req_84326ad21bc488454616" } Python import os from companyfacts import Companyfacts api = Companyfacts(key=os.environ["COMPANYFACTS_KEY"]) error, meta = api.get_company("nobody.example.com") # error:{ "status": 404, "code": "not_found" } # meta.cost: { "price": 0, "currency": "USD" } Response HTTP/1.1 404 Not Found Content-Type:application/ problem+json X-Cost: price= 0, currency= "USD" X-Request-Id: req_84326ad21bc488454616 { "type": "https: //companyfacts.apis.dev/ docs/ errors#not_found", "title": "Not Found", "status": 404, "detail": "No Company has domain nobody.example.com.", "code": "not_found", "instance": "req_84326ad21bc488454616" } Terminal $ npx companyfacts login --key $COMPANYFACTS_KEY $ npx companyfacts companies get nobody.example.com error 404 not_found price 0 USD · req_84326ad21bc488454616Response HTTP/1.1 404 Not Found Content-Type:application/ problem+json X-Cost: price= 0, currency= "USD" X-Request-Id: req_84326ad21bc488454616 { "type": "https: //companyfacts.apis.dev/ docs/ errors#not_found", "title": "Not Found", "status": 404, "detail": "No Company has domain nobody.example.com.", "code": "not_found", "instance": "req_84326ad21bc488454616" } Request curl https://companyfacts.apis.dev/ mcp \ -H "Authorization: Bearer $COMPANYFACTS_KEY" \ --json '{ "jsonrpc": "2.0", "id": 1, "method": "tools/ call", "params": { "name": "getCompany", "arguments": { "domain": "acme.com" } } }' Response HTTP/1.1 200 OK X-Cost:price= 0, currency= "USD" X-Request-Id: req_f9cf5fc65654d907192f { "jsonrpc": "2.0", "id": 1, "result": { "isError": true, "content": [ … ], "structuredContent": { "status": 404, "code": "not_found" }, "_meta": { "cost": { "price": 0, "currency": "USD" }, "requestId": "req_f9cf5fc65654d907192f" } } } A miss answers a Problem with its code, and its price is 0.
Result
Build: you wrote 10 lines: a Source with its Mapping, a Noun and an Offer, and ran it on localhost first. Launch: one command published 11 Interfaces and 2 Verbs on companyfacts.apis.dev, with a Test key. Monetize: each call draws its posted price from prepaid credits bought through Stripe Checkout, and a miss is free. You wrote no Verb, no docs and no price page.
import { define, secret } from 'apis.dev'
/** Any company by its domain, with its headcount and sector. */
export default define({
name: 'companyfacts', domain: 'companyfacts.apis.dev',
sources: { // Source: the API you resell
firms: { origin: 'https: //firms.example.com', key: secret('FIRMS_KEY') },
},
Company: { // Noun: the shape you promise
domain: { type: 'url!#', from: 'firms', map: 'website' }, // Mapping
employees: { type: 'number? ', from: 'firms', map: 'headcount' },
sector: { type: 'string? ', from: 'firms', map: 'industry' },
},
offer: { 'Company.get': 0.002, 'Company.search': 0.005 }, // Offer: the price
})Next steps
- Start a Headless SaaS → Your Customers write each field. You pick the shape, its lifecycle and the plans.
- Dataset API: how a field is filled, kept or live.
- What every product gets: everything else the file gives you.