Skip to content

Verify entitlements on your server

Client SDKs are for selling and for showing the right UI. The decision to serve paid content belongs to your server, which holds the private key and cannot be tampered with by a jailbroken device or a browser console.

TypeScript:

import { OrcaServerClient } from '@maxint/orca-sdk'
const orca = new OrcaServerClient(process.env.ORCA_API_KEY!)
app.get('/premium-content', async (req, res) => {
const active = await orca.getActiveEntitlements(req.user.email, 'prod')
const hasAccess = active.some((e) => e.entitlement_id === 'pro_tier')
if (!hasAccess) return res.status(402).send('Subscribe to access this.')
res.json({ content: '...' })
})

Go:

client, err := orca.NewOrcaServerClient("your_api_key_here")
active, err := client.GetActiveEntitlements(ctx, email, orca.EnvironmentProduction)
for _, e := range active {
if e.Id == "pro_tier" { /* grant */ }
}

Every SDK identifies the customer by email. The email your client passes to identify() must be the same string your server passes to getActiveEntitlements(). Normalise case and whitespace in one place, before either call.

A live call on every request is the simplest correct design. If you cache:

  • Key the cache by email and environment.
  • Invalidate on every verified webhook (see Webhooks).
  • Put an upper bound on cache age (minutes, not days) so a missed webhook cannot grant access indefinitely.
  • Decide per feature whether to fail open (serve cached access when Orca is unreachable) or fail closed. Write that decision down.
const customer = await orca.getCustomerInfo('user@example.com', 'prod')
const { customers, cursor } = await orca.listCustomers(20)
await orca.cancelStripeSubscription('prod', 'entitlement_id', 'user@example.com')
await orca.cancelGocardlessSubscription('prod', 'entitlement_id', 'user@example.com')

App Store and Google Play subscriptions are cancelled by the customer in the store’s own settings; the client SDKs expose the management URLs for you to link to.

  • The private key lives only on the server.
  • One canonical email normalisation function used by client and server.
  • Paid endpoints call getActiveEntitlements or read a cache that webhooks invalidate.
  • A written fail-open / fail-closed policy per feature.