> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# API Gateway Blueprint

> Send a usage event to Dodo Payments for each API call your service handles, then bill customers per call with a Count meter.

The API Gateway Blueprint sends a usage event to Dodo Payments for each API call your service handles, and a **Count** meter turns those events into a per-call charge for each customer. Use it to track API endpoint usage, to inform rate limits, and to bill for API usage. It ships in the `@dodopayments/ingestion-blueprints` npm package as `trackAPICall()`, which sends one event per call, and `createBatch()`, which queues events for high request volumes.

## Use Cases

The API Gateway Blueprint fits these scenarios:

<CardGroup cols={2}>
  <Card title="API-as-a-Service" icon="server">
    Track calls per customer on an API platform and charge by the number of calls.
  </Card>

  <Card title="Rate Limiting" icon="gauge">
    Record each customer's call volume to inform usage-based rate limits. The blueprint records usage but doesn't enforce limits.
  </Card>

  <Card title="Performance Monitoring" icon="chart-line">
    Record response times and status codes with each event, so error rates sit next to billing data.
  </Card>

  <Card title="Multi-Tenant SaaS" icon="users">
    Bill customers for their API consumption across different endpoints.
  </Card>
</CardGroup>

<Info>
  Every event needs the Dodo Payments customer ID of the customer you bill, which starts with `cus_`. Store it with your user record when you create the customer, and pass it as `customerId`.
</Info>

## Quick Start

To track API calls, install the package, create a meter, and send an event for each call.

<Steps>
  <Step title="Install the SDK">
    Install the Dodo Payments Ingestion Blueprints package:

    ```bash theme={null}
    npm install @dodopayments/ingestion-blueprints
    ```
  </Step>

  <Step title="Get Your API Keys">
    Create a Dodo Payments API key under **Developer → API Keys** in the [Dodo Payments dashboard](https://app.dodopayments.com/developer/api-keys), and store it in the `DODO_PAYMENTS_API_KEY` environment variable. Use a test mode key while you build. A test mode key works only with `test_mode`.
  </Step>

  <Step title="Create a Meter">
    In the [Dodo Payments dashboard](https://app.dodopayments.com/), go to **Products → Meters** and click **Create Meter**. Set these fields:

    * **Meter Name**: a descriptive name, such as `API Calls`.
    * **Event Name**: `api_call`, or a name you choose. It must match `eventName` in your code exactly (case-sensitive).
    * **Aggregation Type**: **Count**, to bill by the number of calls.
    * **Measurement Unit**: the unit shown on invoices, such as `calls`.

    To count only some calls, turn on **Enable Event Filtering** and add conditions on metadata keys such as `endpoint`, `method`, or `status_code`.
  </Step>

  <Step title="Track API Calls">
    Create one `Ingestion` instance with your API key and event name, then choose a pattern: one event per call, a batch for high volume, or Express.js middleware that tracks every request. In the middleware, `req.user` comes from your authentication middleware, and its `id` must be a Dodo Payments customer ID. Requests without a signed-in user are sent with the customer ID `anonymous`, which doesn't match any customer.

    <CodeGroup>
      ```javascript Single API Call theme={null}
      import { Ingestion, trackAPICall } from '@dodopayments/ingestion-blueprints';

      const ingestion = new Ingestion({
        apiKey: process.env.DODO_PAYMENTS_API_KEY,
        environment: 'test_mode',
        eventName: 'api_call'
      });

      // Track a single API call
      await trackAPICall(ingestion, {
        customerId: 'cus_123',
        metadata: {
          endpoint: '/api/v1/users',
          method: 'GET',
          status_code: 200,
          response_time_ms: 45
        }
      });
      ```

      ```javascript High-Volume with Batching theme={null}
      import { Ingestion, createBatch } from '@dodopayments/ingestion-blueprints';

      const ingestion = new Ingestion({
        apiKey: process.env.DODO_PAYMENTS_API_KEY,
        environment: 'live_mode',
        eventName: 'api_call'
      });

      // Create batch for high-volume tracking
      const batch = createBatch(ingestion, {
        maxSize: 100,      // Flush after 100 events
        flushInterval: 5000 // Or flush 5 seconds after the last add()
      });

      // Add API calls to batch
      batch.add({
        customerId: 'cus_123',
        metadata: {
          endpoint: '/api/v1/products',
          method: 'GET',
          status_code: 200
        }
      });

      // Clean up when done
      await batch.cleanup();
      ```

      ```javascript Express.js Middleware theme={null}
      import express from 'express';
      import { Ingestion, createBatch } from '@dodopayments/ingestion-blueprints';

      const app = express();

      const ingestion = new Ingestion({
        apiKey: process.env.DODO_PAYMENTS_API_KEY,
        environment: 'live_mode',
        eventName: 'api_call'
      });

      const batch = createBatch(ingestion, {
        maxSize: 50,
        flushInterval: 10000
      });

      // Middleware to track all API calls
      app.use((req, res, next) => {
        const startTime = Date.now();
        
        res.on('finish', () => {
          const responseTime = Date.now() - startTime;
          
          batch.add({
            // req.user is set by your auth middleware
            customerId: req.user?.id || 'anonymous',
            metadata: {
              endpoint: req.path,
              method: req.method,
              status_code: res.statusCode,
              response_time_ms: responseTime
            }
          });
        });
        
        next();
      });

      // Cleanup on shutdown
      process.on('SIGTERM', async () => {
        await batch.cleanup();
        process.exit(0);
      });
      ```
    </CodeGroup>
  </Step>
</Steps>

## Configuration

### Ingestion Configuration

Pass these options to `new Ingestion()`:

<ParamField path="apiKey" type="string" required>
  Your Dodo Payments API key from the dashboard.
</ParamField>

<ParamField path="environment" type="string">
  Environment mode: `test_mode` or `live_mode`. Defaults to `test_mode`. The Dodo Payments SDKs default to `live_mode` instead, so set `live_mode` explicitly in production.
</ParamField>

<ParamField path="eventName" type="string" required>
  Event name that matches your meter's **Event Name** (case-sensitive). Every event this instance sends uses it.
</ParamField>

### Track API Call Options

Pass these options to `trackAPICall()` and `batch.add()`:

<ParamField path="customerId" type="string" required>
  The Dodo Payments customer ID to bill for the call, for example `cus_123`.
</ParamField>

<ParamField path="metadata" type="object">
  Optional metadata about the API call, such as endpoint, method, status code, and response time. Each value must be a string, number, or boolean. The API rejects nested objects, arrays, and `null` values.
</ParamField>

### Batch Configuration

`createBatch(ingestion, options)` queues events in memory and returns an object with three methods: `add()` queues an event, `flush()` sends the queued events, and `cleanup()` sends them and stops the timer. A flush sends one ingest request per event, in parallel.

<ParamField path="maxSize" type="number">
  Number of queued events that triggers an immediate flush. Default: `100`.
</ParamField>

<ParamField path="flushInterval" type="number">
  Milliseconds to wait after the most recent `add()` before the batch flushes. Each `add()` restarts the timer. Default: `5000` (5 seconds).
</ParamField>

## Best Practices

<Tip>
  **Use Batching for High Volume**: For high-traffic applications, use `createBatch()`. `batch.add()` returns immediately, so tracking doesn't add latency to your request handler.
</Tip>

A batch holds events in memory until it flushes, and it doesn't retry events that fail to send. An automatic flush logs the error with `console.error`. A call to `flush()` or `cleanup()` throws it.

<Warning>
  **Clean Up Batches on Shutdown**: Call `batch.cleanup()` when your application shuts down, so pending events are flushed instead of lost.
</Warning>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.