Skip to main content
Question

External Purchases API access for a Brazilian payment provider (Asaas): lifecycle mapping questions

  • Oct 29, 2026 9:05 PM UTC
  • 1 reply
  • 11 views

Forum|alt.badge.img

Hi RevenueCat team 👋

We run a subscription app (iOS + Android via RevenueCat) and also sell subscriptions on the web through Asaas, a Brazilian payment provider (credit card, Pix, boleto). It is not one of the supported Web billing engines, and switching to Stripe/Paddle isn't an option for us right now because of local payment methods and our partner-pricing setup.

What we do today: when an Asaas payment is confirmed, our backend grants a promotional entitlement via POST /v1/subscribers/{id}/entitlements/{entitlement}/promotional and stamps plan attributes on the customer. Access works, but web revenue doesn't show up in Charts (MRR, churn, trial conversion, LTV), so RevenueCat only covers half of our business.

We read the External Purchases API thread for Airwallex and would like to request access as well, for our production project and our staging project (we'd like to validate there first with environment: sandbox). Happy to share both project IDs privately via DM, just let me know who to send them to.

Our backend already keeps an idempotent ledger of every Asaas webhook (payment confirmed/received, overdue, refunded, subscription deleted), so we can post each status change and each payment. Before building it, we have some questions the public docs don't cover:

  1. Installments: our annual plan can be paid in installments on a credit card, so Asaas sends one charge per installment. Should we post one annual purchase with the full price, or one payment per installment? Which one keeps MRR/ARR correct in Charts?
  2. Currency: prices are in BRL. Can we send price + currency: BRL and have Charts convert it the same way it does for store purchases?
  3. Trials: we offer a 7-day trial on the web. Is a trial posted as an initial purchase with price 0 and then a separate conversion event, as other integrators describe?
  4. Refunds: do we post a negative amount, a refunded/expired status, or both?
  5. Migration: existing web subscribers currently have promotional grants. What is the recommended way to move them to external purchases without a gap in access or double-counting in Charts? Should we revoke the promotional entitlement right after posting the external purchase?
  6. Webhooks: we also consume RevenueCat webhooks. We assume events for these purchases arrive with store: EXTERNAL, so we can tell them apart from store events. Is that right?
  7. Plan changes: we have two plan tiers on the same entitlement. Since product changes aren't supported in the beta, is expiring the old subscription and posting a new one the recommended approach?
  8. Billing: does revenue tracked through the External Purchases API count toward our MTR the same way store revenue does?

Thanks a lot! Happy to share feedback on the beta as we integrate.

1 reply

matt-heaney
RevenueCat Staff
Forum|alt.badge.img+6
  • RevenueCat Staff
  • Oct 30, 2026 9:32 AM UTC

Hi there,

 

Thank you for the detailed write-up! I'm Matt from RevenueCat, and I'd love to help here.

 

I've gone through your questions, and I'm happy to confirm that Asaas should work with our External Purchases API.

 

To get started, please send your production and staging project IDs in a private message, and we'll enable the API for both. Please ensure this is sent via a private message, not in a public reply.

 

Once enabled, create an External Source under Project → Apps → New, then link each external product to the entitlement it should unlock.

 

You can find our API documentation here.

 


Installment payments

For annual subscriptions paid in installments, send one annual subscription with the full annual price in the initial payment.

 

RevenueCat calculates MRR based on the subscription period, so an annual subscription contributes price / 12 to MRR.

 

I'd avoid reporting each installment separately, as this could affect your revenue, churn, and renewal metrics. You can continue managing installment collections through Asaas. If a later installment isn't collected, report a negative payment for the uncollected amount.

 


Currency conversion

You can report payments directly in BRL:

"amount_in_local_currency": {
"gross": 199.9,
"currency": "BRL"
}

RevenueCat automatically converts this to USD using the exchange rate at processed_at. You can also provide tax and commission, or send amount_in_usd to use your own conversion instead.

 


Free trials

Trials are supported! Send the initial purchase with status: "trialing", gives_access: true, and payment: null.

 

When the trial converts, send a new active period with the first payment.

 

This generates an INITIAL_PURCHASE event for the trial, followed by a RENEWAL event when it converts.

 


Refunds and failed payments

Refunds are handled by posting a new payment with a negative gross amount and a unique payment_identifier.

 

If access should also end, update the subscription to status: "expired" and gives_access: false.

 

A negative payment that brings the period balance to zero generates a CANCELLATION event. Partial refunds update the balance but don't generate a separate refund event in the beta, so Charts may not update immediately.

 

For overdue payments, use in_grace_period to maintain access, or in_billing_retry with gives_access: false to suspend access while retrying.

 

One important detail: subscription expirations aren't automatic, so you'll need to report these yourself.

 


Migrating existing subscribers

You can migrate customers without double-counting revenue.

 

I'd recommend:

  1. Link the external product to the entitlement.

  2. Post the customer's current subscription with the full annual price.

  3. Confirm the external purchase grants access.

  4. Revoke the existing promotional grant.

 

This avoids any interruption to access.

 

Purchases older than 30 days are treated as historical backfill. They'll appear in Customer History and Charts, but won't trigger webhooks.

 


Webhooks

Yes! External purchases generate webhook events with store: EXTERNAL.

 

Sandbox events use environment: SANDBOX, and purchases older than 30 days won't trigger webhooks.

 


Plan changes

For upgrades and downgrades, keep the same source_subscription_identifier and create a new period with the updated product.

 

This generates a RENEWAL event rather than counting as a new subscription.

 

Dedicated product-change events aren't currently supported in the beta.

 


 

Billing and MTR

Production revenue reported through this API counts towards MTR, using gross revenue before tax and commission.

 

Sandbox transactions won't affect your production MTR or Charts, so you can safely test using environment: sandbox.

 


 

I hope this helps!

 

Once the API is enabled, I'd be happy to review a staging payload to make sure everything is working as expected.

 

If you have any additional questions, please let me know!

 

Thanks,