{
  "auth": {
    "header": "x-agent-key",
    "note": "Request a key from the operator. Calls without a valid key receive 401.",
    "type": "api_key"
  },
  "capabilities": [
    {
      "description": "Place a catering package order with a DayMarket business kitchen for a future date and time. The order enters the standard DayMarket flow: scheduled, then the business confirms and sets the total, then marks it delivered. DayMarket is the merchant of record; the buyer is invoiced. A 15% fulfillment fee is deducted automatically before the business is paid.",
      "endpoint": {
        "method": "POST",
        "path": "/api/agent/order"
      },
      "errors": [
        {
          "code": 400,
          "meaning": "Invalid input: missing field, bad datetime, unknown business or package."
        },
        {
          "code": 401,
          "meaning": "Missing or invalid x-agent-key."
        },
        {
          "code": 404,
          "meaning": "Buyer email has no DayMarket account, or business/package not found or inactive."
        },
        {
          "code": 405,
          "meaning": "Method not allowed. Use POST."
        },
        {
          "code": 503,
          "meaning": "Station not yet provisioned on this deploy."
        }
      ],
      "fees": {
        "fulfillment_fee_bps": 1500,
        "note": "15% fulfillment fee deducted automatically from the order total before the business is paid. The business net lands in its DayMarket balance on delivery."
      },
      "flow": [
        "scheduled",
        "confirmed",
        "delivered"
      ],
      "idempotency": "Pass idempotency_key to make retries safe.",
      "input_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "business": {
            "description": "Business slug (e.g. elliannas-donut-shop) or business UUID. Must be an active DayMarket business.",
            "type": "string"
          },
          "buyer_email": {
            "description": "Email of the buyer. Must match an existing DayMarket member account; the order is placed under that buyer.",
            "format": "email",
            "type": "string"
          },
          "contact": {
            "description": "Human contact for fulfillment day-of. Name required; email or phone strongly recommended.",
            "properties": {
              "email": {
                "format": "email",
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "phone": {
                "type": "string"
              }
            },
            "required": [
              "name"
            ],
            "type": "object"
          },
          "delivery_address": {
            "type": "string"
          },
          "headcount": {
            "description": "Expected attendance. Optional but recommended.",
            "minimum": 1,
            "type": "integer"
          },
          "idempotency_key": {
            "description": "Optional caller-supplied key. Retrying with the same key and identical inputs returns the original order instead of creating a duplicate.",
            "type": "string"
          },
          "notes": {
            "type": "string"
          },
          "package": {
            "description": "Package UUID or exact package name (e.g. Meeting Box). Must be active.",
            "type": "string"
          },
          "scheduled_for": {
            "description": "ISO 8601 datetime the order is needed, e.g. 2026-10-20T09:00:00-05:00. Must be in the future.",
            "format": "date-time",
            "type": "string"
          }
        },
        "required": [
          "business",
          "package",
          "scheduled_for",
          "buyer_email",
          "contact"
        ],
        "type": "object"
      },
      "name": "order_catering",
      "output_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "duplicate": {
            "description": "True when the idempotency key matched an earlier order.",
            "type": "boolean"
          },
          "next": {
            "description": "What happens after this response.",
            "type": "string"
          },
          "ok": {
            "type": "boolean"
          },
          "order": {
            "properties": {
              "business": {
                "type": "string"
              },
              "headcount": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "id": {
                "format": "uuid",
                "type": "string"
              },
              "package": {
                "type": "string"
              },
              "payment_status": {
                "enum": [
                  "unpaid",
                  "paid",
                  "refunded"
                ],
                "type": "string"
              },
              "scheduled_for": {
                "format": "date-time",
                "type": "string"
              },
              "status": {
                "enum": [
                  "scheduled",
                  "confirmed",
                  "delivered",
                  "canceled"
                ],
                "type": "string"
              },
              "total_cents": {
                "description": "Null until the business confirms and sets the total.",
                "type": [
                  "integer",
                  "null"
                ]
              }
            },
            "type": "object"
          },
          "verification": {
            "properties": {
              "id": {
                "format": "uuid",
                "type": "string"
              },
              "inputs_hash": {
                "description": "SHA-256 of the canonical request inputs.",
                "type": "string"
              },
              "recorded_at": {
                "format": "date-time",
                "type": "string"
              }
            },
            "type": "object"
          }
        },
        "required": [
          "ok",
          "order",
          "verification"
        ],
        "type": "object"
      },
      "status": "live",
      "version": "1"
    },
    {
      "name": "answer_call",
      "description": "Answer an incoming voice call when the business cannot pick up. v1 plays a greeting and hands the caller to SMS completion; a realtime voice platform can replace the stub (Phase 3). Every answered call is logged as a verification event.",
      "endpoint": {
        "method": "POST",
        "path": "/api/station/voice"
      },
      "input_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "type": "object",
        "description": "Twilio voice webhook payload (form-encoded). Signature verified with TWILIO_AUTH_TOKEN."
      },
      "errors": [
        {
          "code": 401,
          "meaning": "Twilio signature verification failed."
        },
        {
          "code": 503,
          "meaning": "Station not yet provisioned: TWILIO_AUTH_TOKEN missing."
        }
      ],
      "flow": [
        "call_answered",
        "sms_handoff",
        "caller_replies_by_text"
      ],
      "note": "v1 is a stub: greeting + SMS handoff. Set VOICE_AGENT_URL to route live calls to a realtime voice platform."
    },
    {
      "name": "complete_text_order",
      "description": "Complete an order over SMS. The agent classifies intent, answers routine questions from the business structured data only (grounding rule), captures orders as structured data, validates deterministically, and either auto-approves, queues for human review, or asks a clarifying question. Truthful confirmations only.",
      "endpoint": {
        "method": "POST",
        "path": "/api/station/sms"
      },
      "input_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "type": "object",
        "description": "Twilio SMS webhook payload (form-encoded): From, To, Body, MessageSid. Signature verified with TWILIO_AUTH_TOKEN. Replies via TwiML."
      },
      "errors": [
        {
          "code": 400,
          "meaning": "Invalid input."
        },
        {
          "code": 401,
          "meaning": "Twilio signature verification failed."
        },
        {
          "code": 503,
          "meaning": "Station not yet provisioned."
        }
      ],
      "decisions": [
        "auto_approve",
        "human_review",
        "clarify",
        "answered",
        "escalate"
      ],
      "idempotency": "Twilio MessageSid is used as the idempotency key; redelivered webhooks return the original run.",
      "grounding": "The agent answers only from the business structured data (menu, hours, prices). Anything else becomes: I will have someone text you."
    }
  ],
  "description": "Readable Station prototype on DayMarket. AI agents discover catering capabilities here, invoke them with a single POST, and receive a machine-readable confirmation backed by the existing DayMarket order flow (scheduled, business confirms, delivered, automatic fulfillment fee, business cash-out). Built for agents; the agents build for the customer.",
  "legibility": {
    "business_profiles": "/businesses/{slug}/",
    "llms_txt": "/llms.txt",
    "packages": "/packages.html",
    "sitemap": "/sitemap.xml"
  },
  "operator": "DayMarket",
  "operator_url": "https://daymarket.tabronmerryhill.com",
  "station": "Readable Station",
  "station_version": "0.1.0",
  "verification": "Every agent order writes a verification record (timestamp, inputs hash, order id, status). These records are the audit trail for the station and the seed volume for Readable Evals.",
  "station_status": "live",
  "provisioned_at": "2026-10-11",
  "gates": {
    "gate1_order_catering": "live",
    "gate2_phone_sms": "live"
  }
}