{"openapi":"3.1.1","info":{"title":"Graham & Lane Florists Public Catalog API","version":"1.0.0","description":"Free, anonymous, read-only access to published Edmonton flower arrangements, current CAD prices and studio information. No signup, API key, authentication or payment is required. Does not expose customer data or create carts, purchases, calls or bookings. Online purchasing is temporarily unavailable. Call (780) 429-1637 to order. Canonical versioned endpoints use /api/v1/. Original unversioned endpoints remain compatible. Breaking changes require a new version; future deprecation will be announced in documentation with deprecation and sunset headers before retirement. No retirement is scheduled.","contact":{"name":"Graham & Lane Florists","email":"info@grahamandlane.com","url":"https://grahamandlane.com/pages/contact"}},"servers":[{"url":"https://grahamandlane.com"}],"security":[],"externalDocs":{"description":"Quickstart, pricing, error handling and ordering limitations","url":"https://grahamandlane.com/docs"},"paths":{"/api/arrangements.json":{"get":{"operationId":"find_arrangements","summary":"Find published flower arrangements","description":"Complete matching catalog for original clients, without pagination. Optional q searches names, colours and occasions. Prices exclude delivery and tax; call to confirm stock and order. Use /api/v1/arrangements.json for new paginated integrations.","parameters":[{"name":"q","in":"query","required":false,"description":"Optional search phrase, up to 200 characters. Supply at most one q.","schema":{"type":"string","maxLength":200},"example":"yellow"},{"name":"API-Version","in":"header","required":false,"description":"Optional API major version. Only 1 is supported; any other value returns 400.","schema":{"type":"string","enum":["1"],"default":"1"}}],"responses":{"200":{"description":"Published arrangements. An empty arrangements array means no matches.","content":{"application/json":{"schema":{"type":"object","properties":{"studio":{"type":"string"},"currency":{"type":"string","enum":["CAD"]},"ordering":{"type":"string"},"arrangements":{"type":"array","items":{"$ref":"#/components/schemas/Arrangement"}}},"required":["studio","currency","ordering","arrangements"]}}},"headers":{"API-Version":{"description":"Supported API major version.","schema":{"type":"string","enum":["1"]}},"RateLimit-Limit":{"description":"Per-worker request budget per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests remaining in this worker bucket.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until this worker bucket resets.","schema":{"type":"integer"}}}},"400":{"description":"Invalid query parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Ephemeral per-worker public REST request budget exhausted. Respect Retry-After.","headers":{"Retry-After":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Catalog or service temporarily unavailable. Retry after 60 seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Delay before retrying, in seconds.","schema":{"type":"string","enum":["60"]}}}}}}},"/api/studio.json":{"get":{"operationId":"get_studio_information","summary":"Read studio information","description":"Read public studio contact details, hours, delivery areas, pickup preparation and ordering instructions. No query parameters. Optional API-Version header selects the supported major version. Never initiates a call or booking.","responses":{"200":{"description":"Public studio information.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Studio"}}},"headers":{"API-Version":{"description":"Supported API major version.","schema":{"type":"string","enum":["1"]}},"RateLimit-Limit":{"description":"Per-worker request budget per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests remaining in this worker bucket.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until this worker bucket resets.","schema":{"type":"integer"}}}},"400":{"description":"Invalid query parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Ephemeral per-worker public REST request budget exhausted. Respect Retry-After.","headers":{"Retry-After":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Catalog or service temporarily unavailable. Retry after 60 seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Delay before retrying, in seconds.","schema":{"type":"string","enum":["60"]}}}}},"parameters":[{"name":"API-Version","in":"header","required":false,"description":"Optional API major version. Only 1 is supported; any other value returns 400.","schema":{"type":"string","enum":["1"],"default":"1"}}]}},"/api/v1/arrangements.json":{"get":{"operationId":"find_arrangements_v1","summary":"Find published flower arrangements","description":"Version 1 public catalog. Paginate matching results with limit and offset. Follow pagination.next or the Link rel=next header until hasMore is false. Prices exclude delivery and tax; call to confirm stock and order. Results are ordered by handle. Follow the opaque cursor in pagination.next/nextCursor for subsequent pages; do not combine cursor with offset or change q.","parameters":[{"name":"q","in":"query","required":false,"description":"Optional search phrase, up to 200 characters. Supply at most one q.","schema":{"type":"string","maxLength":200},"example":"yellow"},{"name":"API-Version","in":"header","required":false,"description":"Optional API major version. Only 1 is supported; any other value returns 400.","schema":{"type":"string","enum":["1"],"default":"1"}},{"name":"limit","in":"query","required":false,"description":"Maximum arrangements per page.","schema":{"type":"integer","minimum":1,"maximum":100,"default":100}},{"name":"offset","in":"query","required":false,"description":"Number of matching arrangements to skip.","schema":{"type":"integer","minimum":0,"maximum":9007199254740991,"default":0}},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor returned by a prior response. Keep q unchanged and omit offset.","schema":{"type":"string","maxLength":2048}}],"responses":{"200":{"description":"Published arrangements. An empty arrangements array means no matches.","content":{"application/json":{"schema":{"type":"object","properties":{"studio":{"type":"string"},"currency":{"type":"string","enum":["CAD"]},"ordering":{"type":"string"},"arrangements":{"type":"array","items":{"$ref":"#/components/schemas/Arrangement"}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["studio","currency","ordering","arrangements","pagination"]}}},"headers":{"API-Version":{"description":"Supported API major version.","schema":{"type":"string","enum":["1"]}},"Link":{"description":"Present when another page exists; absolute URL with rel=next.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Per-worker request budget per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests remaining in this worker bucket.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until this worker bucket resets.","schema":{"type":"integer"}}}},"400":{"description":"Invalid query parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Ephemeral per-worker public REST request budget exhausted. Respect Retry-After.","headers":{"Retry-After":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Catalog or service temporarily unavailable. Retry after 60 seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Delay before retrying, in seconds.","schema":{"type":"string","enum":["60"]}}}}}}},"/api/v1/studio.json":{"get":{"operationId":"get_studio_information_v1","summary":"Read studio information","description":"Read public studio contact details, hours, delivery areas, pickup preparation and ordering instructions. No query parameters. Optional API-Version header selects the supported major version. Never initiates a call or booking.","responses":{"200":{"description":"Public studio information.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Studio"}}},"headers":{"API-Version":{"description":"Supported API major version.","schema":{"type":"string","enum":["1"]}},"RateLimit-Limit":{"description":"Per-worker request budget per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Requests remaining in this worker bucket.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Seconds until this worker bucket resets.","schema":{"type":"integer"}}}},"400":{"description":"Invalid query parameters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Ephemeral per-worker public REST request budget exhausted. Respect Retry-After.","headers":{"Retry-After":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Catalog or service temporarily unavailable. Retry after 60 seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Delay before retrying, in seconds.","schema":{"type":"string","enum":["60"]}}}}},"parameters":[{"name":"API-Version","in":"header","required":false,"description":"Optional API major version. Only 1 is supported; any other value returns 400.","schema":{"type":"string","enum":["1"],"default":"1"}}]}}},"components":{"schemas":{"Money":{"type":"object","properties":{"amount":{"type":"string","pattern":"^\\d+(\\.\\d+)?$","description":"CAD decimal amount represented as a string","examples":["89.95"]},"currencyCode":{"type":"string","enum":["CAD"]}},"required":["amount","currencyCode"]},"Arrangement":{"type":"object","properties":{"name":{"type":"string"},"handle":{"type":"string"},"url":{"type":"string","format":"uri"},"image":{"type":"string","format":"uri"},"fromPrice":{"$ref":"#/components/schemas/Money"},"colours":{"type":"array","items":{"type":"string"}},"occasions":{"type":"array","items":{"type":"string"}},"sizes":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"price":{"$ref":"#/components/schemas/Money"},"availableForSale":{"type":"boolean","description":"Published catalog availability; confirm stock with the studio. Does not indicate that online purchasing is enabled."}},"required":["name","price","availableForSale"]}}},"required":["name","handle","url","fromPrice","colours","occasions","sizes"]},"Studio":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"url":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"},"address":{"type":"string"},"hours":{"type":"string"},"ordering":{"type":"string"},"pickup":{"type":"string"},"deliveryAreas":{"type":"array","items":{"type":"string"}}},"required":["name","description","url","phone","email","address","hours","ordering","pickup","deliveryAreas"]},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"documentation":{"type":"string","format":"uri"}},"required":["code","message","documentation"]}},"required":["error"]},"Pagination":{"type":"object","properties":{"limit":{"type":"integer","minimum":1,"maximum":100},"offset":{"type":"integer","minimum":0},"total":{"type":"integer","minimum":0},"hasMore":{"type":"boolean"},"next":{"type":["string","null"],"format":"uri","description":"Absolute next-page URL, or null on the last page."},"nextCursor":{"type":["string","null"],"description":"Opaque cursor for the next page; null on the last page."}},"required":["limit","offset","total","hasMore","next","nextCursor"]}}}}