Metrivo
Docs/Manual Payment API

Manual Payment API

Send payment events from any payment provider via a single REST API call. Works with Paddle, Lemon Squeezy, Gumroad, custom payment systems — anything that processes payments.

Overview

The Manual Payment API is a simple REST endpoint. When a payment succeeds on your end, send a POST request with the payment details and, when available, the Metrivo visitor and session identifiers. Metrivo uses those signals to produce confidence-based attribution to the traffic source, landing page, and campaign.

Your API key is available in your Metrivo dashboard under Settings → API Keys. Keep it secret — treat it like a password.

API Endpoints

POST/api/payments/manual

Submit a payment event for attribution.

Request body

website_iduuidYesWebsite ID from the Metrivo dashboard.
amountnumberYesPayment amount in your reporting unit, for example 49 or 4900 based on how you store revenue.
currencystringYesThree-letter ISO currency code. Metrivo stores it uppercase, for example USD, EUR, GBP.
provider_payment_idstringYesUnique payment ID from your provider. Used with provider to avoid duplicates.
statusstringNoDefaults to paid.
providerstringNoDefaults to manual. Use your provider name if useful.
customer_emailemailNoCustomer email. Helps with confidence-based matching when session data is missing.
paid_atdatetimeNoISO 8601 timestamp. Defaults to the time Metrivo receives the event.
visitor_iduuidNoValue from window.Metrivo.getVisitorId().
session_iduuidNoValue from window.Metrivo.getSessionId().
metadataobjectNoAdditional JSON metadata to store with the payment.

Example request

cURL
curl -X POST https://metrivo.co/api/payments/manual \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "website_id": "6f7c9f52-27f2-4f58-bc27-fc45f0c9c001",
    "amount": 4900,
    "currency": "USD",
    "provider_payment_id": "pay_01HR9Z7N3M8P4KQ2Y6S5T1V9AB",
    "visitor_id": "a1b2c3d4-7e8f-4a9b-8c7d-123456789abc",
    "session_id": "b7f2db6a-7d74-45db-9796-3ddc9f6f2c74",
    "customer_email": "user@example.com",
    "provider": "manual",
    "status": "paid",
    "paid_at": "2026-05-17T10:30:00.000Z",
    "metadata": {
      "checkout": "custom"
    }
  }'

Response (200 OK)

{
  "success": true,
  "payment": {
    "id": "payment_uuid",
    "website_id": "6f7c9f52-27f2-4f58-bc27-fc45f0c9c001",
    "amount": 4900,
    "currency": "USD",
    "provider_payment_id": "pay_01HR9Z7N3M8P4KQ2Y6S5T1V9AB",
    "attributed_source": "google",
    "attributed_medium": "organic",
    "attribution_confidence": "high"
  }
}
POST/api/identify

Identify a visitor by email or custom ID from the browser tracker, or call the public identify endpoint with the same public key and visitor ID. This improves confidence-based matching for payment attribution.

Example request

cURL
window.Metrivo.identify("user@example.com", {
  plan: "starter",
  company: "Acme Inc"
})
HTTP
curl -X POST https://metrivo.co/api/identify \
  -H "Content-Type: application/json" \
  -d '{
    "publicKey": "SITE_PUBLIC_KEY",
    "visitorId": "a1b2c3d4-7e8f-4a9b-8c7d-123456789abc",
    "email": "user@example.com",
    "properties": {
      "plan": "starter",
      "company": "Acme Inc"
    }
  }'

Best practices

Always send the session_id when you can

The session ID is available on the client via window.Metrivo.getSessionId(). Send it to your backend during checkout and include it in the payment event. This gives Metrivo the strongest signal for attribution.

Use provider_payment_id for idempotency

Include the unique payment ID from your provider in every payment event. Metrivo enforces uniqueness by website, provider, and provider_payment_id.

Call identify before payment

When a user signs up or logs in, call the /api/identify endpoint with their email. This creates a persistent mapping between their email and all their session IDs, improving attribution for returning customers.

Send payment events server-side

Never send the /api/payments/manual request from the client. Your API key would be exposed. Always make this request from your backend after the payment webhook/webhook fires.

Error codes

401Invalid or missing API key. Check your Authorization header.
400Invalid JSON or payload. Ensure website_id, amount, currency, and provider_payment_id are present.
403The API key lacks payments:write scope or is not authorized for the posted website_id.
500Payment insert failed. Check provider_payment_id uniqueness and server logs.

Ready to integrate?

Set up your tracking and start sending payment events. See attributed revenue in your dashboard within minutes.