Skip to content

Host-to-Host API

Build your own checkout

Pure REST primitives + HMAC-signed webhooks. Bring your own frontend, render your own payment flow, control every part of the experience. Same Paymos backend, full control over the surface.

Build your own checkout

How it works

Three calls. Your UI in the middle

Create the invoice from your backend, render the payment surface yourself, receive a signed event when the payment confirms. The boundary stays clean.

  1. 1

    Create the invoice

    POST to /v1/invoices from your backend. Pass the amount, the currency, your own external order ID. Get back the invoice ID and its payment URL.

  2. 2

    Render your own UI

    Collect the token and network on your side and confirm them from your server — the call returns the deposit address. Show it, the QR, the timer, however your product looks.

  3. 3

    Receive the signed webhook

    Paymos POSTs an HMAC-signed event to your endpoint when the payment confirms. Verify the signature, mark the order paid, return 200.

Try every call before you ship

The dashboard Playground fires real sandbox requests with your test API key. Pick the endpoint, fill the params, hit Send — see the live HMAC signature, the headers, the response. No Postman, no curl, no copy-paste from the docs.

Three calls. Your UI in the middle

Interface control

When the hosted page isn't enough

For teams that build their own payment form over the API — pixel-perfect to their brand and wired into their own systems. Host-to-host is what you reach for when no ready-made surface fits.

Full surface control

Render the wallet picker, the QR, the status updates yourself. Your design system, your interaction language, your brand.

Native to any stack

Node, Python, PHP, Go, Ruby, Java, .NET — anything that speaks HTTP works. No SDK lock-in.

Signed webhooks with retries

HMAC-signed payloads, at-least-once delivery, exponential backoff retries. Verify on your side, deduplicate on your side.

Sandbox environment

Test mode lives next to production. Same endpoints, isolated data, no real money moves.

What you control

You render the UI. We watch the chain

The boundary is clear: your frontend handles every pixel the customer sees. Our infrastructure handles wallet derivation, chain monitoring, confirmation depth, and settlement.

Your UI

Wallet picker, network picker, address display, QR generation, status feedback — all yours to design.

Your flow

Sequence the steps however your product needs. Bundle checkout into onboarding, split it across screens, gate it behind authentication.

Your brand

Paymos never appears in the customer's URL or visual frame. The payment surface is fully white-labelled.

Your settlement

Withdraw to your treasury wallet on your schedule. Same balance ledger every other Paymos surface settles into.

Get started

Same backend, no SDK to learn

Create an invoice via REST, poll for status changes or subscribe to webhooks, render whatever UI fits. Eight official server SDKs, identical signature scheme across endpoints.

Read docs
import { Paymos, externalOrderId } from '@paymos/sdk';

const paymos = new Paymos({
  apiKey: process.env.PAYMOS_API_KEY,
  apiSecret: process.env.PAYMOS_API_SECRET,
});

const invoice = await paymos.invoices.create({
  projectId: 'prj_xxxxxxxxxxxx',
  amount: '100.00',
  currency: 'USD',
  externalOrderId: externalOrderId('order'),
  clientId: 'customer-456',
});

console.log(invoice.invoiceId, invoice.paymentUrl);
import os

from paymos import Paymos

paymos = Paymos(
    api_key=os.environ["PAYMOS_API_KEY"],
    api_secret=os.environ["PAYMOS_API_SECRET"],
)
invoice = paymos.invoices.create(
    project_id="prj_xxxxxxxxxxxx",
    amount="100.00",
    currency="USD",
    external_order_id="order-123",
    client_id="customer-456",
)

print(invoice["invoice_id"], invoice["payment_url"])
<?php
use Paymos\Client;
use Paymos\ClientConfig;
use Paymos\IdempotencyKey;

$paymos = new Client(new ClientConfig(
    getenv('PAYMOS_API_KEY'),
    getenv('PAYMOS_API_SECRET')
));
$invoice = $paymos->invoices()->create(array(
    'project_id' => 'prj_xxxxxxxxxxxx',
    'amount' => '100.00',
    'currency' => 'USD',
    'external_order_id' => IdempotencyKey::externalOrderId('order'),
    'client_id' => 'customer-456',
));

echo $invoice['invoice_id'] . ' ' . $invoice['payment_url'];
package main

import (
	"context"
	"fmt"
	"os"

	paymos "github.com/Paymos-labs/go-sdk/v2"
)

func main() {
	client, err := paymos.NewClient(os.Getenv("PAYMOS_API_KEY"), os.Getenv("PAYMOS_API_SECRET"))
	if err != nil {
		panic(err)
	}
	invoice, err := client.Invoices.Create(context.Background(), paymos.CreateInvoiceParams{
		ProjectID:       "prj_xxxxxxxxxxxx",
		Amount:          "100.00",
		Currency:        "USD",
		ExternalOrderID: "order-123",
		ClientID:        stringPointer("customer-456"),
	})
	if err != nil {
		panic(err)
	}
	fmt.Println(invoice.InvoiceID, invoice.PaymentURL)
}

func stringPointer(value string) *string { return &value }
using Paymos;

using var paymos = new PaymosClient(
    Environment.GetEnvironmentVariable("PAYMOS_API_KEY")!,
    Environment.GetEnvironmentVariable("PAYMOS_API_SECRET")!);

var invoice = await paymos.Invoices.CreateAsync(new CreateInvoiceRequest(
    ProjectId: "prj_xxxxxxxxxxxx",
    Amount: "100.00",
    Currency: "USD",
    ExternalOrderId: "order-123",
    ClientId: "customer-456"));

Console.WriteLine($"{invoice.InvoiceId} {invoice.PaymentUrl}");
import io.paymos.CreateInvoiceRequest;
import io.paymos.Invoice;
import io.paymos.PaymosClient;

PaymosClient paymos = new PaymosClient(
    System.getenv("PAYMOS_API_KEY"),
    System.getenv("PAYMOS_API_SECRET"));

Invoice invoice = paymos.invoices.create(
    CreateInvoiceRequest.builder()
        .projectId("prj_xxxxxxxxxxxx")
        .amount("100.00")
        .currency("USD")
        .externalOrderId("order-123")
        .clientId("customer-456")
        .build());

System.out.println(invoice.invoiceId() + " " + invoice.paymentUrl());
require 'paymos'

paymos = Paymos::Client.new(
  api_key: ENV.fetch('PAYMOS_API_KEY'),
  api_secret: ENV.fetch('PAYMOS_API_SECRET')
)
invoice = paymos.invoices.create(
  project_id: 'prj_xxxxxxxxxxxx',
  amount: '100.00',
  currency: 'USD',
  external_order_id: 'order-123',
  client_id: 'customer-456'
)

puts "#{invoice.invoice_id} #{invoice.payment_url}"
use paymos::{CreateInvoiceRequest, PaymosClient};

let paymos = PaymosClient::new(
    std::env::var("PAYMOS_API_KEY")?,
    std::env::var("PAYMOS_API_SECRET")?,
)?;
let invoice = paymos
    .invoices()
    .create(&CreateInvoiceRequest {
        project_id: "prj_xxxxxxxxxxxx".to_owned(),
        amount: "100.00".to_owned(),
        currency: "USD".to_owned(),
        external_order_id: "order-123".to_owned(),
        network: None,
        allow_multiple_payments: None,
        customer_fee_percent: None,
        client_id: Some("customer-456".to_owned()),
    })
    .await?;

println!("{} {}", invoice.invoice_id, invoice.payment_url);

One signing scheme

HMAC-SHA256 with a shared secret. Same scheme for invoice creation, status polling, withdrawal, webhook verification — one auth pipeline to maintain.

Platform integration

Multi-project accounts, scoped API keys, idempotent invoice creation via external_order_id. Build the checkout your own way — the API stays the same.

Who uses Host-to-Host

For products with a dedicated payment interface

Anywhere the hosted UI is too constrained — and the business has the engineering team to build their own. Crypto exchanges, custodial wallets, trading platforms, on-ramps.

Crypto exchanges

Run deposits as a native experience inside your trading UI, not as a redirect to a third party.

Custodial wallets

Top-up flows that live entirely inside your wallet app. No browser handoff, no out-of-process step.

Trading platforms

Margin top-ups, deposit reconciliation, multi-account settlement — all driven by the same REST primitives.

Platforms with their own frontend

Product teams that would rather build the payment screen than embed one. Addresses, confirmation state and signed events come from the API; what the user actually looks at is written by your own code.

Pricing

1.0% per settled invoice, 0.3% on Enterprise

The same two numbers as every other Paymos surface. Enterprise is asked for directly, and the founder answers.

See pricing

The payment screen is yours to build