API Reference

Complete reference for the CroissantPay REST API. All endpoints require authentication.

Authentication

All API requests require authentication using an API key. Include your API key in theX-API-Keyheader.

Example Requestbash
curl -X GET "https://api.croissantlabs.com/v1/subscribers/user_123" \
  -H "X-API-Key: mx_live_your_api_key" \
  -H "Content-Type: application/json"

Important: Keep your API keys secure. Never expose them in client-side code. Use the public key (mx_public_*) for the SDK and the secret key (mx_live_*) for server-side requests.

Base URL

Cloud: https://api.croissantlabs.com/v1

Self-hosted: https://your-domain.com/api/v1

Error Handling

The API uses standard HTTP status codes and returns errors in a consistent JSON format.

Error Responsejson
{
  "error": "INVALID_RECEIPT",
  "message": "The receipt could not be validated",
  "code": 400
}

Common Error Codes

400

Bad Request

Invalid parameters or malformed request

401

Unauthorized

Missing or invalid API key

403

Forbidden

Insufficient permissions

404

Not Found

Resource not found

429

Rate Limited

Too many requests

500

Server Error

Internal server error

Receipts

Validate and process purchase receipts from the App Store and Google Play.

POST/receipts

Validate a purchase receipt and grant entitlements

Request Body

{
  "appUserId": "user_123",
  "platform": "ios",
  "receipt": "base64_encoded_receipt_data",
  "productId": "com.app.premium_monthly"
}

Response

{
  "success": true,
  "subscriber": {
    "id": "sub_abc123",
    "appUserId": "user_123",
    "entitlements": ["premium"],
    "activeSubscriptions": [{
      "productId": "com.app.premium_monthly",
      "expiresAt": "2024-02-15T00:00:00Z",
      "isActive": true
    }]
  }
}

Subscribers

Manage subscriber data, entitlements, and subscription status.

GET/subscribers/:appUserId

Get subscriber information including active entitlements

Response

{
  "subscriber": {
    "id": "sub_abc123",
    "appUserId": "user_123",
    "email": "user@example.com",
    "entitlements": {
      "premium": {
        "isActive": true,
        "expiresAt": "2024-02-15T00:00:00Z",
        "productId": "com.app.premium_monthly"
      }
    },
    "subscriptions": [{
      "productId": "com.app.premium_monthly",
      "status": "active",
      "platform": "ios",
      "expiresAt": "2024-02-15T00:00:00Z"
    }],
    "attributes": {
      "custom_key": "custom_value"
    }
  }
}
POST/subscribers/:appUserId/attributes

Update subscriber custom attributes

Request Body

{
  "attributes": {
    "referral_code": "FRIEND123",
    "signup_source": "website"
  }
}

Response

{
  "success": true,
  "attributes": {
    "referral_code": "FRIEND123",
    "signup_source": "website"
  }
}

Entitlements

Define what features users get access to with their purchases.

GET/entitlements

List all entitlements for the app

Response

{
  "entitlements": [
    {
      "id": "ent_123",
      "identifier": "premium",
      "displayName": "Premium Access",
      "description": "Full access to all premium features"
    },
    {
      "id": "ent_456",
      "identifier": "pro",
      "displayName": "Pro Features",
      "description": "Advanced features for power users"
    }
  ]
}
POST/entitlements/grant

Manually grant an entitlement to a subscriber

Request Body

{
  "appUserId": "user_123",
  "entitlementId": "premium",
  "expiresAt": "2024-12-31T23:59:59Z"
}

Response

{
  "success": true,
  "entitlement": {
    "identifier": "premium",
    "isActive": true,
    "expiresAt": "2024-12-31T23:59:59Z",
    "grantedManually": true
  }
}

Offerings

Configure which products to show users on your paywall.

GET/offerings

Get current offerings for the app

Response

{
  "current": {
    "id": "offering_default",
    "identifier": "default",
    "packages": [
      {
        "id": "pkg_monthly",
        "packageType": "MONTHLY",
        "product": {
          "id": "prod_123",
          "storeProductId": "com.app.premium_monthly",
          "price": 9.99,
          "priceString": "$9.99",
          "currencyCode": "USD",
          "title": "Premium Monthly",
          "description": "Full access, billed monthly"
        }
      },
      {
        "id": "pkg_annual",
        "packageType": "ANNUAL",
        "product": {
          "id": "prod_456",
          "storeProductId": "com.app.premium_annual",
          "price": 79.99,
          "priceString": "$79.99",
          "currencyCode": "USD",
          "title": "Premium Annual",
          "description": "Full access, billed yearly (save 33%)"
        }
      }
    ]
  },
  "all": {
    "default": { /* ... */ },
    "sale_offering": { /* ... */ }
  }
}

Products

Manage products that map to App Store and Google Play products.

GET/products

List all products for the app

Response

{
  "products": [
    {
      "id": "prod_123",
      "identifier": "premium_monthly",
      "displayName": "Premium Monthly",
      "type": "subscription",
      "storeProductIdApple": "com.app.premium_monthly",
      "storeProductIdGoogle": "premium_monthly",
      "entitlements": ["premium"]
    }
  ]
}
POST/products

Create a new product

Request Body

{
  "identifier": "premium_annual",
  "displayName": "Premium Annual",
  "type": "subscription",
  "storeProductIdApple": "com.app.premium_annual",
  "storeProductIdGoogle": "premium_annual",
  "entitlementIds": ["premium"]
}

Response

{
  "product": {
    "id": "prod_789",
    "identifier": "premium_annual",
    "displayName": "Premium Annual",
    "type": "subscription",
    "createdAt": "2024-01-15T10:00:00Z"
  }
}

Webhooks

Receive real-time notifications for subscription and purchase events.

Webhook Events

subscription.createdsubscription.renewedsubscription.cancelledsubscription.expiredpurchase.completedpurchase.refundedentitlement.grantedentitlement.revoked
Webhook Payload Examplejson
{
  "id": "evt_123456",
  "type": "subscription.renewed",
  "timestamp": "2024-01-15T10:30:00Z",
  "data": {
    "subscriber": {
      "appUserId": "user_123",
      "email": "user@example.com"
    },
    "subscription": {
      "productId": "com.app.premium_monthly",
      "platform": "ios",
      "expiresAt": "2024-02-15T00:00:00Z"
    },
    "revenue": {
      "amount": 9.99,
      "currency": "USD"
    }
  }
}

Signature Verification

All webhook requests include a signature in the x-croissantpay-signature header. Verify this signature to ensure the request is authentic.

Node.js Verificationjavascript
import { verifyWebhookSignature } from '@croissantpay/react-native/server';

app.post('/webhooks/croissantpay', (req, res) => {
  const signature = req.headers['x-croissantpay-signature'];
  const isValid = verifyWebhookSignature(
    req.body,
    signature,
    process.env.WEBHOOK_SECRET
  );

  if (!isValid) {
    return res.status(401).send('Invalid signature');
  }

  // Process the webhook
  const { type, data } = req.body;
  // ...
});

Rate Limits

API requests are rate limited based on your plan:

PlanRequests/minuteRequests/month
Free6010,000
Starter300100,000
Growth600500,000
Scale1,2002,000,000
Self-hostedUnlimitedUnlimited