---
title: "Reconcile Store Entitlement"
method: POST
path: "/subscriptions/reconcile"
tags: ["subscriptions"]
---

# Reconcile Store Entitlement

`POST /subscriptions/reconcile`

Ask the store what this person actually bought, and repair the row.

`POST /webhooks/revenuecat` is the only way the backend hears about a Play
or App Store purchase, and the Pub/Sub RTDN endpoint beside it is a logging
stub. A webhook that is dropped, rejected during a secret rotation, or lost
while a pod rolls therefore leaves somebody who has been charged on the
free tier with no way back except a hand-written script. This is the way
back: the client calls it after a purchase or a restore, and the server
asks RevenueCat directly rather than believing anything the client says
about its own entitlements.

UPGRADE ONLY. If RevenueCat has no active entitlement but the local row
claims a paid tier, that is reported as drift and nothing is written: the
tier may have come from an invite code, from `bonus_tier` days, or from
Stripe, none of which RevenueCat has ever heard of. Revoking is the sweep's
job, behind an explicit flag, not a user-triggered endpoint's.

Idempotent: two calls in a row leave the same row, and the second reports
`action: "none"`.

## Headers

- `authorization` string, nullable

## Response `200`

Successful Response

- unknown

## Other responses

- `422` — Validation Error

## Changes

> 20 revisions in range; 1 not diffed.

- **2026-09-13** `3c5400a294e1` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/fluentea/apis/aurqa-language-learning-platform-refactored/changes/subscriptions/reconcile/post.md)

---

[API](https://skmtc.dev/fluentea/apis/aurqa-language-learning-platform-refactored.md) · [All operations](https://skmtc.dev/fluentea/apis/aurqa-language-learning-platform-refactored/llms.txt) · [OpenAPI document](https://skmtc.dev/fluentea/apis/aurqa-language-learning-platform-refactored/revisions/ee945980cf00?raw)
