{"openapi":"3.1.0","info":{"title":"ChordMuse Billing API","version":"1.0.0","description":"Verifies App Store purchases, follows subscriptions, and publishes entitlements for ChordMuse apps."},"servers":[{"url":"/"}],"tags":[{"name":"Apps","description":"Called by the apps, as the signed-in user."},{"name":"Apple","description":"Called by Apple."},{"name":"Admin","description":"Support: grants and revokes by hand."},{"name":"Service"}],"paths":{"/v1/health":{"get":{"tags":["Service"],"summary":"Health check","security":[],"responses":{"200":{"description":"Running","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}}}}}}}}},"/v1/{app}/entitlements":{"get":{"tags":["Apps"],"summary":"The signed-in account's entitlement","parameters":[{"name":"app","in":"path","required":true,"description":"The app id (src/config.ts).","schema":{"type":"string","enum":["chordmuse-flow"]}}],"security":[{"firebase":[]}],"responses":{"200":{"description":"The entitlement now","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Entitlement"}}}},"401":{"description":"Not signed in","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown app","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/{app}/apple/verify":{"post":{"tags":["Apps"],"summary":"Verify a purchase","description":"After a purchase or restore, the app sends the transaction (StoreKit `jwsRepresentation`). It is saved and published for the account.","parameters":[{"name":"app","in":"path","required":true,"description":"The app id (src/config.ts).","schema":{"type":"string","enum":["chordmuse-flow"]}}],"security":[{"firebase":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["signedTransaction"],"properties":{"signedTransaction":{"type":"string","description":"The signed transaction (JWS)."}}}}}},"responses":{"200":{"description":"The entitlement now","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Entitlement"}}}},"400":{"description":"Missing, unverifiable, or not one of the app's products","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The purchase belongs to another account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown app","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/{app}/apple/notifications":{"post":{"tags":["Apple"],"summary":"App Store Server Notifications V2","description":"Set as the app's Production and Sandbox Server URL in App Store Connect. Verified by Apple's signature.","parameters":[{"name":"app","in":"path","required":true,"description":"The app id (src/config.ts).","schema":{"type":"string","enum":["chordmuse-flow"]}}],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["signedPayload"],"properties":{"signedPayload":{"type":"string"}}}}}},"responses":{"200":{"description":"Received","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}}}}}},"400":{"description":"Missing or unverifiable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown app","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/{app}/admin/grant":{"post":{"tags":["Admin"],"summary":"Grant an entitlement","parameters":[{"name":"app","in":"path","required":true,"description":"The app id (src/config.ts).","schema":{"type":"string","enum":["chordmuse-flow"]}}],"security":[{"admin":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["accountId","entitlement"],"properties":{"accountId":{"type":"string","description":"Firebase uid"},"entitlement":{"type":"string","enum":["pro","plus"]},"expiresAt":{"type":"integer","description":"Milliseconds since 1970, in the future. Leave out for no expiry."},"note":{"type":"string"}}}}}},"responses":{"200":{"description":"The entitlement now","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Entitlement"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Admin key required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown app","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/{app}/admin/revoke":{"post":{"tags":["Admin"],"summary":"End an account's grants of an entitlement","description":"Only grants are revoked; store subscriptions follow the store.","parameters":[{"name":"app","in":"path","required":true,"description":"The app id (src/config.ts).","schema":{"type":"string","enum":["chordmuse-flow"]}}],"security":[{"admin":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["accountId","entitlement"],"properties":{"accountId":{"type":"string","description":"Firebase uid"},"entitlement":{"type":"string","enum":["pro","plus"]},"note":{"type":"string"}}}}}},"responses":{"200":{"description":"The entitlement now","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Entitlement"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Admin key required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown app","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"Entitlement":{"type":"object","required":["entitlement","expiresAt"],"properties":{"entitlement":{"type":["string","null"],"description":"The best active entitlement, or null for none.","examples":["pro"]},"expiresAt":{"type":["integer","null"],"description":"When it ends, in milliseconds since 1970; null: no expiry, or none.","examples":[1793836800000]}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}}}},"securitySchemes":{"firebase":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"A Firebase ID token of the signed-in user."},"admin":{"type":"http","scheme":"bearer","description":"BILLING_ADMIN_KEY"}}}}