{"openapi":"3.0.3","info":{"title":"Flash API","version":"2.0.0","description":"The Flash REST API lets you manage stores, loyalty members, coupons, points, captures, and more. Authenticate with an API Key passed via the X-API-Key header.","contact":{"name":"Flash Developer Support"}},"servers":[{"url":"/api/v2","description":"Flash v2 API"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string"}}},"Store":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["active","paused","archived"]},"address":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}},"Member":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"},"points_balance":{"type":"integer"},"current_tier_id":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"CouponPool":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"coupon_type":{"type":"string"},"discount_display":{"type":"string"},"status":{"type":"string"}}},"Coupon":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"pool_id":{"type":"string"},"redeemed":{"type":"boolean"},"expires_at":{"type":"string","format":"date-time","nullable":true}}},"PointsTransaction":{"type":"object","properties":{"id":{"type":"string"},"amount":{"type":"integer"},"balance_after":{"type":"integer"},"description":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}},"Capture":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"store_id":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}},"Tier":{"type":"object","properties":{"name":{"type":"string"},"rank":{"type":"integer"},"upgrade_threshold":{"type":"integer"},"multiplier":{"type":"number"}}},"Receipt":{"type":"object","properties":{"id":{"type":"string"},"ocr_status":{"type":"string"},"status":{"type":"string"},"points_awarded":{"type":"integer","nullable":true},"created_at":{"type":"string","format":"date-time"}}}}},"paths":{"/stores":{"get":{"tags":["Stores"],"operationId":"listStores","summary":"List stores","description":"List all stores for the authenticated team. Supports status filter, search, and pagination.","parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["active","paused","archived"]},"description":"Filter by status"},{"name":"search","in":"query","schema":{"type":"string"},"description":"Search by store name"},{"name":"limit","in":"query","schema":{"type":"integer","default":50},"description":"Max results"},{"name":"offset","in":"query","schema":{"type":"integer","default":0},"description":"Pagination offset"}],"responses":{"200":{"description":"Store list","content":{"application/json":{"schema":{"type":"object","properties":{"stores":{"type":"array","items":{"$ref":"#/components/schemas/Store"}},"total":{"type":"integer"}}}}}}}}},"/stores/{id}":{"get":{"tags":["Stores"],"operationId":"getStore","summary":"Get store by ID","description":"Retrieve details of a single store.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Store details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Store"}}}},"404":{"description":"Store not found"}}}},"/members":{"get":{"tags":["Members"],"operationId":"listMembers","summary":"List members","description":"List loyalty members. Supports program filter, status filter, and pagination.","parameters":[{"name":"programId","in":"query","schema":{"type":"string"},"description":"Filter by program ID"},{"name":"status","in":"query","schema":{"type":"string","enum":["pending","active","unsubscribed","inactive","deactivation_pending","deleted"]},"description":"Filter by status"},{"name":"limit","in":"query","schema":{"type":"integer","default":50},"description":"Max results (max 200)"},{"name":"offset","in":"query","schema":{"type":"integer","default":0},"description":"Pagination offset"}],"responses":{"200":{"description":"Member list","content":{"application/json":{"schema":{"type":"object","properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/Member"}},"total":{"type":"integer"}}}}}}}}},"/members/{id}":{"get":{"tags":["Members"],"operationId":"getMember","summary":"Get member by ID","description":"Retrieve a single member's details including decrypted PII fields.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Member details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Member"}}}},"404":{"description":"Member not found"}}}},"/members/{id}/points":{"get":{"tags":["Members"],"operationId":"getMemberPoints","summary":"Get member points balance","description":"Returns the member's current points balance and recent transaction history.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":10},"description":"Max transactions"}],"responses":{"200":{"description":"Points balance + transactions","content":{"application/json":{"schema":{"type":"object","properties":{"memberId":{"type":"string"},"balance":{"type":"integer"},"transactions":{"type":"array","items":{"$ref":"#/components/schemas/PointsTransaction"}}}}}}}}},"post":{"tags":["Members"],"operationId":"earnPoints","summary":"Earn / award points","description":"Award loyalty points to a member. Returns new balance.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["amount"],"properties":{"amount":{"type":"integer","minimum":1,"description":"Points to award"},"description":{"type":"string","description":"Reason"}}}}}},"responses":{"200":{"description":"Points awarded","content":{"application/json":{"schema":{"type":"object","properties":{"transactionId":{"type":"string"},"balance":{"type":"integer"}}}}}}}}},"/members/{id}/tier":{"get":{"tags":["Members"],"operationId":"getMemberTier","summary":"Get member tier","description":"Returns the member's current tier, all available tiers, and upgrade requirements.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Tier info","content":{"application/json":{"schema":{"type":"object","properties":{"currentTier":{"$ref":"#/components/schemas/Tier"},"allTiers":{"type":"array","items":{"$ref":"#/components/schemas/Tier"}}}}}}}}}},"/members/{id}/coupons":{"get":{"tags":["Members"],"operationId":"getMemberCoupons","summary":"Get member coupons","description":"List a member's available (unredeemed, unexpired) coupons.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Coupon list","content":{"application/json":{"schema":{"type":"object","properties":{"memberId":{"type":"string"},"coupons":{"type":"array","items":{"$ref":"#/components/schemas/Coupon"}}}}}}}}}},"/members/{id}/receipts":{"get":{"tags":["Members"],"operationId":"getMemberReceipts","summary":"Get member receipts","description":"List a member's receipt submission history with OCR status and points awarded.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":10},"description":"Max results"}],"responses":{"200":{"description":"Receipt list","content":{"application/json":{"schema":{"type":"object","properties":{"memberId":{"type":"string"},"receipts":{"type":"array","items":{"$ref":"#/components/schemas/Receipt"}}}}}}}}}},"/members/{id}/redeem-coupon":{"post":{"tags":["Members"],"operationId":"redeemPointsForCoupon","summary":"Redeem points for coupon","description":"Deduct points and allocate a coupon from a specified pool.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["pool_id","points_cost"],"properties":{"pool_id":{"type":"string"},"points_cost":{"type":"integer","minimum":1}}}}}},"responses":{"200":{"description":"Coupon redeemed","content":{"application/json":{"schema":{"type":"object","properties":{"pointsDeducted":{"type":"integer"},"newBalance":{"type":"integer"},"coupon":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"}}}}}}}}}}},"/captures":{"get":{"tags":["Captures"],"operationId":"listCaptures","summary":"List captures","description":"List capture records (email + store captures) with pagination.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":50},"description":"Max results"},{"name":"offset","in":"query","schema":{"type":"integer","default":0},"description":"Offset"}],"responses":{"200":{"description":"Capture list","content":{"application/json":{"schema":{"type":"object","properties":{"captures":{"type":"array","items":{"$ref":"#/components/schemas/Capture"}},"total":{"type":"integer"}}}}}}}}},"/coupons":{"get":{"tags":["Coupons"],"operationId":"listCoupons","summary":"List coupons","description":"List coupon codes with optional filters.","parameters":[{"name":"pool_id","in":"query","schema":{"type":"string"},"description":"Filter by pool"},{"name":"limit","in":"query","schema":{"type":"integer","default":50},"description":"Max results"},{"name":"offset","in":"query","schema":{"type":"integer","default":0},"description":"Offset"}],"responses":{"200":{"description":"Coupon list","content":{"application/json":{"schema":{"type":"object","properties":{"coupons":{"type":"array","items":{"$ref":"#/components/schemas/Coupon"}},"total":{"type":"integer"}}}}}}}}},"/coupons/pools":{"get":{"tags":["Coupons"],"operationId":"listCouponPools","summary":"List coupon pools","description":"List coupon pools. Supports status and type filters.","parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["active","paused","archived"]},"description":"Filter by status"},{"name":"coupon_type","in":"query","schema":{"type":"string"},"description":"Filter by type"},{"name":"limit","in":"query","schema":{"type":"integer","default":50},"description":"Max results"},{"name":"offset","in":"query","schema":{"type":"integer","default":0},"description":"Offset"}],"responses":{"200":{"description":"Pool list","content":{"application/json":{"schema":{"type":"object","properties":{"pools":{"type":"array","items":{"$ref":"#/components/schemas/CouponPool"}},"total":{"type":"integer"}}}}}}}}},"/coupons/issue":{"post":{"tags":["Coupons"],"operationId":"issueCoupon","summary":"Issue a coupon","description":"Allocate a coupon code from a pool to a capture / member.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["pool_id","assigned_to"],"properties":{"pool_id":{"type":"string"},"assigned_to":{"type":"string","description":"Capture ID"}}}}}},"responses":{"200":{"description":"Coupon issued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Coupon"}}}}}}},"/coupons/{id}/redeem":{"post":{"tags":["Coupons"],"operationId":"redeemCoupon","summary":"Redeem a coupon","description":"Mark a coupon code as redeemed.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Coupon redeemed"},"404":{"description":"Coupon not found"}}}},"/api-keys":{"get":{"tags":["API Keys"],"operationId":"listApiKeys","summary":"List API keys","description":"List all API keys for the authenticated team.","responses":{"200":{"description":"Key list","content":{"application/json":{"schema":{"type":"object","properties":{"keys":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"prefix":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"created_at":{"type":"string"}}}}}}}}}}},"post":{"tags":["API Keys"],"operationId":"createApiKey","summary":"Create API key","description":"Create a new API key. The full key is returned only once.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","scopes"],"properties":{"name":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}}}}}}},"responses":{"201":{"description":"Key created (full key returned once)","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"key":{"type":"string"},"name":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}}}}}}}}}},"/api-keys/{id}":{"delete":{"tags":["API Keys"],"operationId":"deleteApiKey","summary":"Delete API key","description":"Revoke and delete an API key.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Key deleted"},"404":{"description":"Key not found"}}}},"/auth/register":{"post":{"tags":["Auth"],"operationId":"register","summary":"Register","description":"Register a new user account.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password","name"],"properties":{"email":{"type":"string"},"password":{"type":"string"},"name":{"type":"string"}}}}}},"responses":{"201":{"description":"Account created"}}}},"/auth/login":{"post":{"tags":["Auth"],"operationId":"login","summary":"Login","description":"Authenticate and receive a JWT token.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string"},"password":{"type":"string"}}}}}},"responses":{"200":{"description":"JWT token","content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"}}}}}}}}},"/auth/profile":{"get":{"tags":["Auth"],"operationId":"getProfile","summary":"Get profile","description":"Get the authenticated user's profile.","responses":{"200":{"description":"Profile data"}}},"patch":{"tags":["Auth"],"operationId":"updateProfile","summary":"Update profile","description":"Update the authenticated user's profile fields.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"avatar_url":{"type":"string"}}}}}},"responses":{"200":{"description":"Updated profile"}}}},"/auth/change-password":{"post":{"tags":["Auth"],"operationId":"changePassword","summary":"Change password","description":"Change the authenticated user's password.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["current_password","new_password"],"properties":{"current_password":{"type":"string"},"new_password":{"type":"string"}}}}}},"responses":{"200":{"description":"Password changed"}}}},"/auth/forgot-password":{"post":{"tags":["Auth"],"operationId":"forgotPassword","summary":"Forgot password","description":"Request a password-reset email.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string"}}}}}},"responses":{"200":{"description":"Reset email sent"}}}},"/auth/reset-password":{"post":{"tags":["Auth"],"operationId":"resetPassword","summary":"Reset password","description":"Reset password using a token from the reset email.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token","new_password"],"properties":{"token":{"type":"string"},"new_password":{"type":"string"}}}}}},"responses":{"200":{"description":"Password reset"}}}}},"tags":[{"name":"Stores","description":"Store management"},{"name":"Members","description":"Loyalty member management"},{"name":"Captures","description":"Capture records"},{"name":"Coupons","description":"Coupon pools, codes, and redemption"},{"name":"API Keys","description":"API key management"},{"name":"Auth","description":"Authentication and user profile"}]}