Skip to content

fix(revenuecat): align tools and block with REST v1 API spec#4486

Closed
waleedlatif1 wants to merge 4 commits intostagingfrom
waleedlatif1/validate-revenuecat
Closed

fix(revenuecat): align tools and block with REST v1 API spec#4486
waleedlatif1 wants to merge 4 commits intostagingfrom
waleedlatif1/validate-revenuecat

Conversation

@waleedlatif1
Copy link
Copy Markdown
Collaborator

Summary

  • Validated all 10 RevenueCat tools and the block against REST v1 docs (context7)
  • Fixed refund_google_subscription to use /transactions/{storeTransactionId}/refund
  • Fixed delete_customer to read deleted field (was was_deleted)
  • Made create_purchase X-Platform required; added presentedOfferingIdentifier, paymentMode
  • grant_entitlement: duration now optional, added endTimeMs (one-of)
  • defer_google_subscription: extendByDays now optional, added expiryTimeMs (one-of)
  • Added shared throwIfRevenueCatError helper for {code, message} error envelope
  • Moved type coercions from tools.config.tooltools.config.params to preserve dynamic refs
  • Added two_week duration option; corrected list_offerings X-Platform values
  • Updated update_subscriber_attributes description to note required updated_at_ms

Type of Change

  • Bug fix

Testing

Tested manually; type-check clean

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link
Copy Markdown

vercel Bot commented May 7, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview, Comment May 7, 2026 5:04am

Request Review

@cursor
Copy link
Copy Markdown

cursor Bot commented May 7, 2026

PR Summary

Medium Risk
Updates multiple RevenueCat tool request/response contracts (new required params, endpoint changes, and new parsing/error handling), which could break existing workflows if callers or UI blocks rely on the previous shapes.

Overview
Aligns the RevenueCat integration (tools, block UI, and docs) to the REST v1 spec, expanding the subscriber shape (e.g., last_seen, original_application_version, other_purchases, subscriber_attributes) and standardizing response parsing via new helpers (extractSubscriber, shapeSubscriber).

Fixes and extends key operations: refund_google_subscription now refunds by storeTransactionId via /transactions/{id}/refund; create_purchase now requires X-Platform and supports additional receipt/attribution fields (offering/payment/intro price/attributes); grant_entitlement and defer_google_subscription add one-of timing params (endTimeMs/expiryTimeMs) with validation.

Hardens tool behavior by trimming IDs in URLs, adding centralized {code,message} error handling (throwIfRevenueCatError), and updating the block’s param coercion/mapping to preserve dynamic references and support the new API fields.

Reviewed by Cursor Bugbot for commit e999b64. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 7, 2026

Greptile Summary

This PR aligns all 10 RevenueCat tools and the block UI with the REST v1 API spec, fixing two incorrect endpoints (refund_google_subscription, delete_customer), adding missing required/optional params across several tools, and introducing a shared throwIfRevenueCatError helper that parses the {code, message} error envelope.

  • Endpoint & field corrections: refund_google_subscription now targets /transactions/{storeTransactionId}/refund; delete_customer reads deleted first (falls back to was_deleted); create_purchase adds presentedOfferingIdentifier, paymentMode, and makes platform required.
  • One-of param pairs: grant_entitlement and defer_google_subscription both accept either a relative duration/days or an absolute timestamp, with runtime guards that throw when neither or both are supplied.
  • Block coercion refactor: type conversions moved from tools.config.tool to tools.config.params so the dynamic tool selector stays a pure string expression.

Confidence Score: 4/5

Safe to merge after addressing the empty subscriber output in update_subscriber_attributes.

The new subscriber output added to update_subscriber_attributes will always contain zero-value defaults because the POST /attributes endpoint returns an empty 200 body — any downstream block reading output.subscriber.* fields silently receives empty strings and empty maps instead of real data.

apps/sim/tools/revenuecat/update_subscriber_attributes.ts — the subscriber output field and its declaration in the outputs spec should be removed or clearly documented as always-empty.

Important Files Changed

Filename Overview
apps/sim/tools/revenuecat/types.ts Adds shared helpers: throwIfRevenueCatError (clones response to parse error envelope), extractSubscriber (handles wrapped/unwrapped response shapes), extractCustomer, and shapeSubscriber. Types aligned to REST v1 spec.
apps/sim/tools/revenuecat/update_subscriber_attributes.ts Adds subscriber to the tool's output, but the POST /attributes endpoint returns an empty 200 body — the subscriber output will always contain zero-value defaults, making it misleading to downstream callers.
apps/sim/blocks/blocks/revenuecat.ts Coercions moved from tool to params to preserve dynamic refs; purchasePlatform correctly remapped to platform; extendByDays still has no required constraint for defer_google_subscription (runtime guard in the tool catches it).
apps/sim/tools/revenuecat/refund_google_subscription.ts URL corrected from /subscriptions/{productId}/refund to /transactions/{storeTransactionId}/refund per REST v1 spec. Param renamed accordingly.
apps/sim/tools/revenuecat/defer_google_subscription.ts Adds expiryTimeMs as an alternative to extendByDays; mutual-exclusion and at-least-one guards are correct; API fields use proper snake_case (expiry_time_ms, extend_by_days).
apps/sim/tools/revenuecat/create_purchase.ts platform made required (X-Platform header); presentedOfferingIdentifier, paymentMode, introductoryPrice, attributes, and updatedAtMs added per REST v1 spec; productId correctly made optional.

Sequence Diagram

sequenceDiagram
    participant Block as RevenueCat Block
    participant Params as params() transform
    participant Tool as Tool (e.g. create_purchase)
    participant RC as RevenueCat REST v1

    Block->>Params: raw UI fields (purchasePlatform, extendByDays, etc.)
    Params->>Tool: normalised params (platform, numbers coerced, storeTransactionId mapped)
    Tool->>RC: HTTP request (correct URL + X-Platform header)
    RC-->>Tool: "200 OK / 4xx {code, message}"
    Tool->>Tool: throwIfRevenueCatError(response.clone())
    Tool->>Tool: "response.json() -> extractSubscriber / extractCustomer"
    Tool-->>Block: "{ success, output: { subscriber, metadata, ... } }"
Loading

Reviews (3): Last reviewed commit: "fix(revenuecat): align tools with v1 doc..." | Re-trigger Greptile

Comment thread apps/sim/tools/revenuecat/get_customer.ts
Comment thread apps/sim/tools/revenuecat/grant_entitlement.ts
Comment thread apps/sim/blocks/blocks/revenuecat.ts
Comment thread apps/sim/tools/revenuecat/get_customer.ts
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

- Unwrap {value:{subscriber}} envelope across post-receipts, attributes, entitlements, and Google sub endpoints
- Trim entitlement output to documented fields (expires_date, grace_period_expires_date, product_identifier, purchase_date)
- Add subscriber output fields: last_seen, original_application_version, other_purchases, subscriber_attributes
- create_purchase: productId optional (Google-only required), add introductoryPrice, attributes, updated_at_ms; surface customer + subscriber
- update_subscriber_attributes: read response and surface subscriber
- defer_google_subscription: enforce XOR(extendByDays, expiryTimeMs) and 1-365 range
- get_customer: count active subs by expiry/refund instead of object-key length
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

Closing in favor of fresh branch with consolidated changes.

@waleedlatif1 waleedlatif1 deleted the waleedlatif1/validate-revenuecat branch May 7, 2026 05:12
Comment thread apps/sim/blocks/blocks/revenuecat.ts
Comment thread apps/sim/tools/revenuecat/defer_google_subscription.ts
Comment on lines 58 to 70
},

transformResponse: async (response, params) => {
await throwIfRevenueCatError(response)
const data = await response.json().catch(() => ({}))
const subscriber = shapeSubscriber(extractSubscriber(data))
return {
success: response.ok,
success: true,
output: {
updated: response.ok,
app_user_id: params?.appUserId ?? '',
updated: true,
app_user_id: subscriber.original_app_user_id || (params?.appUserId ?? ''),
subscriber,
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 subscriber output is always empty for this endpoint

RevenueCat's POST /v1/subscribers/{app_user_id}/attributes returns 200 OK with an empty body (the .catch(() => ({})) guard on line 61 exists precisely because .json() would throw on an empty body). This means extractSubscriber({}) returns {} and shapeSubscriber({}) fills every field with its zero-value default: first_seen: '', original_app_user_id: '', subscriptions: {}, entitlements: {}, etc.

Any downstream block reading output.subscriber.original_app_user_id or output.subscriber.entitlements will always receive empty data, silently. The pre-existing app_user_id output correctly falls back to params?.appUserId, but the new subscriber field cannot: there is no response body to populate it from. Removing subscriber from the output (and its declaration in the outputs spec) or documenting it as always-empty would prevent callers from relying on it.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit e999b64. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant