{"openapi":"3.1.0","info":{"title":"Inviting2U Public API","description":"Read-only public API for browsing invitation packages, design templates, and published invitations. Designed for AI agents and third-party integrations. Purchase endpoints are documented but return 501 until OAuth2 is enabled.","version":"1.0.0","termsOfService":"https://inviting2u.com/terms","contact":{"name":"Inviting2U Support","email":"support@inviting2u.com","url":"https://inviting2u.com/contact"},"license":{"name":"Proprietary"}},"servers":[{"url":"https://inviting2u.com","description":"Production"}],"tags":[{"name":"Health","description":"Service liveness and version"},{"name":"Plans","description":"One-time-purchase invitation packages"},{"name":"Templates","description":"Invitation card designs (templates)"},{"name":"Events","description":"Event categories and types supported by the platform"},{"name":"Invitations","description":"Public published invitations"},{"name":"Orders","description":"Purchase a package (currently planned — returns 501)"}],"paths":{"/api/v1/health":{"get":{"tags":["Health"],"summary":"Service health check","description":"Returns service status, version, and a quick check of the database and cache. Use to verify the service is up before issuing other requests. Responds in under 100 ms.","operationId":"getHealth","x-intent":"verify the service is reachable","x-action":"READ_STATUS","responses":{"200":{"description":"Service is up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}}}}},"/api/v1/plans":{"get":{"tags":["Plans"],"summary":"List all active invitation packages","description":"Returns every package available for one-time purchase, with pricing in MYR and validity in months. Use when the user asks about cost, plans, pricing, or available options.","operationId":"listPlans","x-intent":"user wants to know the prices or options","x-action":"READ_LIST","responses":{"200":{"description":"List of plans","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Plan"}}}}}}}}}},"/api/v1/plans/{key}":{"get":{"tags":["Plans"],"summary":"Get a single package by key","description":"Returns details for one package. Plan keys are stable identifiers like \"basic\", \"standard\", \"premium\".","operationId":"getPlan","x-intent":"user asks for details about one specific plan","x-action":"READ_ITEM","parameters":[{"$ref":"#/components/parameters/PlanKey"}],"responses":{"200":{"description":"Plan","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Plan"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/templates":{"get":{"tags":["Templates"],"summary":"List invitation card design templates","description":"Browse the catalog of invitation designs. Filter by event category (e.g. \"wedding\") or style (e.g. \"minimalist\", \"classic\"). Each template has a preview image URL.","operationId":"listTemplates","x-intent":"user wants to browse, find, or choose a template","x-action":"READ_LIST","parameters":[{"name":"category","in":"query","required":false,"schema":{"type":"string"},"description":"Event category slug (e.g. wedding, birthday, corporate)"},{"name":"style","in":"query","required":false,"schema":{"type":"string"},"description":"Style tag (e.g. minimalist, classic, modern)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":20,"maximum":100}}],"responses":{"200":{"description":"List of templates","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Template"}}}}}}}}}},"/api/v1/templates/{code}":{"get":{"tags":["Templates"],"summary":"Get one template by code","description":"Returns full details for a single template, including all preview images and a public preview URL the user can open in a browser.","operationId":"getTemplate","x-intent":"user wants to see one specific template in detail","x-action":"READ_ITEM","parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Template","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Template"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/event-types":{"get":{"tags":["Events"],"summary":"List supported event categories and types","description":"Returns the full taxonomy of event categories (e.g. Wedding, Birthday) and the event types under each. Use to validate user input or suggest options.","operationId":"listEventTypes","x-intent":"user asks what kinds of events are supported","x-action":"READ_LIST","responses":{"200":{"description":"Categories with nested types","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EventCategory"}}}}}}}}}},"/api/v1/invitations/{slug}":{"get":{"tags":["Invitations"],"summary":"Get a public published invitation by slug","description":"Returns the public-facing data of a published invitation: host names, event date, venue, RSVP status, and the URL guests should visit. Only returns invitations the owner has published; otherwise 404.","operationId":"getInvitation","x-intent":"user references an invitation slug and wants its details","x-action":"READ_ITEM","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Invitation","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Invitation"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/orders":{"post":{"tags":["Orders"],"summary":"Purchase an invitation package (planned)","description":"Initiates a one-time package purchase and returns a hosted payment URL. **Currently returns 501 Not Implemented** — this endpoint is documented for forward compatibility and will go live once OAuth2 (Laravel Passport) is enabled. See the contact email for current integration options.","operationId":"createOrder","x-intent":"user wants to purchase or subscribe to a plan","x-action":"PURCHASE","x-status":"planned","security":[{"BearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Idempotency key — repeating a request with the same key within 24 h returns the cached response."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderRequest"}}}},"responses":{"201":{"description":"Order created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderResponse"}}}},"501":{"description":"Not implemented yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/openapi.json":{"get":{"tags":["Health"],"summary":"Get this OpenAPI document","description":"Returns the OpenAPI 3.1 spec for the public API. Self-referencing so agents can re-introspect.","operationId":"getOpenApiSpec","x-intent":"agent wants to read the API contract","x-action":"READ_ITEM","responses":{"200":{"description":"OpenAPI document","content":{"application/json":{"schema":{"type":"object"}}}}}}}},"components":{"schemas":{"Health":{"type":"object","required":["status","version","timestamp"],"properties":{"status":{"type":"string","enum":["ok","degraded","down"]},"version":{"type":"string","example":"1.0.0"},"timestamp":{"type":"string","format":"date-time"},"services":{"type":"object","properties":{"db":{"type":"string","enum":["ok","fail"]},"cache":{"type":"string","enum":["ok","fail"]}}}}},"Plan":{"type":"object","required":["key","name","price","currency","duration_months"],"properties":{"key":{"type":"string","example":"standard"},"name":{"type":"string","example":"Standard"},"price":{"type":"number","format":"float","example":89},"discounted_price":{"type":"number","format":"float","example":89},"discount_percent":{"type":"integer","example":0},"currency":{"type":"string","example":"MYR"},"duration_months":{"type":"integer","example":12},"duration_label":{"type":"string","example":"12 months"},"features":{"type":"array","items":{"type":"string"}},"is_popular":{"type":"boolean"},"purchase_url":{"type":"string","format":"uri"}}},"Template":{"type":"object","required":["code","name"],"properties":{"code":{"type":"string","example":"TPL001"},"name":{"type":"string"},"style_tag":{"type":"string","nullable":true},"event_categories":{"type":"array","items":{"type":"string","enum":["wedding","perayaan","baby","birthday"]}},"preview_image":{"type":"string","format":"uri","nullable":true},"preview_images":{"type":"array","items":{"type":"string","format":"uri"}},"preview_url":{"type":"string","format":"uri"},"is_featured":{"type":"boolean"},"is_popular":{"type":"boolean"}}},"EventCategory":{"type":"object","required":["slug","name"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"types":{"type":"array","items":{"$ref":"#/components/schemas/EventType"}}}},"EventType":{"type":"object","required":["slug","name"],"properties":{"slug":{"type":"string"},"name":{"type":"string"}}},"Invitation":{"type":"object","required":["slug","is_published","url"],"properties":{"slug":{"type":"string"},"event_title":{"type":"string","nullable":true},"event_type":{"type":"string","nullable":true},"hosts":{"type":"string","nullable":true},"event_date":{"type":"string","format":"date-time","nullable":true},"venue":{"type":"string","nullable":true},"is_published":{"type":"boolean"},"rsvp_open":{"type":"boolean"},"url":{"type":"string","format":"uri"},"locales":{"type":"array","items":{"type":"string"}}}},"OrderRequest":{"type":"object","required":["plan_key","template_code","payment_provider"],"properties":{"plan_key":{"type":"string","example":"standard"},"template_code":{"type":"string","example":"TPL001"},"payment_provider":{"type":"string","enum":["billplz","toyyibpay","stripe","paypal","manual"]},"promo_code":{"type":"string","nullable":true},"return_url":{"type":"string","format":"uri","description":"Where to redirect the user after payment completes"}}},"OrderResponse":{"type":"object","properties":{"order_id":{"type":"integer"},"status":{"type":"string","enum":["pending","paid","failed"]},"amount":{"type":"number"},"currency":{"type":"string"},"payment_url":{"type":"string","format":"uri","description":"Hand this URL back to the user to complete payment"},"message":{"type":"string","description":"Human-readable status the agent can relay to the user"}}},"Error":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string","description":"Human-readable message the agent can relay to the user"},"code":{"type":"string","description":"Machine-readable error code","example":"NOT_FOUND"},"suggestion":{"type":"string","description":"What the agent should try next","nullable":true}}}},"responses":{"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying"},"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":{"PlanKey":{"name":"key","in":"path","required":true,"schema":{"type":"string","enum":["standard"]},"description":"Stable package identifier"}},"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"User session token (planned — currently no public auth required for v1 read endpoints)."},"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-Agent-ID","description":"Optional agent identifier for analytics; not used for authorization."}}}}