Fiat Module
Note: all numeric values, amounts, rates, and identifiers in the examples are illustrative and provided for demonstration purposes only. Real values depend on market conditions, account configuration, and the parameters of a specific transaction.
Overview
Fiat Module is a subsystem of the CryptoCash platform that allows a merchant to accept fiat payments from end users and receive cryptocurrency to their wallet. Integration is performed through signed API requests. Payments are processed via a payment provider (Mercuryo). The end user completes the payment in the CryptoCash widget, where they select a payment method. After the payment is processed, the merchant receives a webhook with the final status. Supported features:- Payment by card, Apple Pay, Google Pay, SEPA, and other payment methods
- Signed requests (
ED25519orLEGACY/SHA256) for merchant authentication - Webhooks to the merchant on every transaction status change
- Automatic calculation of the merchant’s earnings based on
partner_fee
High-level flow
| Payment method | Flow |
|---|---|
| Apple Pay (native) | The user pays directly in the widget — without being redirected to an external page |
| Card / other methods | The user is redirected to the payment provider’s page to complete the payment |
Merchant setup and Fiat API Key
What the merchant configures
After the administrator has prepared the account, the merchant generates a Fiat API Key in the dashboard. When creating the key, the merchant sets parameters that apply to all payments associated with this key:| Parameter | Description |
|---|---|
keyType | Signature algorithm: ED25519 (recommended) or LEGACY (SHA256) |
keyName | Custom key name |
partnerFee | Share of the provider fee that goes to the merchant; configured by the administrator on the provider account |
paymentMethods | Payment methods available in the widget, for example ["card", "apple_pay"] |
webhookUrl | URL for receiving payment status webhooks |
logoUrl | Merchant logo displayed in the widget |
ipRestrictionEnabled | Whether to restrict API access by IP address |
allowedIpAddresses | List of allowed IP addresses or CIDR ranges |
expiresAt | Specific key expiration date |
neverExpires | If true, the key does not expire (expiresAt = null); by default, the key validity period is 1 year |
publicKey / privateKey pair. The private key is stored on the platform in encrypted form and is shown to the merchant only once — during creation. Save it immediately.
If two-factor authentication is enabled on the merchant account, 2FA confirmation is required to generate the key.
Fiat API Key fields
| Field | Type | Description | |
|---|---|---|---|
publicKey | string | Key identifier, passed in every request | |
privateKey | string | Secret for signing requests; stored encrypted on the platform | |
keyType | ED25519 | LEGACY | Signature algorithm |
isActive | boolean | Whether the key is active | |
expiresAt | datetime | null | Expiration time (null — no expiration) |
paymentMethods | string[] | Allowed payment methods | |
webhookUrl | string | null | URL for webhook delivery |
logoUrl | string | null | Logo URL |
ipRestrictionEnabled | boolean | Whether IP restriction is enabled | |
allowedIpAddresses | string[] | Allowed IP addresses |
ED25519 vs LEGACY
ED25519 | LEGACY | |
|---|---|---|
| Algorithm | Asymmetric cryptography (Ed25519) | SHA256-based signature |
| Key relation | publicKey is mathematically derived from privateKey | publicKey is an identifier; privateKey is a shared secret used for signing |
| Verification | Signature is verified using publicKey without knowing privateKey | The platform uses the stored privateKey to verify the signature |
| Recommended | Yes | Only for compatibility with legacy integrations |
What is checked on each request
When receiving a signed request, the platform checks:- The key is active
- The key has not expired
- The IP of the API caller (merchant server) is included in the allowed list if IP restriction is enabled
- The signature is valid for the selected algorithm
Important: IP restriction applies to the address of the server making the API request, not to the end user’s IP in the payment payload ip field.
Signed requests
All merchant API requests must be signed. The signature algorithm is defined by thekeyType value selected when creating the key.
Request structure
publicKey is passed either in the x-public-key header or inside the data object. If both are present, the header takes priority.
ED25519 (recommended)
LEGACY (SHA256)
Full example
Payload forform/retrieve:
Payment creation — form/retrieve
Endpoint
Request
Thedata field of the signed request contains the following JSON:
| Field | Type | Required | Description |
|---|---|---|---|
ticker | string | ✓* | Crypto asset and network ticker, for example "USDTTRC20" |
currency | string | ✓* | Cryptocurrency code, for example "USDT" |
network | string | ✓* | Blockchain network, for example "TRC20" |
fiatCurrency | string | ✓ | Fiat currency code, for example "SGD" |
fiatAmount | string | ✓ | Fiat amount as a string, for example "100" |
address | string | ✓ | Wallet address for cryptocurrency crediting |
ip | string | ✓ | End user’s IP address |
email | string | — | Customer email |
redirectUrl | string | — | URL to return the user to after payment |
lang | string | — | Widget language, default "en" |
externalId | string | — | External order ID on the merchant side; must be unique within the key |
* To select a crypto asset, pass either ticker or the currency + network pair.
Response
| Field | Description |
|---|---|
id | Internal transaction UUID |
externalId | External ID from the request or null |
url | CryptoCash widget URL — redirect the user to this URL |
What happens after the request
- Signature and IP are checked.
externalIduniqueness is checked within the merchant key.- The fiat amount is checked against the minimum allowed amount for the selected currency.
- The
networkvalue is normalized case-insensitively. - A transaction is created with the
Newstatus. - The widget URL is generated.
- A
payment::createdwebhook is sent to the merchant. idandurlare returned.
CryptoCash widget and provider page
| CryptoCash widget | Payment provider page | |
|---|---|---|
| URL | https://buy.cryptocash.world/merchant/payment/{id} | Generated inside the widget |
| Branding | Merchant logo | Provider styling |
| Purpose | Payment method selection, rate preview, native Apple Pay | Direct payment processing |
Merchant Public API
Retrieve payment
data field contains one of the following:
Payment list
data field:
| Field | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number |
pageSize | number | 100 | Number of items per page |
dateAfter | datetime | — | Filter: created after this date |
dateBefore | datetime | — | Filter: created before this date |
Currency lists
data:
crypto-currencies/list returns the cryptocurrencies available to the merchant together with networks and tickers. Values from tickers can be passed to form/retrieve instead of the currency + network pair.
Payment response fields
| Field | Type | Nullable | Description |
|---|---|---|---|
id | string | Transaction UUID | |
externalId | string | ✓ | Merchant external ID |
status | string | Current status | |
fiatCurrency | string | Fiat currency code | |
fiatAmount | string | Fiat amount | |
cryptoCurrency | string | Cryptocurrency code | |
network | string | Blockchain network | |
cryptoAmount | string | ✓ | Received crypto amount |
address | string | Wallet address | |
hash | string | ✓ | Blockchain transaction hash |
widgetUrl | string | ✓ | Widget URL |
createdAt | datetime | Creation time | |
updatedAt | datetime | Last update time |
Transaction statuses
| Status | Description |
|---|---|
New | Transaction created, awaiting user action |
Waiting | Payment accepted and being processed |
Paid | Cryptocurrency sent to the wallet address |
Fail | Payment failed |
Canceled | Payment canceled |
Error handling
All API errors are returned in one of two formats: Format A — coded error:Error codes
| Code | Description |
|---|---|
1000 | Bad request |
1102 | Invalid request: unsupported network, amount below minimum, duplicate externalId |
1110 | Request validation error |
2010 | data decoding error |
2011 | signature decoding error |
2020 | Invalid signature |
2021 | API key blocked |
2030 | IP address forbidden |
3001 | Order not found |
3002 | Transaction not found |