---
title: "Start a Content product"
url: /quickstart/content
---

# Start a Content product

> A live API that sells what you publish: free to list, paid by the read, or open whole to members by the month.

You need Node 20 and a GitHub account. The examples use `briefs.apis.dev`, which stands for your domain; your first deploy answers at once on a free Host, and your own domain is one line.

1. **Start the folder**

   ```sh title="Terminal"
   $ npx apis.dev init content
   ✓ wrote definition.ts: a Content product
     next: npx apis.dev dev
   ```

   `init` writes a [Content](/patterns/content.md) product with one kind of item, its review and its prices.

2. **Write the file**

   ```ts title="definition.ts"
   import { define } from 'apis.dev'

   /** A weekly brief on the software companies that changed headcount, for members and their agents. */
   export default define({
     name: 'briefs', domain: 'briefs.apis.dev',
     Issue: {                                      // Noun: an edition your editors write
       week: 'string!#', title: 'string', body: 'markdown',
       status: {                                   // Verbs: drafted, then published
         draft: [], publish: { in: 'drafted', role: 'editor' },
       },
     },
     offer: {                                      // Offer: free to list, paid by the read
       'Issue.list': 0, 'Issue.read': 0.25,
       Member: { month: 8, includes: { 'Issue.read': 'all' } },
     },
   })
   ```

   An Issue is drafted, then published by an editor. Anyone lists Issues for free, a read of one is priced, and a Member's plan opens every read.

3. **Try it locally**

   ```sh title="Terminal"
   $ npx apis.dev dev
   ✓ every Interface on http://localhost:8787, against your Test twin
     reloads on every save
   ```

   Draft, publish and read an Issue on localhost. Your [Test twin](/reference/platform.md#test-twin) keeps its own Issues, and its books never post.

4. **Publish it**

   ```sh title="Terminal"
   $ npx apis.dev deploy
   ✓ signed in with GitHub
   ✓ definition.ts: briefs on briefs.apis.dev
   ✓ Stripe connected: each Customer pays into your own account
   ✓ 1 Noun, 8 Verbs, 1 plan, 2 prices
       Issue    draft, get, list, update, delete, restore, read, publish
       Member          8 a month, every Issue.read included
       Issue.list      0 a call
       Issue.read      0.25 a read
   ✓ published v1 to https://briefs.apis.dev: 11 Interfaces
       REST              /issues
       CLI               npx briefs
       MCP               /mcp
       SDK               npm i briefs, pip install briefs
       Docs              /docs
       OpenAPI           /openapi.json
       llms.txt          /llms.txt
       agents.json       /.well-known/agents.json
       Pricing           /pricing
       Landing site      /
       Developer portal  /dashboard
   ✓ Test key: briefs_test_ZL8WX5MtmpaL96W5LKkpbLBBV5JEjpb6ed40
   ```

   Deploy prints `read` beside the moves: one whole Issue, sold by access. Anyone can list the Issues on your site and through the API, at no charge.

5. **Read the price list**

   ```json title="/pricing"
   {
     "currency": "USD",
     "rates": [
       { "name": "Member",
         "price": 8, "unit": "month",
         "includes": { "Issue.read": "all" } },
       { "name": "Issue.list",
         "price": 0, "unit": "call" },
       { "name": "Issue.read",
         "price": 0.25, "unit": "call" }
     ]
   }
   ```

   Your readers and their agents see both ways to pay before they read: a price a read, or a plan a month.

6. **Publish an Issue**

   **draft**

   ```sh title="Request"
   curl https://briefs.apis.dev/issues \
     -H "Authorization: Bearer $BRIEFS_KEY" \
     --json '{
       "week": "2026-W44",
       "title": "Who hired this week",
       "body": "Acme grew from 180 to 240 people; Globex cut 30."
     }'
   ```

   ```http title="Response"
   HTTP/1.1 201 Created
   Location: /issues/2026-W44
   X-Action-Id: act_1
   X-Cost: price=0, currency="USD"
   X-Request-Id: req_61936998da1fa61dab74

   {
     "id": "issue_44",
     "week": "2026-W44",
     "title": "Who hired this week",
     "body": "Acme grew from 180 to 240 people; Globex cut 30.",
     "status": "drafted",
     "createdAt": "2026-10-26T06:00:00Z",
     "updatedAt": "2026-10-26T06:00:00Z"
   }
   ```

   **publish**

   ```sh title="Request"
   curl -X POST https://briefs.apis.dev/issues/2026-W44/publish \
     -H "Authorization: Bearer $BRIEFS_KEY"
   ```

   ```http title="Response"
   HTTP/1.1 200 OK
   X-Action-Id: act_2
   X-Cost: price=0, currency="USD"
   X-Request-Id: req_73ca46e71f66378cb0fd

   {
     "id": "issue_44",
     "week": "2026-W44",
     "title": "Who hired this week",
     "body": "Acme grew from 180 to 240 people; Globex cut 30.",
     "status": "published",
     "createdAt": "2026-10-26T06:00:00Z",
     "updatedAt": "2026-10-26T08:30:00Z"
   }
   ```

   An editor drafts the week's Issue and publishes it with their own [Key](/reference/platform.md#key). Only a member who holds the `editor` Role can publish.

7. **Read it with no credits**

   **curl**

   ```sh title="Request"
   curl https://briefs.apis.dev/issues/2026-W44 \
     -H "Authorization: Bearer $BRIEFS_KEY" \
     -H "Prefer: code=402"
   ```

   **TypeScript**

   ```ts title="TypeScript"
   import { Briefs } from 'briefs'

   const api = new Briefs({ key: process.env.BRIEFS_KEY })
   const { error, meta } = await api.readIssue('2026-W44')
   // error: { status: 402, code: 'payment_required' }
   // meta.cost: { price: 0, currency: 'USD' }
   ```

   **Python**

   ```python title="Python"
   import os
   from briefs import Briefs

   api = Briefs(key=os.environ["BRIEFS_KEY"])
   error, meta = api.read_issue("2026-W44")
   # error: { "status": 402, "code": "payment_required" }
   # meta.cost: { "price": 0, "currency": "USD" }
   ```

   **CLI**

   ```sh title="Terminal"
   $ npx briefs login --key $BRIEFS_KEY
   $ npx briefs issues read 2026-W44
   error 402 payment_required
   price 0 USD · req_ed7c2b0dac55cde2bd81
   ```

   **MCP**

   ```sh title="Request"
   curl https://briefs.apis.dev/mcp \
     -H "Authorization: Bearer $BRIEFS_KEY" \
     -H "Prefer: code=402" \
     --json '{
     "jsonrpc": "2.0", "id": 1, "method": "tools/call",
     "params": { "name": "readIssue", "arguments": { "id": "2026-W44" } }
   }'
   ```

   ```http title="Response"
   HTTP/1.1 200 OK
   X-Cost: price=0, currency="USD"
   X-Request-Id: req_490740fc55115341f8ba

   {
     "jsonrpc": "2.0",
     "id": 1,
     "result": {
       "isError": true,
       "content": [
         {
           "type": "text",
           "text": "{\"status\":402,\"code\":\"payment_required\"}"
         }
       ],
       "structuredContent": { "status": 402, "code": "payment_required" },
       "_meta": {
         "cost": { "price": 0, "currency": "USD" },
         "requestId": "req_490740fc55115341f8ba"
       }
     }
   }
   ```


   ```http title="Response"
   HTTP/1.1 402 Payment Required
   Content-Type: application/problem+json
   X-Cost: price=0, currency="USD"
   X-Request-Id: req_ed7c2b0dac55cde2bd81

   {
     "type": "https://briefs.apis.dev/docs/errors#payment_required",
     "title": "Payment Required",
     "status": 402,
     "detail": "The credit balance is 0; Issue.read draws 0.25 from it.",
     "code": "payment_required",
     "instance": "req_ed7c2b0dac55cde2bd81",
     "offers": [
       {
         "kind": "credits",
         "price": 10,
         "checkout": "https://briefs.apis.dev/checkout/credits-10"
       },
       {
         "kind": "plan",
         "name": "Member",
         "price": 8,
         "checkout": "https://briefs.apis.dev/checkout/member"
       }
     ]
   }
   ```

   A reader with no credits meets 402 at price 0, with two offers: a credit pack, or Member at $8 a month. Each opens Stripe Checkout.

8. **Buy credits and read it**

   **curl**

   ```sh title="Request"
   curl https://briefs.apis.dev/issues/2026-W44 \
     -H "Authorization: Bearer $BRIEFS_KEY"
   ```

   **TypeScript**

   ```ts title="TypeScript"
   import { Briefs } from 'briefs'

   const api = new Briefs({ key: process.env.BRIEFS_KEY })
   const { data, meta } = await api.readIssue('2026-W44')
   // data: {
   //   'id': 'issue_44',
   //   'week': '2026-W44',
   //   'title': 'Who hired this week',
   //   'body': 'Acme grew from 180 to 240 people; Globex cut 30.',
   //   'status': 'published',
   //   'createdAt': '2026-10-26T06:00:00Z',
   //   'updatedAt': '2026-10-26T08:30:00Z'
   // }
   // meta.cost: { price: 0.25, currency: 'USD' }
   ```

   **Python**

   ```python title="Python"
   import os
   from briefs import Briefs

   api = Briefs(key=os.environ["BRIEFS_KEY"])
   data, meta = api.read_issue("2026-W44")
   # data: {
   #   "id": "issue_44",
   #   "week": "2026-W44",
   #   "title": "Who hired this week",
   #   "body": "Acme grew from 180 to 240 people; Globex cut 30.",
   #   "status": "published",
   #   "createdAt": "2026-10-26T06:00:00Z",
   #   "updatedAt": "2026-10-26T08:30:00Z"
   # }
   # meta.cost: { "price": 0.25, "currency": "USD" }
   ```

   **CLI**

   ```sh title="Terminal"
   $ npx briefs login --key $BRIEFS_KEY
   $ npx briefs issues read 2026-W44
   {
     "id": "issue_44",
     "week": "2026-W44",
     "title": "Who hired this week",
     "body": "Acme grew from 180 to 240 people; Globex cut 30.",
     "status": "published",
     "createdAt": "2026-10-26T06:00:00Z",
     "updatedAt": "2026-10-26T08:30:00Z"
   }
   price 0.25 USD · req_83c741a2f5aedafa4b1f
   ```

   **MCP**

   ```sh title="Request"
   curl https://briefs.apis.dev/mcp \
     -H "Authorization: Bearer $BRIEFS_KEY" \
     --json '{
     "jsonrpc": "2.0", "id": 1, "method": "tools/call",
     "params": { "name": "readIssue", "arguments": { "id": "2026-W44" } }
   }'
   ```

   ```http title="Response"
   HTTP/1.1 200 OK
   X-Cost: price=0.25, currency="USD"
   X-Request-Id: req_ce861093369d9ba88d97

   {
     "jsonrpc": "2.0",
     "id": 1,
     "result": {
       "content": [
         {
           "type": "text",
           "text": "{\"id\":\"issue_44\",\"week\":\"2026-W44\",\"title\":\"Who hired this week\",\"body\":\"Acme grew from 180 to 240 people; Globex cut 30.\",\"status\":\"published\",\"createdAt\":\"2026-10-26T06:00:00Z\",\"updatedAt\":\"2026-10-26T08:30:00Z\"}"
         }
       ],
       "structuredContent": {
         "id": "issue_44",
         "week": "2026-W44",
         "title": "Who hired this week",
         "body": "Acme grew from 180 to 240 people; Globex cut 30.",
         "status": "published",
         "createdAt": "2026-10-26T06:00:00Z",
         "updatedAt": "2026-10-26T08:30:00Z"
       },
       "_meta": {
         "cost": { "price": 0.25, "currency": "USD" },
         "requestId": "req_ce861093369d9ba88d97"
       }
     }
   }
   ```


   ```http title="Response"
   HTTP/1.1 200 OK
   X-Cost: price=0.25, currency="USD"
   X-Request-Id: req_83c741a2f5aedafa4b1f

   {
     "id": "issue_44",
     "week": "2026-W44",
     "title": "Who hired this week",
     "body": "Acme grew from 180 to 240 people; Globex cut 30.",
     "status": "published",
     "createdAt": "2026-10-26T06:00:00Z",
     "updatedAt": "2026-10-26T08:30:00Z"
   }
   ```

   The same read answers the whole Issue and draws $0.25. A Member reads it, and every other Issue, at 0.

9. **Get paid**

   ```text title="Stripe receipt · October 2026 · USD"
   Issue.read    14 × 0.25        3.50
   ───────────────────────────────────
   Total                          3.50
   Paid from 10.00 of credits     3.50
   Balance                        6.50
   ```

   This is one reader's month, paid from a pack of credits. A Member's receipt is one line a month, and each lands in your own Stripe account.

## Result
Your API answers on https://briefs.apis.dev: Issues your editors draft and publish, at $0.25 a read for a person or an agent.

The list of Issues is free, and a Member opens every Issue whole at $8 a month. You wrote no paywall, no subscription code and no metering.

## Next steps
- **[Start a Marketplace](/quickstart/marketplace.md) →** sell what many suppliers do, under your brand, and keep a share of each sale.
- [Content](/patterns/content.md): editions, access tiers, one-off products, communities and licence terms.
- [Commerce](/commerce.md): subscriptions, per-read prices, credits and refunds on Stripe.