Skip to content

Applications and payment integration

Use einvoice as a billing backend for your own SaaS products. Create an application, define pricing plans, embed the payment widget, and receive signed webhooks on every transaction.

The Applications feature lets you:

  • Create applications representing your third-party SaaS products
  • Define pricing plans (recurring subscriptions or one-time payments)
  • Generate API keys to secure server-to-server calls
  • Configure webhooks to be notified of each payment
  • Embed the paywall SDK directly in your web pages
  • Monitor failed webhook deliveries for debugging

An application (or “app”) represents one of your SaaS products inside einvoice. When one of your customers pays via the paywall, einvoice:

  1. Creates the payment session under your application’s name
  2. Processes the payment via your payment gateway (Berexia)
  3. Issues an invoice to your customer (B2C or B2B)
  4. Sends a signed webhook to your URL so you can provision access
  1. Go to Company → Settings → Applications
  2. Click “Create an application”
  3. Fill in the form:
    • Name: display name of your SaaS (e.g. “My Application”)
    • Slug: short unique identifier (e.g. my-app) — used in API key prefixes
    • Webhook URL: your server URL to receive payment notifications
    • Success URL: page to redirect to after a successful payment (optional)
    • Cancel URL: return page if the user abandons checkout (optional)
  4. Click “Create”

Important — Copy the webhook secret immediately. After creation, the webhook secret is displayed only once. Copy it and store it securely (environment variable). It will not be accessible again.

API keys secure the communication between your server and the einvoice API. There are two types:

  • Prefix: ek_{slug}_
  • Scoped to a single application
  • Used server-side to create payment sessions
  • Recommended for integrating a specific application
  • Prefix: ck_{slug}_
  • Full access to all data in your account
  • Used for global integrations (e.g. internal management tools)
  • Use with caution — broader access
  • An API key is displayed only once at creation — copy it immediately
  • Never include an API key in frontend code or the client-side SDK
  • Store keys in server-side environment variables
  • Rotate your keys regularly
  1. In the application list, click “View keys” for the relevant application
  2. Click “Create key”
  3. Give the key a descriptive name (e.g. “Production”, “Node.js server”)
  4. Click “Create”
  5. Copy the displayed key immediately — it will not be visible after closing

Rotation generates a new key and keeps the old one active for 24 hours (grace period), giving you time to deploy the new key.

  1. On the key row, click “Rotate”
  2. Confirm the operation
  3. Retrieve the new key from the display box
  4. Update your environment variable
  5. The old key will be automatically invalidated after 24 hours

Revocation is immediate and irreversible. Any request using this key will be rejected.

  1. On the key row, click “Revoke”
  2. Confirm in the dialog box
  3. The key is disabled instantly

Use rotation (not revocation) if you want to replace a key without service interruption.

The webhook secret is used to verify the authenticity of notifications sent by einvoice to your server. It is automatically generated when you create an application.

If your secret is compromised, regenerate it:

  1. In the application view, click “Regenerate secret”
  2. Confirm the operation
  3. Copy the new secret immediately from the display
  4. Update your environment variable

Regeneration immediately invalidates the old secret. Webhooks that cannot be verified will be rejected by your server.

Your server must verify the signature of each webhook to reject fraudulent requests.

Headers sent by einvoice:

  • X-Einvoice-Event: event name (subscription.activated, payment.succeeded, subscription.renewed)
  • X-Einvoice-Signature: HMAC-SHA256 signature of the request body

Verification example (Node.js):

const sig = req.headers['x-einvoice-signature'];
const expected = crypto.createHmac('sha256', process.env.EINVOICE_WEBHOOK_SECRET)
.update(JSON.stringify(req.body)).digest('hex');
if (sig !== expected) return res.status(401).send('Invalid signature');

At the bottom of the Applications page, the “Failed deliveries” section lists webhooks that could not be delivered after 5 attempts (delays: immediate → 1 min → 5 min → 30 min → 2 h).

For each failed delivery, you will see:

  • The event concerned
  • The attempt number
  • The occurrence date
  • The associated external reference (your user identifier)

Make sure your webhook URL is publicly accessible and returns HTTP 200 for each event.

To display your application’s plans on your website, add the einvoice script:

Simple plan display:

<script src="https://app.einvoice.ma/paywall.js"
data-app="YOUR_APP_ID" data-target="#pricing">
</script>

Checkout with a server session: Your server first creates a payment session via the API, then passes the identifier to the SDK:

<script src="https://app.einvoice.ma/paywall.js"></script>
<script>
const paywall = new EinvoicePaywall({ app: 'YOUR_APP_ID' });
paywall.checkout(sessionId, '#pricing');
paywall.on('success', (data) => {
// data.subscription_id, data.plan_slug, data.external_ref
window.location.href = '/welcome';
});
</script>

The API key must never be included in frontend code. Buyer identity is set exclusively server-side when creating the session.

Share these resources with the technical team integrating einvoice:

  • Name keys by environment: “Production”, “Staging”, “CI” for easy rotation
  • Rotate keys regularly (every 90 days recommended)
  • Test webhooks with a tool like Webhook.site before going live
  • Monitor failed deliveries after every deployment of your server
  • Respond quickly (HTTP 200) to webhooks — einvoice waits less than 10 seconds for a response
  • Check that you are sending the X-API-Key: ek_... header in the request
  • Confirm the key is active (not revoked) in the key list
  • A key in rotation may still work for 24 hours — check the expiry date
  • Verify that the webhook URL is publicly accessible from the internet (not localhost)
  • Ensure your server returns HTTP 200 — any other code triggers a retry
  • Check the “Failed deliveries” section to identify the error
  • Make sure you are using the raw request body (not the parsed object)
  • In Node.js: use express.raw() or express.json() before the signature middleware
  • If the secret has changed (regenerated), update your environment variable
  • Verify that data-app matches your application identifier exactly
  • The /rpc/get_app_plans endpoint is public, no API key is needed client-side
  • Check the browser console for CORS or network errors

Need help? Contact our technical support.