Skip to content

Start a Service API

A live API that sells an outcome: each Customer's annual report, drafted, checked, signed and filed, charged once when the Customer accepts it.

You need Node 20 and a GitHub account. The sample answers on filings.apis.dev; your first deploy answers at once on a free Host, and your own domain is one line.

  1. Start the folder

    Terminal
    $ npx apis.dev init service-api
    ✓ wrote definition.ts: a Service API
      next: npx apis.dev dev

    init writes a Service API with one case, its moves and the price of its outcome.

  2. Write the file

    definition.ts
    26 lines
    import { define, workflow, agentic } from 'apis.dev'
    
    /** Each Customer's annual report, drafted, signed and filed, charged once when the Customer accepts it. */
    export default define({
      name: 'filings', domain: 'filings.apis.dev',
      Filing: {                                     // Noun: the work your buyer watches
        company: 'string', year: 'number',
        status: {                                   // Verbs: one per move
          order: [],
          draft: { in: 'ordered', run: workflow(async ($, filing) => {
            const { form } = await $.generative('Draft the annual report for {company}', filing,
              { returns: { form: 'string' } })
            await $.human('Check the draft', { form }, { role: 'paralegal' })  // unseen: a step
            return { form }
          }) },
          sign: 'drafted',                          // seen: the Customer's turn
          file: { in: 'signed', run: agentic('File the signed report with the state') },
          accept: 'filed', reject: 'filed',         // the Customer accepts, or it is redone
        },
      },
      on: { 'Filing.ordered': 'Filing.draft', 'Filing.signed': 'Filing.file' },
      offer: {
        'Filing.order': { price: 25, when: 'accepted', accept: 'customer',
                          acceptWithin: '7d', remedy: 'redo' },
      },
    })

    A model drafts and a paralegal checks, inside one Workflow. The Customer signs, an agent files, and the Customer accepts or rejects what was filed.

  3. Try it locally

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

    Order a filing on localhost and walk it to accepted. In your Test twin the paralegal's task goes to you, and nothing is filed.

  4. Publish it

    Terminal
    $ npx apis.dev deploy
    ✓ signed in with GitHub
    ✓ definition.ts: filings on filings.apis.dev
    ✓ Stripe connected: each Customer pays into your own account
    ✓ 1 Noun, 9 Verbs, 2 Triggers, 1 price
        Filing   order, get, list, update, delete, restore, sign, accept, reject
        Filing.ordered → Filing.draft
        Filing.signed → Filing.file
        Filing.order    25 once, when accepted
    ✓ published v1 to https://filings.apis.dev: 11 Interfaces
        REST              /filings
        CLI               npx filings
        MCP               /mcp
        SDK               npm i filings, pip install filings
        Docs              /docs
        OpenAPI           /openapi.json
        llms.txt          /llms.txt
        agents.json       /.well-known/agents.json
        Pricing           /pricing
        Landing site      /
        Developer portal  /dashboard
    ✓ Test key: filings_test_xZ4w7ptrJjwZ2r8pvwKjvZzH5pqCGj040acc

    draft and file serve no path: Filing.ordered and Filing.signed start them, so they are internal. Your Customer makes the other moves.

  5. Read the price list

    /pricing
    8 lines
    {
      "currency": "USD",
      "rates": [
        { "name": "Filing.order",
          "price": 25, "unit": "outcome",
          "when": "accepted" }
      ]
    }

    Your Customers and their agents read one price, and when it is charged: on acceptance, never by the hour.

  6. Order one with no credits

    POST filings.apis.dev/filings
    Request
    curl https://filings.apis.dev/filings \
      -H "Authorization: Bearer $FILINGS_KEY" \
      -H "Prefer: code=402" \
      --json '{"company":"acme.com","year":2026}'
    Response
    HTTP/1.1 402 Payment Required
    Content-Type: application/problem+json
    X-Cost: price=0, currency="USD"
    X-Request-Id: req_3684ba7186b965f12f33
    
    {
      "type": "https://filings.apis.dev/docs/errors#payment_required",
      "title": "Payment Required",
      "status": 402,
      "detail": "The credit balance is 0; Filing.order holds 25 until accepted.",
      "code": "payment_required",
      "instance": "req_3684ba7186b965f12f33",
      "offers": [
        {
          "kind": "credits",
          "price": 50,
          "checkout": "https://filings.apis.dev/checkout/credits-50"
        },
        {
          "kind": "credits",
          "price": 200,
          "checkout": "https://filings.apis.dev/checkout/credits-200"
        }
      ]
    }

    An order holds its price from the credits until the Customer accepts. With none to hold, it answers 402 at price 0, with packs that cover it.

  7. Buy credits and order it

    POST filings.apis.dev/filings
    Request
    curl https://filings.apis.dev/filings \
      -H "Authorization: Bearer $FILINGS_KEY" \
      --json '{"company":"acme.com","year":2026}'
    Response
    HTTP/1.1 201 Created
    Location: /filings/filing_1
    X-Action-Id: act_1
    X-Cost: price=0, currency="USD"
    X-Request-Id: req_cbec164c216729631ad5
    
    {
      "id": "filing_1",
      "company": "acme.com",
      "year": 2026,
      "status": "ordered",
      "createdAt": "2026-10-24T09:00:00Z",
      "updatedAt": "2026-10-24T09:00:00Z"
    }

    After Checkout, the order answers 201 at price 0 and holds $25. Filing.ordered starts the draft.

  8. Watch the work, then sign

    Request
    curl https://filings.apis.dev/filings/filing_1 \
      -H "Authorization: Bearer $FILINGS_KEY"
    Response
    HTTP/1.1 200 OK
    X-Cost: price=0, currency="USD"
    X-Request-Id: req_f781a6ad9678c1e5146d
    
    {
      "id": "filing_1",
      "company": "acme.com",
      "year": 2026,
      "status": "drafting",
      "createdAt": "2026-10-24T09:00:00Z",
      "updatedAt": "2026-10-24T09:00:01Z"
    }

    Your Customer watches the filing move: drafting while the model and the paralegal work, then drafted, their turn. Signing starts the filing.

  9. Accept it

    POST filings.apis.dev/filings/filing_1/accept
    Request
    curl -X POST https://filings.apis.dev/filings/filing_1/accept \
      -H "Authorization: Bearer $FILINGS_KEY"
    Response
    HTTP/1.1 200 OK
    X-Action-Id: act_5
    X-Cost: price=25, currency="USD"
    X-Request-Id: req_0978142c439357dbbea3
    
    {
      "id": "filing_1",
      "company": "acme.com",
      "year": 2026,
      "status": "accepted",
      "createdAt": "2026-10-24T09:00:00Z",
      "updatedAt": "2026-10-26T08:15:00Z"
    }
    Delivery
    POST /hooks/filings HTTP/1.1
    Host: hooks.acme.com
    X-Webhook-Attempt: 1
    X-Webhook-Signature: t=1793002500,v1=b8aad23b578b9e3d90ceca7c000bf3e2d6ffe9bf7deaa592147920ed358a0845
    
    {
      "id": "evt_11",
      "type": "Filing.accepted",
      "at": "2026-10-26T08:15:00Z",
      "seq": 11,
      "data": { "id": "filing_1", "status": "accepted" },
      "charged": { "price": 25, "currency": "USD" }
    }

    Acceptance is the one move with a price: it charges the held $25 once, and Filing.accepted carries the charge to every Watch. A rejected filing is redone at no charge.

  10. Get paid

Stripe receipt · October 2026 · USD
Filing.order     1 × 25       25.00
───────────────────────────────────
Total                         25.00
Paid from 50.00 of credits    25.00
Balance                       25.00

The accepted filing is one line on your Customer's Stripe receipt, and the money lands in your own Stripe account.

Result

Your API answers on https://filings.apis.dev: a filing a model drafts, a paralegal checks and the Customer signs, charged $25 once the Customer accepts it.

A rejected filing is redone at no charge. You wrote no case tracker, no hold on the price and no acceptance window.

Next steps

  • Start a Content product → sell what you publish, by the read and by the month.
  • Service API: outcomes and acceptance, grades, review and supervision.
  • Work: the steps agents and people do, reviewed and signed off.