PayEngine Logo

PayEngine

by metronomiQ

Overview

Welcome to the Metronomiq API documentation. Build time-based payment solutions with Lightning Network integration.

Lightning Network Integration

Native Lightning support with millisatoshi precision

Time-Based Payments

Stream payments by the second via WebSocket

Base URLs

Production: https://payengine.metronomiq.io/api
Test: https://payengine-test.metronomiq.io/api

⚠️ Note: The test environment runs on Bitcoin Regtest and Lightning Network Regtest for development and testing purposes.

Authentication

All API requests require authentication using your API key.

Authentication Header

x-api-key: your_api_key_here

Example Request

curl -X GET https://payengine.metronomiq.io/users \
  -H "  : your_api_key_here"

API Key Rotation

For security, rotate your API key regularly. Use both old and new keys during the rotation process.

curl -X POST https://payengine.metronomiq.io/applications/rotate-key \
  -H "Authorization: RotateKey your_rotate_key"

Application Setup

Configure your application for PayEngine integration.

Set Public Key

PATCH /applications/public-key

Required for WebSocket Streaming

You must upload your public key before using WebSocket streaming. PayEngine uses this to verify JWT tokens generated with your private key.

Upload your RSA public key in PEM format.

Request

{
  "publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...\n-----END PUBLIC KEY-----"
}

Response

200 OK

Set Webhook URL

PATCH /applications/webhook-url

Configure the URL where PayEngine will send webhook notifications.

Request

{
  "url": "https://your-app.com/webhooks/payengine"
}

Response

200 OK

Refresh Webhook Secret

GET /applications/refresh-webhook-secret

Generate a new webhook signing secret for security.

Response

200 OK
{
  "newWebhookSecret": "new_webhook_secret"
}

Rotate API Key

POST /applications/rotate-key

Generate a new API key for enhanced security. Use the Authorization header with your rotate key.

Headers

Authorization: RotateKey your_rotate_key

Response

200 OK
{
  "newApiKey": "pe_prod_abc123..."
}

User Management

Manage users within your application.

Overview

What is a User?

A User in PayEngine represents an individual within your application's ecosystem who can send and receive payments. Each user gets their own managed Lightning wallet hosted by PayEngine.

External ID

The externalId is your unique identifier for this user in your system. This allows you to map PayEngine users to users in your database.

Managed Wallet

Each user automatically gets a Lightning wallet managed by PayEngine. You don't need to handle private keys or Lightning complexity.

Instant Payments

Users can send and receive Lightning payments instantly with millisatoshi precision. Perfect for micropayments and streaming money.

Create User

POST /users

Create a new user with an internal wallet.

Request

{
  "externalId": "user_123"
}

Response

201 Created
{
  "id": "user-uuid-here",
  "externalId": "user_123",
  "feePercent": 10,
  "applicationId": "application-uuid-here",
  "walletId": "wallet-uuid-here"
}

Get All Users

GET /users

List all users in your application.

Response

200 OK
[
  {
    "id": "user-uuid-here",
    "externalId": "user_123",
    "feePercent": 10,
    "applicationId": "application-uuid-here",
    "walletId": "wallet-uuid-here"
  },
  {
    "id": "user-uuid-2-here",
    "externalId": "user_456", 
    "feePercent": 15,
    "applicationId": "application-uuid-here",
    "walletId": "wallet-uuid-2-here"
  }
]

Get User

GET /users/{id}

Get a specific user by their external ID.

Path Parameters

id: User external ID (e.g., "user_123")

Response

200 OK
{
  "id": "user-uuid-here",
  "externalId": "user_123",
  "feePercent": 10,
  "applicationId": "application-uuid-here",
  "walletId": "wallet-uuid-here"
}

Tipping

POST /users/{id}/tip

Send a tip from one user to another user.

Path Parameters

id: User external ID of the sender (e.g., "user_123")

Request

{
  "toUserId": "user_456",
  "amount": 1000,
  "currency": "SAT"
}

Request Body Parameters

  • toUserId (string, required) - External ID of the recipient user
  • amount (number, required) - Amount to tip in satoshis
  • currency (string, required) - Must be "SAT"

Response

201 Created
{
  "success": true,
  "transactionId": "transaction-uuid-here",
  "fromUserId": "user_123",
  "toUserId": "user_456",
  "amount": 1000,
  "currency": "SAT"
}

Create Deposit Invoice

POST /users/{id}/deposit

Generate a Lightning invoice for user deposits.

Path Parameters

id: User external ID (e.g., "user_123")

Request

{
  "amount": 1000
}

Response

201 Created
{
  "id": "deposit-uuid-here",
  "paymentHash": "payment-hash-here",
  "request": "lnbc1000...",
  "amountSat": "1000",
  "amountMsat": "1000000",
  "description": "Deposit for user user_123",
  "status": "PENDING",
  "expiresAt": "2024-01-01T12:30:00Z"
}

Status Values

  • PENDING - Invoice created, waiting for payment
  • PAID - Invoice has been paid successfully
  • EXPIRED - Invoice has expired without payment

Preview Withdrawal

POST /users/{id}/withdraw/preview

Preview fees and check balance before withdrawal.

Path Parameters

id: User external ID (e.g., "user_123")

Request

{
  "invoice": "lnbc1000n1pwg..."
}

Response

200 OK
{
  "invoiceAmountMsat": "1000000",
  "invoiceAmountSat": "1000",
  "estimatedFeeMsat": "1001",
  "estimatedFeeSat": "1",
  "totalRequiredMsat": "1001001",
  "totalRequiredSat": "1001",
  "currentBalanceMsat": "45900",
  "currentBalanceSat": "45",
  "hasSufficientFunds": false,
  "description": "Payment for services",
  "destination": "02152fe11f478063aab5a324d0c244b268205d1edd577b0bd95f4c935b5ff71966",
  "expiresAt": "2025-09-05T21:35:17.000Z"
}

Execute Withdrawal

POST /users/{id}/withdraw

Pay a Lightning invoice on behalf of a user.

Path Parameters

id: User external ID (e.g., "user_123")

Request

{
  "invoice": "lnbc1000n1pwg..."
}

Response

200 OK
{
  "paymentHash": "payment-hash-here",
  "amountMsat": "1000000",
  "feeMsat": "1000",
  "totalDebitedMsat": "1001000",
  "estimatedFeeMsat": "800",
  "actualFeeMsat": "1000",
  "confirmedAt": "2024-01-01T12:00:00Z"
}

Get Balance

GET /users/{id}/balance

Check a user's wallet balance.

Path Parameters

id: User external ID (e.g., "user_123")

Response

200 OK
{
  "balance": {
    "balanceMsat": "5000000",
    "balanceSat": "5000"
  }
}

Get Deposit Status

GET /users/{id}/deposit/{paymentHash}/status

Check the status of a deposit invoice.

Path Parameters

id: User external ID (e.g., "user_123")
paymentHash: Payment hash from deposit invoice

Response

200 OK
When deposit exists (PENDING/PAID):
{
  "status": "PAID",
  "amountMsat": "1000000",
  "amountSat": "1000",
  "description": "Deposit for user user_123",
  "expiresAt": "2024-01-01T12:30:00Z",
  "createdAt": "2024-01-01T12:00:00Z",
  "walletId": "wallet-uuid-here"
}
When deposit is expired:
{
  "status": "EXPIRED",
  "amountMsat": "1000000",
  "expiresAt": "2024-01-01T12:30:00Z"
}
When deposit not found:
{
  "status": "NOT_FOUND"
}

Response Fields

  • status - Always present
  • amountMsat? - Present when status is PENDING, PAID, or EXPIRED
  • amountSat? - Present when status is PENDING or PAID
  • description? - Present when status is PENDING or PAID
  • expiresAt? - Present when status is PENDING, PAID, or EXPIRED
  • createdAt? - Present when status is PENDING or PAID
  • walletId? - Present when status is PENDING or PAID

Note: Fields marked with ? are optional and may not be present in all responses.

Status Values

  • PENDING - Invoice created, waiting for payment
  • PAID - Invoice has been paid successfully
  • EXPIRED - Invoice has expired without payment
  • NOT_FOUND - Payment hash not found

Update User

PATCH /users/{id}

Update a user's external ID.

Path Parameters

id: Current user external ID (e.g., "user_123")

Request

{
  "updatedExternalId": "user_456", //optional
  "feePercent": 10, //optional
  "tipFeePercent": 10 //optional
}

Response

200 OK
{
  "id": "user-uuid-here",
  "externalId": "user_456",
  "feePercent": 10,
  "applicationId": "application-uuid-here",
  "walletId": "wallet-uuid-here"
}

Delete User

DELETE /users/{id}

Delete a user and their associated wallet.

Path Parameters

id: User external ID (e.g., "user_123")

Response

200 OK
{
  "id": "user-uuid-here",
  "externalId": "user_123",
  "feePercent": 10,
  "applicationId": "application-uuid-here",
  "walletId": "wallet-uuid-here"
}

Payment Policies

Define time-based payment rules.

Overview

What is a Payment Policy?

A Payment Policy defines the rules for time-based streaming payments. It specifies how much a user should pay, to whom, and at what frequency. Think of it as a "subscription template" that can be used multiple times.

Receiver

The externalUserId specifies which user will receive the payments. This must be an existing user's externalId.

Payment Rate

Combine amount, stepValue, and stepUnit to define the rate. Example: 100 sats every 5 seconds = pay 20 sats/second.

Use Cases

Perfect for streaming content, live sessions, pay-per-minute services, or any time-based monetization model.

Pro Tip

Create different policies for different content types or pricing tiers. You can reuse the same policy across multiple streaming sessions.

Create Payment Policy

POST /payment-policies

Create a new payment policy.

Request

{
  "externalUserId": "user_123",
  "name": "policy_premium_video",
  "amount": 1,
  "stepValue": 5,
  "stepUnit": "SECONDS"
}

Response

201 Created
{
  "id": "policy-uuid-here",
  "userId": "user-uuid-here",
  "name": "policy_premium_video",
  "amount": 1,
  "stepValue": 5,
  "currency": "SATS",
  "stepUnitId": "step-unit-uuid-here",
  "createdAt": "2024-01-01T12:00:00Z"
}

Get All Payment Policies

GET /payment-policies

Retrieve all payment policies in your application.

Response

200 OK
[
  {
    "id": "policy-uuid-here",
    "userId": "user-uuid-here",
    "name": "policy_premium_video",
    "amount": 1,
    "stepValue": 5,
    "currency": "SATS",
    "stepUnitId": "step-unit-uuid-here",
    "createdAt": "2024-01-01T12:00:00Z",
    "stepUnit": {
      "id": "step-unit-uuid-here",
      "name": "SECONDS",
      "unitTypeId": "unit-type-uuid-here",
      "unitType": {
        "id": "unit-type-uuid-here",
        "name": "TIME"
      }
    }
  },
  {
    "id": "policy-uuid-2-here",
    "userId": "user-uuid-2-here",
    "name": "policy_music_stream",
    "amount": 2,
    "stepValue": 10,
    "currency": "SATS",
    "stepUnitId": "step-unit-uuid-here",
    "createdAt": "2024-01-01T13:00:00Z",
    "stepUnit": {
      "id": "step-unit-uuid-here",
      "name": "SECONDS",
      "unitTypeId": "unit-type-uuid-here",
      "unitType": {
        "id": "unit-type-uuid-here",
        "name": "TIME"
      }
    }
  }
]

Get Payment Policy

GET /payment-policies/{id}

Get a specific payment policy by its ID.

Path Parameters

id: Payment policy UUID

Response

200 OK
{
  "id": "policy-uuid-here",
  "userId": "user-uuid-here",
  "name": "policy_premium_video",
  "amount": 1,
  "stepValue": 5,
  "currency": "SATS",
  "stepUnitId": "step-unit-uuid-here",
  "createdAt": "2024-01-01T12:00:00Z",
  "stepUnit": {
    "id": "step-unit-uuid-here",
    "name": "SECONDS",
    "unitTypeId": "unit-type-uuid-here",
    "unitType": {
      "id": "unit-type-uuid-here",
      "name": "TIME"
    }
  }
}

Get Policies for User

GET /payment-policies/users/{id}

Get all payment policies for a specific user (where they are the receiver).

Path Parameters

id: User external ID (e.g., "user_123")

Response

200 OK
[
  {
    "id": "policy-uuid-here",
    "userId": "user-uuid-here",
    "name": "policy_premium_video",
    "amount": 1,
    "stepValue": 5,
    "currency": "SATS",
    "stepUnitId": "step-unit-uuid-here",
    "createdAt": "2024-01-01T12:00:00Z",
    "stepUnit": {
      "id": "step-unit-uuid-here",
      "name": "SECONDS",
      "unitTypeId": "unit-type-uuid-here",
      "unitType": {
        "id": "unit-type-uuid-here",
        "name": "TIME"
      }
    },
    "_count": {
      "resources": 0
    }
  }
]

Get Policy for Resource

GET /payment-policies/resources/{id}

Get the payment policy associated with a specific resource.

Path Parameters

id: Resource external ID (e.g., "video_123")

Response

200 OK
{
  "id": "policy-uuid-here",
  "userId": "user-uuid-here",
  "name": "policy_premium_video",
  "amount": 1,
  "stepValue": 5,
  "currency": "SATS",
  "stepUnitId": "step-unit-uuid-here",
  "createdAt": "2024-01-01T12:00:00Z",
  "stepUnit": {
    "id": "step-unit-uuid-here",
    "name": "SECONDS",
    "unitTypeId": "unit-type-uuid-here",
    "unitType": {
      "id": "unit-type-uuid-here",
      "name": "TIME"
    }
  }
}

Update Payment Policy

PATCH /payment-policies/{id}

Update an existing payment policy.

Path Parameters

id: Payment policy UUID

Request

{
  "name": "policy_updated_name",
  "amount": 10,
  "stepValue": 1,
  "stepUnit": "SECONDS"
}

Response

200 OK
{
  "id": "policy-uuid-here",
  "userId": "user-uuid-here",
  "name": "policy_updated_name",
  "amount": 10,
  "stepValue": 1,
  "currency": "SATS",
  "stepUnitId": "step-unit-uuid-here",
  "createdAt": "2024-01-01T12:00:00Z"
}

Delete Payment Policy

DELETE /payment-policies/{id}

Delete a payment policy. Cannot be deleted if it's being used by resources.

Path Parameters

id: Payment policy UUID

Response

200 OK
{
  "id": "policy-uuid-here",
  "userId": "user-uuid-here",
  "name": "policy_premium_video",
  "amount": 1,
  "stepValue": 5,
  "currency": "SATS",
  "stepUnitId": "step-unit-uuid-here",
  "createdAt": "2024-01-01T12:00:00Z"
}

Resources Management

Manage billable resources and content in your application.

Overview

What is a Resource?

A Resource represents any billable content or service in your application - like a video, music track, article, live stream, or API endpoint. Resources are linked to payment policies to enable time-based monetization.

External Resource ID

The externalId is your unique identifier for this resource in your system. This allows you to map PayEngine resources to content in your database.

Payment Policy Link

Each resource is linked to a payment policy that defines how users are charged when accessing this resource.

Examples

Video streaming, music playback, article reading, API usage, live streaming, or any time-based service.

🚀 Best Practice: Naming Convention

Include the resource type in your externalId for better organization:

  • track_12345 - for music tracks
  • video_67890 - for videos
  • stream_abc123 - for live streams
  • article_xyz789 - for articles

Get Policies for Resources

POST /resources/policies

Get payment policies for multiple resources by their external IDs.

Request

{
  "resourceIds": [
    "video_12345",
    "track_67890",
    "stream_abc123"
  ]
}

Response

200 OK
[
  {
    "externalResourceId": "video_12345",
    "policy": {
      "id": "policy-uuid-here",
      "name": "policy_premium_video",
      "amount": 1,
      "stepValue": 5,
      "currency": "SATS",
      "stepUnit": {
        "id": "step-unit-uuid-here",
        "name": "SECONDS",
        "unitTypeId": "unit-type-uuid-here"
      }
    }
  },
  {
    "externalResourceId": "track_67890",
    "policy": {
      "id": "policy-uuid-2-here",
      "name": "policy_music_stream",
      "amount": 2,
      "stepValue": 10,
      "currency": "SATS",
      "stepUnit": {
        "id": "step-unit-uuid-here",
        "name": "SECONDS",
        "unitTypeId": "unit-type-uuid-here"
      }
    }
  }
]

Link Resource to Policy

POST /resources

Link a resource to a payment policy for monetization.

Request

{
  "externalResourceId": "video_12345",
  "policyId": "policy-uuid-here"
}

Response

201 Created
{
  "externalResourceId": "video_12345",
  "policyId": "policy-uuid-here"
}

Update Resource Policy

PATCH /resources/{id}

Update the payment policy associated with a resource.

Path Parameters

id: Resource external ID (e.g., "video_12345")

Request

{
  "externalResourceId": "video_12345",
  "policyId": "policy-uuid-new-here"
}

Response

200 OK
{
  "externalResourceId": "video_12345",
  "policyId": "policy-uuid-new-here"
}

Delete Resource

DELETE /resources/{id}

Remove a resource from monetization. This unlinks it from its payment policy.

Path Parameters

id: Resource external ID (e.g., "video_12345")

Response

200 OK
{
  "externalResourceId": "video_12345",
  "policyId": "policy-uuid-here"
}

Units

Understanding the time units used in payment policies.

Overview

Understanding Unit Types & Step Units

Payment policies use a two-level system to define time-based billing intervals. This system provides flexibility and standardization for various monetization models.

Unit Type

The Unit Type represents the category of measurement used for billing intervals. Currently, TIME is the primary unit type, focusing on temporal-based payments.

Step Unit

The Step Unit defines the specific increment within a Unit Type. For the TIME unit type, step units include SECONDS, MINUTES, and HOURS.

Available Step Units

Current step units available for the TIME unit type:

SECONDS

Perfect for real-time streaming content like videos, music, or live streams.

stepUnit: "SECONDS"

MINUTES

Ideal for services billed per minute, like voice calls or consultations.

stepUnit: "MINUTES"

HOURS

Best for hourly services, professional consultations, or long-term access.

stepUnit: "HOURS"

Get All Unit Types

GET /units

Retrieve all available unit types with their associated step units.

Response

200 OK
[
  {
    "id": "unit-type-uuid-here",
    "name": "TIME",
    "units": [
      {
        "id": "step-unit-uuid-1-here",
        "name": "SECONDS"
      },
      {
        "id": "step-unit-uuid-2-here", 
        "name": "MINUTES"
      },
      {
        "id": "step-unit-uuid-3-here",
        "name": "HOURS"
      }
    ]
  }
]

Get Step Units by Unit Type

GET /units/{name}/steps

Get all step units for a specific unit type.

Path Parameters

name: Unit type name (e.g., "TIME")

Response

200 OK
[
  {
    "id": "step-unit-uuid-1-here",
    "name": "SECONDS"
  },
  {
    "id": "step-unit-uuid-2-here",
    "name": "MINUTES"
  },
  {
    "id": "step-unit-uuid-3-here",
    "name": "HOURS"
  }
]

Step Unit Data Structure

When retrieving payment policies, step units are returned as nested objects with their associated unit type information:

Example Step Unit Object in Policy

{
  "stepUnit": {
    "id": "step-unit-uuid-here",
    "name": "SECONDS",
    "unitTypeId": "unit-type-uuid-here",
    "unitType": {
      "id": "unit-type-uuid-here",
      "name": "TIME"
    }
  }
}
💡 Integration Tip

When creating payment policies, you only need to specify the stepUnit string (e.g., "SECONDS"). The API will automatically resolve the full structure with IDs and relationships.

Webhook Events

Receive real-time notifications.

Event Types

SESSION_STARTED

A new payment session has started

TICK

A payment tick has occurred

SESSION_PAUSED

Session has been paused

SESSION_ENDED

Session has ended

Webhook Payload Example

{
  "event": "TICK",
  "sessionId": "session-uuid",
  "payerId": "user_123",
  "policyId": "policy-uuid",
  "timestamp": "2024-01-01T12:00:00Z",
  "paidDelta": 1
}

Debit Events

Track and retrieve payment debit events for users and resources.

Overview

What is a Debit Event?

A Debit Event represents a payment transaction that occurred during a streaming session. Each debit event tracks the amount debited, the associated policy, resource, and the completion status of the transaction.

Transaction Tracking

Each event includes session ID, amount, status (PENDING, SUCCESS, FAILED), and timestamps for creation and completion.

Policy Association

Events are linked to payment policies, allowing you to track which policy triggered each debit.

Date Range Filtering

Query debit events within specific date ranges based on completion timestamps for detailed analytics.

Use Cases

Perfect for generating reports, tracking user spending, auditing transactions, and analyzing resource usage patterns.

Get Debit Events by User

GET /debit-events/users/:externalUserId

Retrieve all debit events for a specific user with optional date range filtering.

Path Parameters

externalUserId The external ID of the user

Query Parameters

dateFrom optional Start date for filtering (ISO 8601 format)
dateTo optional End date for filtering (ISO 8601 format)

Response

200 OK
[
  {
    "id": "debit-event-uuid-1",
    "sessionId": "session-uuid-1",
    "amount": 100,
    "status": "SUCCESS",
    "createdAt": "2024-01-15T10:00:00Z",
    "completedAt": "2024-01-15T10:00:01Z",
    "policyId": "policy-uuid",
    "resourceId": "resource-id-1",
    "policy": {
      "id": "policy-uuid",
      "name": "Premium Video Stream",
      "amount": 1,
      "stepValue": 5,
      "currency": "SATS",
      "user": {
        "id": "user-uuid",
        "externalId": "user_123"
      },
      "stepUnit": {
        "id": "step-unit-uuid",
        "name": "SECONDS",
        "unitTypeId": "unit-type-uuid",
        "unitType": {
          "name": "TIME"
        }
      }
    }
  },
  {
    "id": "debit-event-uuid-2",
    "sessionId": "session-uuid-2",
    "amount": 50,
    "status": "SUCCESS",
    "createdAt": "2024-01-20T14:30:00Z",
    "completedAt": "2024-01-20T14:30:01Z",
    "policyId": "policy-uuid-2",
    "resourceId": "resource-id-2",
    "policy": {
      "id": "policy-uuid-2",
      "name": "Standard Audio Stream",
      "amount": 1,
      "stepValue": 10,
      "currency": "SATS",
      "user": {
        "id": "user-uuid",
        "externalId": "user_123"
      },
      "stepUnit": {
        "id": "step-unit-uuid",
        "name": "SECONDS",
        "unitTypeId": "unit-type-uuid",
        "unitType": {
          "name": "TIME"
        }
      }
    }
  }
]

Get Debit Events by Resource

GET /debit-events/resources/:resourceId

Retrieve all debit events for a specific resource with optional date range filtering.

Path Parameters

resourceId The ID of the resource

Query Parameters

dateFrom optional Start date for filtering (ISO 8601 format)
dateTo optional End date for filtering (ISO 8601 format)

Response

200 OK
[
  {
    "id": "debit-event-uuid-3",
    "sessionId": "session-uuid-3",
    "amount": 200,
    "status": "SUCCESS",
    "createdAt": "2024-01-10T09:15:00Z",
    "completedAt": "2024-01-10T09:15:01Z",
    "policyId": "policy-uuid",
    "resourceId": "video_stream_001",
    "policy": {
      "id": "policy-uuid",
      "name": "Premium Video Stream",
      "amount": 2,
      "stepValue": 1,
      "currency": "SATS",
      "user": {
        "id": "user-uuid",
        "externalId": "content_creator_456"
      },
      "stepUnit": {
        "id": "step-unit-uuid",
        "name": "SECONDS",
        "unitTypeId": "unit-type-uuid",
        "unitType": {
          "name": "TIME"
        }
      }
    }
  },
  {
    "id": "debit-event-uuid-4",
    "sessionId": "session-uuid-4",
    "amount": 150,
    "status": "FAILED",
    "createdAt": "2024-01-12T11:20:00Z",
    "completedAt": "2024-01-12T11:20:02Z",
    "policyId": "policy-uuid",
    "resourceId": "video_stream_001",
    "policy": {
      "id": "policy-uuid",
      "name": "Premium Video Stream",
      "amount": 2,
      "stepValue": 1,
      "currency": "SATS",
      "user": {
        "id": "user-uuid",
        "externalId": "content_creator_456"
      },
      "stepUnit": {
        "id": "step-unit-uuid",
        "name": "SECONDS",
        "unitTypeId": "unit-type-uuid",
        "unitType": {
          "name": "TIME"
        }
      }
    }
  }
]

Error Responses

404 Not Found
User or resource not found
{
  "error": "USER_NOT_FOUND",
  "message": "User not found"
}
400 Bad Request
Invalid date format
{
  "error": "INVALID_DATE_FORMAT",
  "message": "Date must be in ISO 8601 format (YYYY-MM-DDTHH:mm:ssZ)"
}

WebSocket Streaming

Real-time streaming payments using WebSocket connections.

Overview

WebSocket streaming allows real-time payment streaming based on time. Your application connects to PayEngine's WebSocket server to start, pause, resume, and stop payment streams between users according to your payment policies.

Prerequisites

  • Public key uploaded via PATCH /applications/public-key
  • Valid webhook URL configured
  • JWT token generated with your private key
  • Payment policy and user created

Setup Process

1

Upload Public Key

Upload your RSA public key so PayEngine can verify JWT tokens signed with your private key.

PATCH /applications/public-key
Content-Type: application/json

{
  "publicKey": "-----BEGIN PUBLIC KEY-----\n..."
}
2

Configure Webhook URL

Set your webhook URL to receive payment event notifications.

PATCH /applications/webhook-url
Content-Type: application/json

{
  "webhookUrl": "https://your-app.com/webhooks/payengine"
}
3

Generate JWT Token

Generate a JWT token using your private key for WebSocket authentication.

// Example JWT generation
const jwt = require('jsonwebtoken');

const payload = {
  sub: 'your-app-id',              // Application ID
  policyId: 'policy-uuid-456',     // Payment policy ID
  userExternalId: 'user_payer',    // Payer user external ID
  iat: Math.floor(Date.now() / 1000),
  exp: Math.floor(Date.now() / 1000) + (60 * 60) // 1 hour
};

const token = jwt.sign(payload, privateKey, { 
  algorithm: 'RS256',
  keyid: 'your-key-id'  // Optional key identifier
});

WebSocket Connection

Connection URL

Production: wss://payengine.metronomiq.io/stream
Test: wss://payengine-test.metronomiq.io/stream

Authentication

Include JWT token in connection headers:

const WebSocket = require('ws');

const ws = new WebSocket('wss://payengine.metronomiq.io/stream', {
  headers: {
    'authorization': `Bearer ${jwtToken}`
  }
});

ws.on('open', () => {
  console.log('🟢 WebSocket connection established');
});

ws.on('message', data => {
  const msg = JSON.parse(data);
  console.log('📨 Received:', msg);
});

Message Types

Automatic Session Start

The payment session starts automatically when the WebSocket connection is established with a valid JWT token containing policyId and userExternalId.

Pause Session

Temporarily pause the active payment session

// Send pause message
const pauseMessage = {
  type: 'pause'
};
ws.send(JSON.stringify(pauseMessage));

Resume Session

Resume a paused payment session

// Send resume message
const resumeMessage = {
  type: 'resume'
};
ws.send(JSON.stringify(resumeMessage));

Stop Session

End the payment session (closing WebSocket connection)

// Close the WebSocket to end session
ws.close();

Response Format

All WebSocket responses follow this format:

{
  "success": true,
  "message": "Session started successfully",
  "data": {
    "sessionId": "session-uuid-789",
    "status": "ACTIVE",
    "startedAt": "2024-01-01T12:00:00Z"
  }
}

Error Handling

Standard error responses and codes used throughout the Metronomiq API.

Error Format

{
  "error": {
    "code": "USER_NOT_FOUND",
    "message": "User not found",
    "status": 404
  }
}

Authentication & Authorization

Status Code Description
401 UNAUTHORIZED API key missing or invalid
401 INVALID_API_KEY Invalid API key format or value
403 API_KEY_REVOKED API key has been revoked
403 APPLICATION_SUSPENDED Application has been suspended
401 APPLICATION_NOT_AUTHENTIFIED Application authentication failed

Users & Wallets

Status Code Description
404 USER_NOT_FOUND User with specified ID not found
409 USER_ALREADY_EXIST User with this external ID already exists
400 INSUFFICIENT_BALANCE_WITHDRAW Insufficient balance for withdrawal request

Payment Policies

Status Code Description
404 PAYMENT_POLICY_NOT_FOUND Payment policy not found
409 PAYMENT_POLICY_USED_BY_RESOURCES Cannot delete policy, it's used by resources

Application Management

Status Code Description
404 APP_NOT_FOUND Application not found
409 DUPLICATE_APP_ID Application ID already exists
400 BAD_PUB_KEY Invalid public key format
409 RESOURCE_ALREADY_EXIST Resource with this identifier already exists

System Errors

Status Code Description
400 DB_VALIDATION_ERROR Database validation failed
500 INTERNAL_SERVER_ERROR Internal server error
429 OUT_OF_QUOTA API quota exceeded
500 UNKNOWN Unknown error occurred