{
    "openapi": "3.1.0",
    "info": {
        "title": "CoCap",
        "version": "0.0.1",
        "summary": "Collaborative event-memory platform \u2014 public web surface and agent discovery documents.",
        "description": "CoCap lets a host create a private cinematic film for an occasion and invite guests by QR code or link. This document describes CoCap's publicly addressable surface plus its agent discovery artifacts.\n\nIMPORTANT FOR AGENTS: CoCap's pages are static; `POST /api/events` is the one operation backed by compute (a Firebase Cloud Function). Paths marked `x-availability: planned` DO NOT EXIST yet and will not respond as documented. Only paths marked `live` are callable today.",
        "contact": {
            "name": "CoCap",
            "url": "https://cocap.cam"
        },
        "license": {
            "name": "MIT",
            "identifier": "MIT"
        },
        "x-mpp": {
            "version": "0.1",
            "availability": "planned",
            "description": "Machine Payable Protocol discovery metadata. Declares the price shape for CoCap's paid tier so agents can plan. NO PAYMENT RAIL IS LIVE \u2014 no endpoint accepts or settles a payment, and `POST /api/events` is live and free to call. See specs/agent-readiness/006-mpp.md.",
            "currency": "USD",
            "settlement": "none",
            "pricePoints": [
                {
                    "id": "starter",
                    "name": "Starter",
                    "amount": "0.00",
                    "currency": "USD",
                    "unit": "per-event",
                    "includes": [
                        "Up to 25 guests",
                        "Standard resolution",
                        "7-day storage",
                        "Basic QR invite"
                    ]
                },
                {
                    "id": "premium",
                    "name": "Premium",
                    "amount": "49.00",
                    "currency": "USD",
                    "unit": "per-event",
                    "includes": [
                        "Unlimited guests",
                        "4K high-res downloads",
                        "Lifetime storage",
                        "Custom QR branding",
                        "Live slideshow mode"
                    ]
                }
            ],
            "payableOperations": ["createEventProgrammatically"],
            "reference": "https://mpp.dev"
        },
        "x-x402": {
            "version": "1",
            "availability": "planned",
            "description": "x402 discovery metadata. Declares intent to charge for programmatic API access. NOT IMPLEMENTED \u2014 no endpoint returns HTTP 402, and `POST /api/events` is live and free. Settlement network and asset are undecided. See specs/agent-readiness/005-x402.md.",
            "scheme": "exact",
            "network": null,
            "asset": null,
            "payTo": null,
            "payableOperations": ["createEventProgrammatically"],
            "discovery": "https://cocap.cam/.well-known/x402.json",
            "reference": "https://www.x402.org"
        }
    },
    "servers": [
        {
            "url": "https://cocap.cam",
            "description": "Production"
        }
    ],
    "tags": [
        {
            "name": "pages",
            "description": "Human-facing pages, each with a markdown representation for agents."
        },
        {
            "name": "discovery",
            "description": "Machine-readable descriptions of CoCap."
        },
        {
            "name": "events",
            "description": "Event creation. Live and free; no payment is required."
        }
    ],
    "paths": {
        "/": {
            "get": {
                "operationId": "getLandingPage",
                "summary": "Landing page",
                "description": "Product overview, features, how-it-works, pricing and FAQ. Rendered client-side by Expo Router / React Native Web, so a non-executing fetch returns only the app shell. Agents should read /index.md instead.",
                "tags": ["pages"],
                "x-availability": "live",
                "x-markdown-representation": "/index.md",
                "responses": {
                    "200": {
                        "description": "HTML application shell.",
                        "content": {
                            "text/html": {}
                        },
                        "headers": {
                            "Link": {
                                "description": "Discovery relations: sitemap, describedby, alternate (markdown), service-desc, author.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/index.md": {
            "get": {
                "operationId": "getLandingPageMarkdown",
                "summary": "Landing page as markdown",
                "description": "Markdown representation of the landing page. This is the recommended entry point for agents.",
                "tags": ["pages"],
                "x-availability": "live",
                "responses": {
                    "200": {
                        "description": "Markdown document.",
                        "content": {
                            "text/markdown": {}
                        }
                    }
                }
            }
        },
        "/create": {
            "get": {
                "operationId": "getCreateEventPage",
                "summary": "Host event-creation flow",
                "description": "The page where a host names an event, picks a vibe, and generates a private feed with an invite QR code. Completing this flow is a human step.",
                "tags": ["pages", "events"],
                "x-availability": "live",
                "x-markdown-representation": "/create.md",
                "responses": {
                    "200": {
                        "description": "HTML application shell.",
                        "content": {
                            "text/html": {}
                        }
                    }
                }
            }
        },
        "/create.md": {
            "get": {
                "operationId": "getCreateEventPageMarkdown",
                "summary": "Event-creation flow as markdown",
                "tags": ["pages"],
                "x-availability": "live",
                "responses": {
                    "200": {
                        "description": "Markdown document.",
                        "content": {
                            "text/markdown": {}
                        }
                    }
                }
            }
        },
        "/llms.txt": {
            "get": {
                "operationId": "getLlmsTxt",
                "summary": "Concise agent description",
                "tags": ["discovery"],
                "x-availability": "live",
                "responses": {
                    "200": {
                        "description": "llms.txt document.",
                        "content": {
                            "text/plain": {}
                        }
                    }
                }
            }
        },
        "/llms-full.txt": {
            "get": {
                "operationId": "getLlmsFullTxt",
                "summary": "Extended agent documentation",
                "tags": ["discovery"],
                "x-availability": "live",
                "responses": {
                    "200": {
                        "description": "Extended llms document.",
                        "content": {
                            "text/plain": {}
                        }
                    }
                }
            }
        },
        "/.well-known/agent-card.json": {
            "get": {
                "operationId": "getAgentCard",
                "summary": "A2A Agent Card",
                "description": "CoCap's A2A identity, skills, and declared AP2 payment capability.",
                "tags": ["discovery"],
                "x-availability": "live",
                "responses": {
                    "200": {
                        "description": "A2A Agent Card.",
                        "content": {
                            "application/json": {}
                        }
                    }
                }
            }
        },
        "/api/events": {
            "post": {
                "operationId": "createEventProgrammatically",
                "summary": "Create an event",
                "description": "Creates a film and returns the ids and links a host or guest needs. Unauthenticated and free \u2014 creating a film requires no account and no payment, despite the price shape declared under `info.x-mpp`.\n\nThe server mints `id`, `qrValue` and `createdAt`; supplying them has no effect. A `coverImageUri` is kept only when it is an http(s) URL a guest could actually fetch. The resulting film is readable at `https://firebasestorage.googleapis.com/v0/b/<bucket>/o/<id>%2Fevent.json?alt=media`.",
                "tags": ["events"],
                "x-availability": "live",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "name",
                                    "startAt",
                                    "endAt",
                                    "revealAt"
                                ],
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "minLength": 1,
                                        "maxLength": 80,
                                        "description": "Event title shown to guests."
                                    },
                                    "guestMessage": {
                                        "type": "string",
                                        "maxLength": 280,
                                        "description": "Short note shown to guests when they join."
                                    },
                                    "eventType": {
                                        "type": "string",
                                        "enum": [
                                            "Wedding",
                                            "Birthday",
                                            "Trip",
                                            "Party",
                                            "Brand Event",
                                            "Everyday Moment"
                                        ]
                                    },
                                    "startAt": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event begins."
                                    },
                                    "endAt": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When the event ends. Must be after startAt."
                                    },
                                    "revealAt": {
                                        "type": "string",
                                        "format": "date-time",
                                        "description": "When guests may see the film. Must be after endAt."
                                    },
                                    "coverImageUri": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "http(s) cover image. Device-local URIs are ignored."
                                    }
                                }
                            },
                            "example": {
                                "name": "Sofia's Birthday",
                                "guestMessage": "Bring a hat",
                                "eventType": "Birthday",
                                "startAt": "2026-02-01T18:00:00.000Z",
                                "endAt": "2026-02-01T23:00:00.000Z",
                                "revealAt": "2026-02-02T18:00:00.000Z"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Event created.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "id",
                                        "galleryUrl",
                                        "inviteUrl",
                                        "event"
                                    ],
                                    "properties": {
                                        "id": {
                                            "type": "string",
                                            "pattern": "^[0-9A-Z]{6}$"
                                        },
                                        "galleryUrl": {
                                            "type": "string",
                                            "format": "uri"
                                        },
                                        "inviteUrl": {
                                            "type": "string",
                                            "format": "uri",
                                            "description": "Target the QR code encodes."
                                        },
                                        "event": {
                                            "type": "object",
                                            "description": "The stored event.json, as written."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Invalid payload. `errors` names each offending field.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "string",
                                            "const": "invalid_payload"
                                        },
                                        "message": {
                                            "type": "string"
                                        },
                                        "errors": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "field": {
                                                        "type": "string"
                                                    },
                                                    "message": {
                                                        "type": "string"
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "405": {
                        "description": "Method not allowed. Use POST."
                    },
                    "413": {
                        "description": "Body larger than 64 KiB."
                    },
                    "502": {
                        "description": "The event could not be stored. Retry."
                    },
                    "503": {
                        "description": "No event id could be allocated. Retry."
                    }
                }
            }
        }
    }
}
