Payment Gateway API

Accept credit/debit cards (Visa, Mastercard, Maestro), Apple Pay, Google Pay, and SEPA bank transfers on any website. No merchant onboarding required. No API keys. Instant payouts in USDC (Polygon) to your own wallet.

No API Keys No Merchant KYC API v1.0 Instant USDC Payouts Visa & Mastercard Apple Pay Google Pay SEPA
Merchant vs. End-User KYC Merchants can integrate instantly without any sign-up, documents, or verification. End-users (customers) may be asked to complete a quick identity check by the payment provider during their first transaction, depending on the provider and jurisdiction.

Integration Flow

1 server-side API call + 1 client-side redirect + callback webhook. Optionally, a currency conversion call before the redirect.

1

Create Wallet (server-side API call)

Generate a temporary encrypted wallet address by passing your USDC wallet + a callback URL. You receive an encrypted address_in and an ipn_token for tracking. Store the ipn_token in your database.

2

Redirect Customer (client-side redirect)

Redirect the customer's browser to the checkout URL with the encrypted wallet, amount, currency, and provider. The customer completes payment via the provider's hosted checkout.

3

Receive & Verify Callback (webhook)

After payment, a GET callback hits your URL with transaction data. Always verify via the Payment Status endpoint before marking the order as paid. USDC arrives instantly in your wallet.

Base URL

API: https://pay.syncom-europe.com
Checkout: https://checkout.syncom-europe.com
All endpoints use GET requests. No authentication headers or API keys required — just pass the required query parameters.

URL Encoding Rules

Incorrect URL encoding is the most common integration error. Follow these rules precisely.

ParameterEncoding Rule
callback Apply encodeURIComponent() once to the full callback URL (including your query params).
address_in The value returned by Create Wallet is already encoded. Apply encodeURIComponent() once more when passing it to Process Payment.
email Apply encodeURIComponent() — the @ becomes %40.

JavaScript Example

JavaScript
const callbackUrl = `https://myshop.com/api/callback?orderId=${orderId}`; // Create Wallet — encode the callback const walletUrl = `https://pay.syncom-europe.com/control/wallet.php` + `?address=${merchantWallet}` + `&callback=${encodeURIComponent(callbackUrl)}`; // Process Payment — encode the address_in const checkoutUrl = `https://checkout.syncom-europe.com/process-payment.php` + `?address=${encodeURIComponent(wallet.address_in)}` + `&amount=${amount}` + `&provider=${provider}` + `¤cy=${currency}` + `&email=${encodeURIComponent(email)}`;

PHP Example

PHP
// Create Wallet $walletUrl = "https://pay.syncom-europe.com/control/wallet.php" . "?address=" . $merchantWallet . "&callback=" . urlencode($callbackUrl); // Process Payment $checkoutUrl = "https://checkout.syncom-europe.com/process-payment.php" . "?address=" . urlencode($wallet['address_in']) . "&amount=" . $amount . "&provider=" . $provider . "¤cy=" . $currency . "&email=" . urlencode($email);

Amount & Precision

To avoid floating-point rounding issues, follow these rules when handling amounts.

Treat all amounts as strings Never use floating-point arithmetic on payment amounts. The API returns all values as strings — keep them as strings in your code and database.
FieldWhat it representsWhen to use
value_coin USDC amount received by the order's temporary wallet from the payment provider. Use for payment verification — compare against your expected order amount.
value_forwarded_coin Total USDC forwarded from the order wallet to the merchant (after network fees). Use for accounting — this is what actually arrives in your wallet.

When verifying payments, allow a small tolerance (e.g. ±0.02 USDC) to account for minor FX rounding by providers.


GET Create Wallet

Generate a temporary encrypted wallet address for an order. Each callback URL gets a unique wallet. All received USDC is instantly forwarded to your merchant wallet.

https://pay.syncom-europe.com/control/wallet.php?address={your-usdc-wallet}&callback={urlencoded-callback-url}

Request Parameters

ParameterDescription
addressrequired Your USDC (Polygon) wallet address to receive instant payouts.
callbackrequired URL-encoded callback URL. Must be HTTPS. Include your order identifier as a query parameter (e.g. ?orderId=123) — it will be preserved in the callback.

Example Request

cURL
curl --location \ 'https://pay.syncom-europe.com/control/wallet.php?address=0xF977814e90dA44bFA03b6295A0616a897441aceC&callback=https%253A%252F%252Fwww.example.com%252Forders.php%253Fnumber%253D8271468415326'

Response

FieldDescription
address_in Encrypted wallet address — pass this to the Process Payment redirect. URL-encode it once more when building the redirect URL.
polygon_address_in Unencrypted Polygon wallet address assigned to this order (for reference/on-chain tracking).
callback_url The decoded callback URL you provided.
ipn_token Token for verifying payment status. Store this in your database alongside the order.
Response — 200 OK
{ "address_in": "eE5A43DAkczRwxoW3IL7sGsRh6CiMx4kkTCccr6n/YMTGhy9b...", "polygon_address_in": "0x756C4D5EAad2165b3841a543Cf851Eed6AAF211B", "callback_url": "https://www.example.com/orders.php?number=8271468415326", "ipn_token": "ZEE2cW8zb1N0N2otZEc3eHh3MDNUU1lTMEExYmVvcD..." }

GET Process Payment

Redirect the customer's browser to the payment page. This is not a server-side API call — send the customer here via HTTP redirect or window.location.

https://checkout.syncom-europe.com/process-payment.php?address={encrypted-address}&amount={amount}&provider={provider}&currency={currency}&email={email}

Request Parameters

ParameterDescription
addressrequired The URL-encoded address_in value from the Create Wallet response.
amountrequired Payment amount as a string (e.g. 103.78). Do not use floating-point math.
providerrequired Payment provider identifier. See providers list (e.g. moonpay, stripe, transak).
currencyrequired Fiat currency code (e.g. USD, EUR). Some providers support USD only — use the Convert endpoint first.
emailoptional Customer's email (URL-encoded). Pre-fills the provider's checkout form.

Example

Browser Redirect URL
https://checkout.syncom-europe.com/process-payment.php ?address=eE5A43DAkczRwxoW3IL7sGsRh6CiMx4kkTCccr6n%252FYMTGhy9b1eeIJLTr9Lho64fJTIeOfgsnJNNc%252FarqtR1jw%253D%253D &amount=103.78 &provider=moonpay &email=john%2540example.com ¤cy=USD
No iframes The customer must be redirected to the payment provider directly. Do NOT embed the checkout page in an iframe — this violates provider terms and will cause payment failures.

GET Convert to USD

Some providers (Stripe, Wert, Transfi, Ramp Network) support USD only. Use this endpoint to convert other currencies before calling Process Payment.

https://pay.syncom-europe.com/control/convert.php?from={currency}&value={amount}

Request Parameters

ParameterDescription
fromrequired Source currency code (e.g. EUR, SEK, GBP, CHF).
valuerequired Amount to convert (e.g. 1258.31).

Example

cURL
curl --location 'https://pay.syncom-europe.com/control/convert.php?from=EUR&value=1258.31'
Response — 200 OK
{ "status": "success", "value_coin": "1351.76", "exchange_rate": "1.07427" }

GET Callback Event

When a customer completes payment, a GET request is sent to your callback URL with all your original query parameters plus the following transaction data.

https://www.example.com/orders.php?number=827746841326&value_coin=105.6&coin=polygon_usdc&txid_in=0xa22a...&txid_out=0x94c2...&address_in=0x32e8...&value_forwarded_coin=104.016

Callback Parameters

ParameterDescription
value_coin USDC amount paid by the provider to the order wallet.
coin Payout coin type, usually polygon_usdc or polygon_usdt.
txid_in Polygon TXID — payment from provider to the order's temporary wallet.
txid_out Polygon TXID — instant payout from temporary wallet to your merchant wallet.
address_in Unencrypted Polygon wallet for this order. Must match polygon_address_in from Create Wallet.
value_forwarded_coin Total USDC forwarded to the merchant wallet (after network fees).
Never trust callbacks blindly Callbacks can be spoofed. Always verify via the Callback Verification flow before marking an order as paid.

GET Check Payment Status

Verify whether a payment has been completed. Use the ipn_token stored during Create Wallet.

https://pay.syncom-europe.com/control/payment-status.php?ipn_token={ipn_token}

Request Parameters

ParameterDescription
ipn_tokenrequired The ipn_token from the Create Wallet response.

Response

FieldDescription
status paid or unpaid
value_coin USDC amount sent by the provider to the order wallet.
txid_out Blockchain TXID of the payout to your merchant wallet.
coin Payout coin type (e.g. polygon_usdc).
Response — 200 OK (Paid)
{ "status": "paid", "value_coin": "117.59", "txid_out": "0xe85ed56174785b0bb9fcb522655f961675ad236f2aad2f5bb4fa2f074ac09726", "coin": "polygon_usdc" }
Rate limiting This endpoint is for verification and occasional status checks only. Do not poll it continuously — rely on the Callback Event as the trigger, then verify once with this endpoint.

Callback Verification

Callbacks arrive as unsigned GET requests. Anyone who knows your callback URL could send a fake request. Always verify before marking an order as paid.

Required Verification Flow

1

Receive Callback

Extract the order ID from your callback's query parameters (e.g. orderId). Look up the stored ipn_token for that order in your database.

2

Verify via Payment Status

Call GET /control/payment-status.php?ipn_token={stored_token} and confirm status=paid.

3

Validate Amount & TXID

Compare the returned value_coin against your expected order amount (with ±0.02 tolerance). Optionally verify txid_out matches.

4

Idempotency Check

Before marking paid, check that this txid_out hasn't already been processed (prevents replay attacks). Only then update your order status.

Pattern: Callback as trigger, Status endpoint as truth Use the callback to know when to check. Use the Payment Status endpoint to know if it's real.

Error Handling

The API may return errors in the following format.

Error Response Format

Error Response
{ "status": "error", "message": "Invalid wallet address" }

Common HTTP Status Codes

CodeMeaningWhat to do
200 Success Parse response JSON normally.
400 Bad Request Check your parameters — likely a missing or malformed value (bad encoding, invalid wallet address).
422 Unprocessable Parameters are syntactically valid but semantically wrong (e.g. unsupported currency for provider).
429 Rate Limited Too many requests. Wait 30–60 seconds before retrying. Implement exponential backoff.
500 Server Error Transient failure. Retry with exponential backoff (max 3 retries).
Tip Always check for "status": "success" in the JSON response body, even on HTTP 200. Some errors may return 200 with an error message in the body.

Quickstart: Next.js (App Router)

A production-ready integration pattern using Next.js with proper callback verification, idempotency, and error handling.

1. Create Payment Session

app/api/payments/create-session/route.ts
import { NextResponse } from "next/server"; type CreateSessionBody = { orderId: string; amount: string; // always string, never float currency: string; // e.g. "EUR", "USD" provider: string; // e.g. "moonpay", "stripe" email?: string; }; export async function POST(req: Request) { const body = (await req.json()) as CreateSessionBody; // Build callback URL with your order identifier const callbackUrl = new URL( `${process.env.APP_URL}/api/payments/callback` ); callbackUrl.searchParams.set("orderId", body.orderId); // Step 1: Create Wallet const walletUrl = new URL( "https://pay.syncom-europe.com/control/wallet.php" ); walletUrl.searchParams.set("address", process.env.MERCHANT_USDC_WALLET!); walletUrl.searchParams.set("callback", callbackUrl.toString()); const walletRes = await fetch(walletUrl.toString()); if (!walletRes.ok) { return NextResponse.json( { status: "error", message: "wallet_create_failed" }, { status: 502 } ); } const wallet = await walletRes.json(); // Store ipn_token + expected amount in your DB // await db.paymentSessions.create({ // orderId: body.orderId, // ipnToken: wallet.ipn_token, // expectedAmount: body.amount, // currency: body.currency, // }); // Step 2: Build redirect URL for the customer const redirectUrl = new URL( "https://checkout.syncom-europe.com/process-payment.php" ); redirectUrl.searchParams.set("address", wallet.address_in); redirectUrl.searchParams.set("amount", body.amount); redirectUrl.searchParams.set("provider", body.provider); redirectUrl.searchParams.set("currency", body.currency); if (body.email) { redirectUrl.searchParams.set("email", body.email); } return NextResponse.json({ status: "success", redirect_url: redirectUrl.toString(), }); }

2. Callback Handler (with Verification)

app/api/payments/callback/route.ts
import { NextResponse } from "next/server"; export async function GET(req: Request) { const url = new URL(req.url); const orderId = url.searchParams.get("orderId"); const txidOut = url.searchParams.get("txid_out"); if (!orderId) { return NextResponse.json({ ok: false }, { status: 400 }); } // Load session from DB // const session = await db.paymentSessions.findUnique({ // where: { orderId } // }); // if (!session) return NextResponse.json({ ok: false }, { status: 404 }); // Idempotency: already paid? Just return 200 // if (session.status === "paid") { // return NextResponse.json({ ok: true }); // } // VERIFY: Never trust the callback — check payment status const statusUrl = new URL( "https://pay.syncom-europe.com/control/payment-status.php" ); statusUrl.searchParams.set("ipn_token", session.ipnToken); const statusRes = await fetch(statusUrl.toString()); if (!statusRes.ok) { return NextResponse.json({ ok: false }, { status: 502 }); } const status = await statusRes.json(); if (status.status === "paid") { // Verify amount (with tolerance for FX rounding) const paid = parseFloat(status.value_coin); const expected = parseFloat(session.expectedAmount); if (Math.abs(paid - expected) > 0.02) { // Amount mismatch — log for review console.warn(`Amount mismatch: paid=${paid}, expected=${expected}`); } // Replay check: ensure txid_out not already used if (txidOut && status.txid_out && txidOut !== status.txid_out) { return NextResponse.json({ ok: false }, { status: 409 }); } // Mark order as paid + store txid_out // await db.orders.update({ // where: { id: orderId }, // data: { status: "paid", txidOut: status.txid_out } // }); } // Always return 200 to acknowledge the callback return NextResponse.json({ ok: true }); }
Pattern: Callback as trigger, Status endpoint as truth The callback tells you when to check. The Payment Status endpoint tells you whether it's real. Never update order status based on callback parameters alone.

Payment Providers

Use the provider parameter in Process Payment. Each provider has different minimum order amounts, supported currencies, and fee structures. Fees are generally lower for larger transaction amounts.

Provider IDCurrencyNotes
moonpayMultiWide coverage, popular choice
stripeUSD onlyUse Convert endpoint for EUR/GBP/etc.
transakMultiGood international coverage
wertUSD onlyFast onboarding for customers
rampnetworkUSD onlyUse Convert endpoint for other currencies
guardarianMultiMulti-currency support
mercuryoMultiMulti-currency support
banxaMultiMulti-currency support
transfiUSD onlyUse Convert endpoint
utorgMultiMulti-currency support
revolutMultiRecommended for UK customers (bypasses 24h FCA cooling-off period)
Fee handling Processing fees can be passed to the customer at checkout. When enabled, the customer sees fees transparently and the merchant receives the full order amount in USDC.

Requirements

For the Merchant

A USDC wallet on the Polygon network. Use any self-custodial wallet — Trust Wallet (SWIFT option), MetaMask, Coinbase Wallet, or similar.

For the Customer

A 3D Secure enabled card (Verified by Visa / Mastercard SecureCode). First-time customers may need to complete identity verification (KYC) with the payment provider — typically under 2 minutes.

Technical Requirements

Callback endpoints must use HTTPS. The callback handler must respond within a reasonable timeout. Store ipn_token values in your database for payment verification.

Payment finality USDC payouts are irreversible on-chain. Card disputes are handled entirely by the payment provider — merchants receive USDC payouts and are not involved in chargeback processes.

Changelog

VersionDateChanges
v1.0 2025-02-13 Initial release — Create Wallet, Process Payment, Convert to USD, Callback Event, Payment Status.
Syncom Europe Payment Gateway API v1.0 — Support: support@syncom-europe.com