Documentation

Learn how to integrate Drip metered billing into your application.

Introduction

What is Drip?

Drip is an on-chain metered billing platform built on Base using USDC. It enables businesses to charge customers for usage-based services with minimal trust assumptions and full transparency.

  • On-chain settlement: All charges are recorded on Base for full auditability
  • USDC payments: Stable, predictable pricing without crypto volatility
  • User-controlled funds: Customers hold their own funds via smart accounts
  • API-first: Simple REST API for recording usage and triggering charges

How It Works

1

Off-chain Metering

Your application records usage events via the Drip API. Events are stored off-chain for fast processing.

2

Usage Pricing

Usage is priced according to your pricing plans. Charges are calculated automatically.

3

On-chain Settlement

Charges are settled on-chain via session keys. Transactions are batched for gas efficiency.

Getting Started

Quick Start Guide

1. Create a Business Account

Sign up for Drip and create your business profile in the dashboard.

2. Get Your API Key

Navigate to API Keys and generate a new key. Store it securely.

# Your API key looks like this:
sk_live_a1b2c3d4e5f6g7h8i9j0...

3. Create a Customer

curl -X POST https://api.drip.dev/v1/customers \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "externalCustomerId": "user_123",
    "onchainAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f..."
  }'

4. Record Usage & Charge

curl -X POST https://api.drip.dev/v1/usage \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "customerId": "cus_abc123",
    "usageType": "api_call",
    "quantity": 100,
    "idempotencyKey": "unique-request-id"
  }'

Core Concepts

ERC-4337

Smart Accounts

Drip uses ERC-4337 smart accounts (DripAccount) for customer fund management. Unlike traditional custodial solutions, users maintain control of their own funds.

  • Users deposit USDC into their own smart account
  • Funds remain in the user's control until charged
  • Account abstraction enables gasless transactions for users
  • Compatible with existing EOA wallets via counterfactual deployment
Permissions

Session Keys

Session keys provide scoped, time-limited permissions for billing operations. They allow Drip to charge customers without requiring user signatures for each transaction.

  • Target scoping: Keys can only call specific contract addresses
  • Selector scoping: Keys are limited to specific function selectors
  • Time bounds: Keys expire after a configurable duration (e.g., 30 days)
  • Rate limits: maxPerCall and maxPerPeriod caps prevent excessive charges
  • Revocable: Users can revoke session keys at any time
Settlement

BillingModule

The BillingModule smart contract handles USDC custody and charge execution. It enforces all billing invariants on-chain.

  • Deposits: Users deposit USDC into their billing balance
  • Withdrawals: Users can withdraw available balance at any time
  • Charges: Authorized charges deduct from user balance
  • Events: All operations emit events for auditability
Idempotency

Replay Protection

Every usage event generates a unique usageId that prevents double-charging. This is enforced both off-chain and on-chain.

  • Each charge transaction includes the usageId
  • The BillingModule rejects duplicate usageIds
  • Use idempotencyKey for client-side deduplication
  • Charges can be queried and reconciled by usageId
Safety

Depeg Protection

Drip includes a circuit breaker that pauses billing operations if USDC depegs significantly from its $1 target. This protects both merchants and customers from unexpected value loss.

  • 5% threshold: Billing pauses if USDC/USD price deviates more than 5%
  • Chainlink oracle: Price feeds from decentralized oracles
  • Automatic resume: Operations resume when price stabilizes
  • Manual override: Operators can pause/unpause if needed

Integration Guide

Authentication

All API requests require authentication via Bearer token. Include your API key in the Authorization header.

curl -X GET https://api.drip.dev/v1/customers \
  -H "Authorization: Bearer sk_live_your_api_key_here"

Security tip: Never expose API keys in client-side code. Make API calls from your backend server only.

Creating Customers

Before charging a user, create a customer record linking their identity to their on-chain address.

interface CreateCustomerRequest {
  externalCustomerId?: string;  // Your internal user ID
  onchainAddress: string;       // 0x... Ethereum address
  metadata?: Record<string, any>;
}

// Example
const customer = await fetch('/v1/customers', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_live_...',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    externalCustomerId: 'user_123',
    onchainAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f...',
    metadata: { plan: 'pro', signupDate: '2024-01-15' }
  })
});

Recording Usage Events

Record usage events as they occur. Each event triggers a charge based on your pricing configuration.

interface RecordUsageRequest {
  customerId: string;      // Drip customer ID
  usageType: string;       // e.g., "api_call", "compute_minute"
  quantity: number;        // Must be positive
  idempotencyKey?: string; // Client-generated, max 64 chars
  metadata?: Record<string, any>;
}

// Synchronous charging (waits for on-chain confirmation)
const result = await fetch('/v1/usage', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer sk_live_...', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    customerId: 'cus_abc123',
    usageType: 'api_call',
    quantity: 100,
    idempotencyKey: 'req_' + Date.now()
  })
});

// Async charging (returns immediately, use webhooks for confirmation)
const asyncResult = await fetch('/v1/usage/async', {
  method: 'POST',
  // ... same body
});

Handling Webhooks

Subscribe to webhooks for real-time notifications about charges, balances, and other events.

// Register a webhook
await fetch('/v1/webhooks', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer sk_live_...', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    url: 'https://your-app.com/webhooks/drip',
    events: ['charge.succeeded', 'charge.failed', 'customer.balance.low']
  })
});

// Verify webhook signature (HMAC-SHA256)
const crypto = require('crypto');
const signature = req.headers['x-drip-signature'];
const expectedSig = crypto
  .createHmac('sha256', webhookSecret)
  .update(JSON.stringify(req.body))
  .digest('hex');
const isValid = crypto.timingSafeEqual(
  Buffer.from(signature),
  Buffer.from(expectedSig)
);

Error Handling

The API returns standard HTTP status codes and structured error responses.

StatusCodeDescription
401UNAUTHORIZEDInvalid or missing API key
402PAYMENT_REQUIREDInsufficient customer balance
403ACCOUNT_PAUSEDAccount paused due to low balance
404NOT_FOUNDResource not found
409DUPLICATE_CUSTOMERCustomer already exists
422VALIDATION_ERRORInvalid request parameters
429RATE_LIMIT_EXCEEDEDUsage cap or rate limit exceeded

Security Model

Trust-Minimized Architecture

Drip is designed to minimize trust requirements. Users maintain control of their funds at all times, and billing operations are constrained by on-chain logic.

User Controls

  • Users own their smart account
  • Users approve session key permissions
  • Users can revoke keys at any time
  • Users can withdraw funds at any time

On-chain Guarantees

  • Session key limits enforced by contract
  • Duplicate charges rejected on-chain
  • Balance checks prevent overdrafts
  • All operations emit verifiable events

Rate Limits & Caps

Multiple layers of rate limiting protect against runaway charges.

Limit TypeScopeDescription
maxPerCallSession KeyMaximum USDC per individual charge
maxPerPeriodSession KeyMaximum USDC per rolling time window
DAILY_CHARGE_LIMITCustomerMaximum charges per day per customer
SINGLE_CHARGE_LIMITCustomerMaximum amount for a single charge

Security Best Practices

  • Store API keys in environment variables, never in code
  • Use separate API keys for development and production
  • Rotate API keys periodically
  • Always verify webhook signatures before processing
  • Implement usage caps appropriate for your use case
  • Monitor the balance.low webhook to alert customers before charges fail
  • Use idempotencyKey for all usage recording to prevent duplicates

x402 Payment Protocol

NEW

What is x402?

x402 is a protocol for HTTP 402 Payment Required responses that enables micropayments for API access. When a client receives a 402 response, it can automatically handle payment and retry the request - perfect for AI agents and automated clients.

How x402 Works

1

Client Calls API

Client makes a normal API request to a protected endpoint.

2

Server Returns 402

If payment is required, server responds with 402 and X-Payment-* headers.

3

Client Signs Payment

Client uses a session key to sign the payment request via /v1/x402/sign.

4

Client Retries with Proof

Client retries the original request with X-Payment-* proof headers.

5

Server Verifies & Processes

Server verifies the payment signature and processes the request.

Response Headers (402)

When a 402 Payment Required is returned, these headers contain payment details:

HTTP/1.1 402 Payment Required
X-Payment-Required: true
X-Payment-Amount: 0.001000
X-Payment-Currency: USDC
X-Payment-Recipient: 0x742d35Cc6634C0532925a3b844Bc9e7595f...
X-Payment-Chain: base-sepolia
X-Payment-Description: Usage charge: api_call
X-Payment-Usage-Id: 550e8400-e29b-41d4-a716-446655440000
X-Payment-Expires: 1703001234567

Payment Proof Headers

After signing, include these headers when retrying the request:

POST /v1/usage HTTP/1.1
Authorization: Bearer sk_live_...
X-Payment-Signature: 0x1234...abcd
X-Payment-Session-Key: sk_session_123
X-Payment-Smart-Account: 0x742d35Cc6634C0532925a3b844Bc9e7595f...
X-Payment-Timestamp: 1703001234567

Signing Endpoint

Use the signing endpoint to create a payment signature:

// POST /v1/x402/sign
const response = await fetch('/v1/x402/sign', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    smartAccount: '0x742d35Cc6634C0532925a3b844Bc9e7595f...',
    sessionKeyId: 'sk_session_123',
    paymentRequest: {
      amount: '0.001000',
      recipient: '0x...',
      usageId: '550e8400-e29b-41d4-a716-446655440000',
      expiresAt: 1703001234567
    }
  })
});

const { signature, timestamp } = await response.json();

Use Cases

  • AI Agents: Autonomous agents can pay for API access without human intervention
  • Automated Clients: Scripts and bots can handle payment flows programmatically
  • Micropayments: Pay per request without subscription commitments
  • Multi-tenant Apps: Different users with different session key permissions

FAQ

What chains does Drip support?

Drip is deployed on Base L2 (mainnet) and Base Sepolia (testnet). Base provides low transaction fees and fast confirmation times, making it ideal for metered billing.

What happens if a user runs out of funds?

When a user's balance is too low for a charge, the API returns a 402 Payment Required error. You can subscribe to the customer.balance.low webhook to proactively notify users before this happens.

How are gas fees handled?

Users pay gas fees for deposits and withdrawals. For charges, Drip batches transactions and covers gas fees, passing a small portion to merchants as part of the settlement fee.

Can users revoke session keys?

Yes. Users can revoke session keys at any time through the dashboard or by calling the smart contract directly. Revoked keys immediately lose the ability to authorize charges.

Is there a minimum charge amount?

There is no minimum charge amount enforced by Drip. However, for very small charges, batching is recommended to optimize gas efficiency.

Next Steps