# Payments, clearly documented A practical Merchant API guide, from the first invoice to payout reconciliation. Start with hosted checkout, then connect webhooks and server-side automation. ## Your first payment 1. Create a project in the [merchant cabinet](/cabinet). Complete activation if payment is required. 2. Obtain the project ID, API key and API secret under Integrations. Keep secrets on your server. 3. Create an invoice with the request below. Store its `invoice_id` against your `order_id`. 4. Redirect the buyer to the returned `invoice_url`. Bitcofy offers the available networks and assets. 5. Verify a signed webhook or read the invoice through the API. Fulfil only on the verified result, never on a browser redirect alone. ```bash curl --request POST 'https://pay.bitcofy.pro/api/v1/invoices' \ --header "X-API-Key: $BITCOFY_API_KEY" \ --header "X-API-Secret: $BITCOFY_API_SECRET" \ --header 'Content-Type: application/json' \ --data '{"project_id":"YOUR_PROJECT_ID","order_id":"order-1001","amount":"49.90","currency":"USD","buy_type":"package","success_url":"https://merchant.example/order/success","cancel_url":"https://merchant.example/order/cancel"}' ``` `amount` is the order price in `USD` or `RUB`, not a USDT quantity. Use the selected payment option's `amount_crypto`, fees and rate lock. Creating an invoice again with the same project and order ID returns the existing invoice; changed request fields do not update it. ## Authentication and secrets Base origin: `https://pay.bitcofy.pro`. Reference paths already include `/api/v1`. | Operation | Credentials | Purpose | | --- | --- | --- | | Public information | None | Networks, rates and integration capabilities | | Project reads | `X-API-Key` or `Authorization: Bearer ` | Access to your own project | | Project writes | API key plus `X-API-Secret` | Invoices, settings and payouts | | Signed payout or request decision | Write access plus `signature`, `nonce`, `timestamp` | Additional Ed25519 signature | | Cabinet login | User session | Not a Merchant API key | API keys start with `bpk_`, API secrets with `bps_`, webhook secrets with `bwhsec_live_`. These credentials are distinct. Register the Base64 Ed25519 public key; keep the private key on your server. HTTP headers are case-insensitive; JSON names and network/asset values must match the API. JSON writes use `Content-Type: application/json`. ## Invoice lifecycle Invoice status, transaction confirmations and withdrawable balance are different states. | Status | Meaning | Action | | --- | --- | --- | | `created` | Invoice exists; payment window has not started | Share checkout URL | | `waiting_payment` | Route selected and payment window started | Await payment before session expiry | | `pending` | Transfer detected, processing incomplete | Wait for confirmations and resolution | | `paid` | Payment accepted | Fulfil once | | `paid_over` | Overpayment accepted | Reconcile the actual credited amount | | `partially_paid`, `wrong_amount`, `additional_payment` | Amount needs further handling | Inspect payments and resolution, not automatic full fulfilment | | `late_payment` | Late payment recorded | Inspect credit outcome against your order policy | | `expired`, `cancel` | Window expired or invoice cancelled | Do not fulfil from browser navigation alone | Use `required_confirmations` from the chosen payment option and `confirmations`/`credited` from payments. Requirements vary by network and configuration. A transaction hash is not proof of credit. A `created` invoice does not represent a running payment window. The session timer starts when the buyer selects a network and asset. The active route and rate are locked for the session; inspect current session fields rather than inferring timing from invoice creation. ## Hosted checkout and available assets Prefer the returned `invoice_url`. Public `by-hash` methods support hosted checkout; they do not replace authenticated Merchant API methods. Before `POST …/payment-session`, open the hosted invoice page in the same browser. The endpoint requires a valid access cookie and applies rate limits. The invoice hash alone is insufficient. A `403` asking to open the hosted page indicates missing access. `/api/v1/public/networks` describes platform capabilities. For an invoice, use its current `payment_options`; project and administrator restrictions can change availability. Do not offer an option from an obsolete cache. Read address and amount for the same network/asset pair. A token symbol on another network is not interchangeable. Return URLs control navigation, not payment confirmation. ## Receive and verify webhooks Configure a public HTTPS URL through the cabinet or `POST …/webhook/config`, send a test through `POST …/webhook/test`, and inspect delivery records through `GET …/webhook/events`. Headers: `X-Bitcofy-Event-Id`, `X-Bitcofy-Event-Type`, `X-Bitcofy-Timestamp`, `X-Bitcofy-Signature`, `X-Bitcofy-Retry-Count`. Signature: hex HMAC-SHA256 using the webhook secret over the exact timestamp string, a dot, and the original request body bytes. Do not re-serialize JSON before verification. ```javascript import { createHmac, timingSafeEqual } from 'node:crypto'; export function verifyWebhook(rawBody, timestamp, signature, secret) { if (!Buffer.isBuffer(rawBody) || typeof timestamp !== 'string' || typeof signature !== 'string' || !/^[a-f0-9]{64}$/i.test(signature)) return false; const expected = createHmac('sha256', secret) .update(timestamp + '.', 'utf8').update(rawBody).digest(); return timingSafeEqual(expected, Buffer.from(signature, 'hex')); } ``` 1. Verify signature, timestamp freshness and project ownership. Choose your receiver freshness window with clock skew in mind. 2. Persist and deduplicate by `event_id` atomically with order processing. 3. Return any `2xx` after durable acceptance. Queue slow processing. 4. Handle duplicate and out-of-order deliveries; retrieve the current object when needed. Delivery timeout is 5 seconds, with up to 10 total attempts. Retry delays are 15, 30, 60, 120, 240 seconds, then capped at 300 seconds; queue scheduling affects actual delivery time. Exhausted events become dead. Use API reconciliation as well as webhooks. Core events: `invoice.created`, `invoice.status_changed`, `payout.created`, `payout.processing`, `payout.status_changed`, `payout.rejected`, `webhook.test`. Additional payout transition events can occur. Do not depend on arrival order. ## Payouts and approval requests Use a directly signed `POST /api/v1/payouts`, or create a payout request through `POST …/payout-requests` for a separate approval/rejection step. Check `/balances`, network, asset and destination first. Ledger balance can exceed `available_for_withdrawal` because collection is pending. Obtain fees and availability from the API. For direct payouts, `amount` includes the fee; reconcile `gross_amount`, `fee_amount` and `net_amount`. HTTP `200` does not mean blockchain sending is complete. | State | Meaning | | --- | --- | | `requested` | Awaiting a decision | | `approved`, `rejected` | Request decision; approval does not prove payout completion | | `pending` / `provider_status=processing` | Payout processing | | `success` / `provider_status=completed` | Completed | | `send_error` / `provider_status=failed` | Sending error; reconcile result and reservation release | Store request, payout and idempotency IDs, transaction hash and final-state flags. `GET …/payouts/reconcile` accepts exactly one of `request_id`, `payout_id` or `idempotency_key`. ## Ed25519 signing Generate keys on your server and register the public key with `POST …/security/payout-key`. Base64-encode the signature. API key and secret remain required. The direct payout message is UTF-8, joined with LF (`\n`), without a trailing newline: ```text bitcofy-payout-v1 {project_id} {network} {asset} {amount} {destination_address} {idempotency_key} {nonce} {timestamp_utc} ``` Approval/rejection uses a different message. Action is `approve` or `reject`; keep the reason line empty for approval: ```text bitcofy-payout-approval-v1 {project_id} {request_id} {action} {rejection_reason_or_empty} {nonce} {timestamp_utc} ``` Timestamp must be within 5 minutes of server time. The server normalizes it using Python UTC `isoformat()`. Send and sign a timestamp without fractional seconds and with `+00:00`, for example `2026-09-29T12:00:00+00:00`, to avoid `Z`/offset and fractional-second differences. Generate a unique nonce for each new signed attempt. Send `amount` as a plain decimal string without exponent notation and sign the identical string. Avoid floating-point numbers. A server-provided example message illustrates the format; sign the actual values of your operation. These examples sign an already assembled canonical message. API-generated `private_key` is a Base64 32-byte seed. This differs from the expanded 64-byte TweetNaCl/Go key; convert the seed as shown below. ### Node.js ```javascript import { createPrivateKey, sign } from 'node:crypto'; // message: canonical UTF-8 message shown above, no trailing newline. export function signMessage(seedBase64, message) { const seed = Buffer.from(seedBase64, 'base64'); if (seed.length !== 32) throw new Error('Expected a 32-byte Ed25519 seed'); const pkcs8 = Buffer.concat([ Buffer.from('302e020100300506032b657004220420', 'hex'), seed ]); const key = createPrivateKey({ key: pkcs8, format: 'der', type: 'pkcs8' }); return sign(null, Buffer.from(message, 'utf8'), key).toString('base64'); } ``` ### Python ```python # Dependency: cryptography import base64 from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey def sign_message(seed_base64: str, message: str) -> str: seed = base64.b64decode(seed_base64, validate=True) key = Ed25519PrivateKey.from_private_bytes(seed) # 32-byte seed return base64.b64encode(key.sign(message.encode('utf-8'))).decode('ascii') ``` ### Go ```go package payouts import ( "crypto/ed25519" "encoding/base64" "fmt" ) func SignMessage(seedBase64 string, message string) (string, error) { seed, err := base64.StdEncoding.DecodeString(seedBase64) if err != nil || len(seed) != ed25519.SeedSize { return "", fmt.Errorf("expected a Base64 32-byte Ed25519 seed") } key := ed25519.NewKeyFromSeed(seed) signature := ed25519.Sign(key, []byte(message)) return base64.StdEncoding.EncodeToString(signature), nil } ``` ## Retries and reconciliation | Situation | Action | | --- | --- | | Invoice creation timeout | Find by order ID or retry with the same order ID | | Payout timeout | Query by the same idempotency key or reconcile first | | Payout already exists | Observe it; do not create a second payout | | New signed attempt after reconciliation | Keep the logical operation key, refresh nonce/timestamp, sign again | | `400`, `401`, `403`, `422` | Fix parameters, access or signature before retrying | | Payout `409` | Inspect the structured reason, available balance and reservation | | `429` or temporary unavailability | Back off with jitter; respect `Retry-After` when present | Do not change the idempotency key just because a response was lost. A failed connection can leave a write's outcome unknown. Prefer status reads and webhooks over repeated POST requests. ## Before going live 1. Verify project access, activation and asset availability. 2. Exercise successful, partial, expired and late payments. 3. Verify raw-body webhook signatures, duplicates and out-of-order events. 4. Ensure browser redirects cannot fulfil orders without API confirmation. 5. Exercise response loss, identifier lookup and payout duplicate protection. 6. Verify payout fees, available balances, Ed25519 encoding, nonce and timestamp. 7. Log operation identifiers and errors without credentials or private keys. ## For agents and automated readers Share [the documentation URL](https://pay.bitcofy.pro/docs) directly. The full guide and reference are present in HTML without JavaScript or authentication. - [Russian Markdown](/docs.md): guide and complete endpoint reference. - [English Markdown](/docs/en.md): guide, parameters, responses and errors. - [llms.txt](/llms.txt): compact discovery index. - [llms-full.txt](/llms-full.txt): complete English documentation in one text response. - [OpenAPI JSON](/openapi.json): live public application schema. Choose a workflow, then consult the exact endpoint. Replace illustrative IDs and example values; they are not real credentials. Fetch networks, fees and confirmation requirements from the API. ## Reference data ## GET /api/v1/health Health Access: No API key ### Parameters No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/health' ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `status` | `string` | Required | Object state; see the relevant workflow for values and actions. | | `app` | `string` | Required | App | ```json { "status": "ok", "app": "string" } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | ## GET /api/v1/public/rates List Rates Access: No API key ### Parameters No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/public/rates' ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `rates` | `array` | Required | Rates | | `rates[].base_currency` | `string` | Required | Base Currency | | `rates[].quote_currency` | `string` | Required | Quote Currency | | `rates[].rate` | `string` | Required | Rate pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `rates[].source` | `string` | Required | Source | | `rates[].captured_at` | `string` | Required | Captured At format: date-time | ```json { "rates": [ { "base_currency": "USD", "quote_currency": "USD", "rate": "string", "source": "api", "captured_at": "2026-07-13T12:00:00Z" } ] } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | ## GET /api/v1/public/networks List Networks Access: No API key This is a network registry. Determine invoice-specific availability from its payment_options. ### Parameters No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/public/networks' ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. ```json [ { "example_key": "string" } ] ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | ## GET /api/v1/public/integrations List Public Integrations Access: No API key ### Parameters No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/public/integrations' ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `[].slug` | `string` | Required | Slug | | `[].display_name` | `string` | Required | Display Name | | `[].category` | `string` | Required | Category | | `[].description` | `string` | Required | Description | | `[].supports_webhooks` | `boolean` | Required | Supports Webhooks | | `[].supports_embedded_checkout` | `boolean` | Required | Supports Embedded Checkout | | `[].docs_markdown` | `string` | Required | Docs Markdown | ```json [ { "slug": "string", "display_name": "string", "category": "string", "description": "string", "supports_webhooks": false, "supports_embedded_checkout": false, "docs_markdown": "string" } ] ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | ## Invoices & checkout ## POST /api/v1/invoices Create Invoice Access: X-API-Key + X-API-Secret USD or RUB; buy_type: package or balance. Repeated project_id + order_id returns the existing invoice without updating it. ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | | `X-API-Secret` | header | Required | API secret for this key; required for writes. | | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | `string` | Required | Project identifier; must belong to the API key. | | `order_id` | `string` | Required | Your order identifier. Reuse in the same project returns the existing invoice. | | `amount` | `number / string` | Required | Amount > 0: invoice fiat currency, or payout asset units including fee. Send a decimal string. >: 0; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `currency` | `string` | Required | USD or RUB; order price currency, not the cryptoasset. | | `buy_type` | `string` | Optional | package: order payment; balance: credit actual confirmed amount after fee. default: "package"; min length: 1; max length: 32 | | `callback_url` | `string / null` | Optional | Legacy invoice field; does not configure project webhooks. Use /webhook/config. | | `success_url` | `string / null` | Optional | Absolute HTTP(S) return URL after payment. A redirect does not prove credit. | | `cancel_url` | `string / null` | Optional | Absolute HTTP(S) return URL on cancellation. | | `customer_id` | `string / null` | Optional | Optional customer identifier in your system. | | `customer_email` | `string / null` | Optional | Optional valid customer email. format: email | | `metadata` | `object` | Optional | Your JSON order metadata. System billing_invoice_kind fields are reserved. | ```bash curl --request POST 'https://pay.bitcofy.pro/api/v1/invoices' \ --header "X-API-Key: $BITCOFY_API_KEY" \ --header "X-API-Secret: $BITCOFY_API_SECRET" \ --header 'Content-Type: application/json' \ --data '{ "project_id": "project_demo_001", "order_id": "order_1001", "amount": "100.00", "currency": "USD", "buy_type": "package", "callback_url": "https://merchant.example/api/bitcofy/webhook", "success_url": "https://merchant.example/payment/success", "cancel_url": "https://merchant.example/payment/cancel", "customer_id": "customer_42", "customer_email": "buyer@example.com", "metadata": { "order_ref": "SO-1001", "source": "landing", "plan": "pro" } }' ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `invoice_id` | `string` | Required | Invoice identifier returned on creation. | | `invoice_hash` | `string` | Required | Public identifier from the checkout URL. Keep customer links private. | | `invoice_url` | `string` | Required | Hosted checkout URL for the customer. | | `requested_usd_amount` | `string` | Required | Requested Usd Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `service_fee_usd_amount` | `string / null` | Optional | Service Fee Usd Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `total_payable_usd_amount` | `string / null` | Optional | Total Payable Usd Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `expires_at` | `string` | Required | Expires At format: date-time | | `status` | `string` | Required | Object state; see the relevant workflow for values and actions. | | `buy_type` | `string` | Required | package: order payment; balance: credit actual confirmed amount after fee. | | `invoice_language` | `string` | Required | Invoice Language | | `resolved_language` | `string` | Required | Resolved Language | | `success_url` | `string / null` | Optional | Absolute HTTP(S) return URL after payment. A redirect does not prove credit. | | `cancel_url` | `string / null` | Optional | Absolute HTTP(S) return URL on cancellation. | | `payment_session_started_at` | `string / null` | Optional | Payment Session Started At format: date-time | | `payment_session_expires_at` | `string / null` | Optional | Payment Session Expires At format: date-time | | `payment_session_active` | `boolean` | Optional | Payment Session Active default: false | | `selected_network` | `string / null` | Optional | Selected Network | | `selected_asset` | `string / null` | Optional | Selected Asset | | `payment_options` | `array` | Required | Payment Options | | `payment_options[].network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `payment_options[].asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `payment_options[].option_key` | `string` | Required | Option Key | | `payment_options[].fee_percent` | `string` | Optional | Fee Percent default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].fee_usd_amount` | `string` | Optional | Fee Usd Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].total_payable_usd_amount` | `string` | Optional | Total Payable Usd Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].amount_crypto` | `string` | Required | Cryptoasset amount for the selected payment route. pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].rate_value` | `string` | Required | Rate Value pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].rate_locked_until` | `string` | Required | Rate Locked Until format: date-time | | `payment_options[].required_confirmations` | `integer` | Required | Confirmation threshold for this network; do not hardcode it. | | `payment_options[].network_logo_url` | `string / null` | Optional | Network Logo Url | | `payment_options[].asset_logo_url` | `string / null` | Optional | Asset Logo Url | | `tracked_payment_option` | `object / null` | Optional | tracked payment option | | `tracked_payment_option.network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `tracked_payment_option.asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `tracked_payment_option.option_key` | `string` | Required | Option Key | | `tracked_payment_option.fee_percent` | `string` | Optional | Fee Percent default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.fee_usd_amount` | `string` | Optional | Fee Usd Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.total_payable_usd_amount` | `string` | Optional | Total Payable Usd Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.amount_crypto` | `string` | Required | Cryptoasset amount for the selected payment route. pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.rate_value` | `string` | Required | Rate Value pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.rate_locked_until` | `string` | Required | Rate Locked Until format: date-time | | `tracked_payment_option.required_confirmations` | `integer` | Required | Confirmation threshold for this network; do not hardcode it. | | `tracked_payment_option.network_logo_url` | `string / null` | Optional | Network Logo Url | | `tracked_payment_option.asset_logo_url` | `string / null` | Optional | Asset Logo Url | ```json { "invoice_id": "inv_demo_001", "invoice_hash": "dd8659b3058a", "invoice_url": "string", "requested_usd_amount": "string", "service_fee_usd_amount": "string", "total_payable_usd_amount": "string", "expires_at": "2026-07-13T12:00:00Z", "status": "ok", "buy_type": "package", "invoice_language": "auto", "resolved_language": "auto", "success_url": "https://merchant.example/payment/success", "cancel_url": "https://merchant.example/payment/cancel", "payment_session_started_at": "2026-07-13T12:00:00Z", "payment_session_expires_at": "2026-07-13T12:00:00Z", "payment_session_active": false, "selected_network": "Tron", "selected_asset": "USDT", "payment_options": [ { "network": "Tron", "asset": "USDT", "option_key": "string", "fee_percent": "0", "fee_usd_amount": "0", "total_payable_usd_amount": "0", "amount_crypto": "string", "rate_value": "string", "rate_locked_until": "2026-07-13T12:00:00Z", "required_confirmations": 1, "network_logo_url": "Tron", "asset_logo_url": "USDT" } ], "tracked_payment_option": { "network": "Tron", "asset": "USDT", "option_key": "string", "fee_percent": "0", "fee_usd_amount": "0", "total_payable_usd_amount": "0", "amount_crypto": "string", "rate_value": "string", "rate_locked_until": "2026-07-13T12:00:00Z", "required_confirmations": 1, "network_logo_url": "Tron", "asset_logo_url": "USDT" } } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `400` | Invalid request or state | Inspect detail, parameters, signature and current state; do not retry unchanged. | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `404` | Object not found | Verify the identifier and project. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Invoice not found after creation` ## GET /api/v1/invoices/{invoice_id} Get Invoice Access: X-API-Key A detected transaction does not yet imply credit. Check status, confirmations, required_confirmations and credited where present. ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `invoice_id` | path · `string` | Required | Invoice identifier returned on creation. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/invoices/YOUR_INVOICE_ID' \ --header "X-API-Key: $BITCOFY_API_KEY" ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `invoice_id` | `string` | Required | Invoice identifier returned on creation. | | `invoice_hash` | `string` | Required | Public identifier from the checkout URL. Keep customer links private. | | `invoice_url` | `string` | Required | Hosted checkout URL for the customer. | | `requested_usd_amount` | `string` | Required | Requested Usd Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `service_fee_usd_amount` | `string / null` | Optional | Service Fee Usd Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `total_payable_usd_amount` | `string / null` | Optional | Total Payable Usd Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `expires_at` | `string` | Required | Expires At format: date-time | | `status` | `string` | Required | Object state; see the relevant workflow for values and actions. | | `buy_type` | `string` | Required | package: order payment; balance: credit actual confirmed amount after fee. | | `invoice_language` | `string` | Required | Invoice Language | | `resolved_language` | `string` | Required | Resolved Language | | `success_url` | `string / null` | Optional | Absolute HTTP(S) return URL after payment. A redirect does not prove credit. | | `cancel_url` | `string / null` | Optional | Absolute HTTP(S) return URL on cancellation. | | `payment_session_started_at` | `string / null` | Optional | Payment Session Started At format: date-time | | `payment_session_expires_at` | `string / null` | Optional | Payment Session Expires At format: date-time | | `payment_session_active` | `boolean` | Optional | Payment Session Active default: false | | `selected_network` | `string / null` | Optional | Selected Network | | `selected_asset` | `string / null` | Optional | Selected Asset | | `payment_options` | `array` | Required | Payment Options | | `payment_options[].network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `payment_options[].asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `payment_options[].option_key` | `string` | Required | Option Key | | `payment_options[].fee_percent` | `string` | Optional | Fee Percent default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].fee_usd_amount` | `string` | Optional | Fee Usd Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].total_payable_usd_amount` | `string` | Optional | Total Payable Usd Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].amount_crypto` | `string` | Required | Cryptoasset amount for the selected payment route. pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].rate_value` | `string` | Required | Rate Value pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].rate_locked_until` | `string` | Required | Rate Locked Until format: date-time | | `payment_options[].required_confirmations` | `integer` | Required | Confirmation threshold for this network; do not hardcode it. | | `payment_options[].network_logo_url` | `string / null` | Optional | Network Logo Url | | `payment_options[].asset_logo_url` | `string / null` | Optional | Asset Logo Url | | `tracked_payment_option` | `object / null` | Optional | tracked payment option | | `tracked_payment_option.network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `tracked_payment_option.asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `tracked_payment_option.option_key` | `string` | Required | Option Key | | `tracked_payment_option.fee_percent` | `string` | Optional | Fee Percent default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.fee_usd_amount` | `string` | Optional | Fee Usd Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.total_payable_usd_amount` | `string` | Optional | Total Payable Usd Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.amount_crypto` | `string` | Required | Cryptoasset amount for the selected payment route. pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.rate_value` | `string` | Required | Rate Value pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.rate_locked_until` | `string` | Required | Rate Locked Until format: date-time | | `tracked_payment_option.required_confirmations` | `integer` | Required | Confirmation threshold for this network; do not hardcode it. | | `tracked_payment_option.network_logo_url` | `string / null` | Optional | Network Logo Url | | `tracked_payment_option.asset_logo_url` | `string / null` | Optional | Asset Logo Url | | `order_id` | `string` | Required | Your order identifier. Reuse in the same project returns the existing invoice. | | `fiat_currency` | `string` | Required | Fiat Currency | | `amount_fiat` | `string` | Required | Amount Fiat pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `deposit_addresses` | `array` | Required | Deposit Addresses | | `deposit_addresses[].network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `deposit_addresses[].address` | `string` | Required | Address | | `deposit_addresses[].derivation_path` | `string` | Required | Derivation Path | | `deposit_addresses[].wallet_status` | `string` | Required | Wallet Status | ```json { "invoice_id": "inv_demo_001", "invoice_hash": "dd8659b3058a", "invoice_url": "string", "requested_usd_amount": "string", "service_fee_usd_amount": "string", "total_payable_usd_amount": "string", "expires_at": "2026-07-13T12:00:00Z", "status": "ok", "buy_type": "package", "invoice_language": "auto", "resolved_language": "auto", "success_url": "https://merchant.example/payment/success", "cancel_url": "https://merchant.example/payment/cancel", "payment_session_started_at": "2026-07-13T12:00:00Z", "payment_session_expires_at": "2026-07-13T12:00:00Z", "payment_session_active": false, "selected_network": "Tron", "selected_asset": "USDT", "payment_options": [ { "network": "Tron", "asset": "USDT", "option_key": "string", "fee_percent": "0", "fee_usd_amount": "0", "total_payable_usd_amount": "0", "amount_crypto": "string", "rate_value": "string", "rate_locked_until": "2026-07-13T12:00:00Z", "required_confirmations": 1, "network_logo_url": "Tron", "asset_logo_url": "USDT" } ], "tracked_payment_option": { "network": "Tron", "asset": "USDT", "option_key": "string", "fee_percent": "0", "fee_usd_amount": "0", "total_payable_usd_amount": "0", "amount_crypto": "string", "rate_value": "string", "rate_locked_until": "2026-07-13T12:00:00Z", "required_confirmations": 1, "network_logo_url": "Tron", "asset_logo_url": "USDT" }, "order_id": "order_1001", "fiat_currency": "USD", "amount_fiat": "string", "deposit_addresses": [ { "network": "Tron", "address": "TQ9ExampleDestinationAddress123456789", "derivation_path": "string", "wallet_status": "string" } ] } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `404` | Object not found | Verify the identifier and project. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Invoice not found` - `Project API key is required` ## GET /api/v1/invoices/{invoice_id}/payments Get Invoice Payments Access: X-API-Key A detected transaction does not yet imply credit. Check status, confirmations, required_confirmations and credited where present. ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `invoice_id` | path · `string` | Required | Invoice identifier returned on creation. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/invoices/YOUR_INVOICE_ID/payments' \ --header "X-API-Key: $BITCOFY_API_KEY" ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `invoice_id` | `string` | Required | Invoice identifier returned on creation. | | `invoice_status` | `string` | Required | Invoice Status | | `buy_type` | `string` | Required | package: order payment; balance: credit actual confirmed amount after fee. | | `credited_total_amount` | `string` | Optional | Credited Total Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `credited_fee_total` | `string` | Optional | Credited Fee Total default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `items` | `array` | Required | Items | | `items[].transaction_id` | `string` | Required | Transaction Id | | `items[].invoice_id` | `string` | Required | Invoice identifier returned on creation. | | `items[].network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `items[].asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `items[].tx_hash` | `string` | Required | Tx Hash | | `items[].logical_index` | `string` | Required | Logical Index | | `items[].address` | `string` | Required | Address | | `items[].amount` | `string` | Required | Amount > 0: invoice fiat currency, or payout asset units including fee. Send a decimal string. pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `items[].confirmations` | `integer` | Required | Current confirmation count for the detected transaction. | | `items[].block_number` | `integer / null` | Optional | Block Number | | `items[].status` | `string` | Required | Object state; see the relevant workflow for values and actions. | | `items[].buy_type` | `string` | Required | package: order payment; balance: credit actual confirmed amount after fee. | | `items[].crediting_status` | `string` | Required | Crediting Status | | `items[].net_amount_after_fee` | `string` | Optional | Net Amount After Fee default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `items[].fee_amount` | `string` | Optional | Fee Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `items[].detected_at` | `string` | Required | Detected At format: date-time | | `items[].confirmed_at` | `string / null` | Optional | Confirmed At format: date-time | ```json { "invoice_id": "inv_demo_001", "invoice_status": "string", "buy_type": "package", "credited_total_amount": "0", "credited_fee_total": "0", "items": [ { "transaction_id": "string", "invoice_id": "inv_demo_001", "network": "Tron", "asset": "USDT", "tx_hash": "0xabc123def456", "logical_index": "string", "address": "TQ9ExampleDestinationAddress123456789", "amount": "string", "confirmations": 1, "block_number": 1, "status": "ok", "buy_type": "package", "crediting_status": "string", "net_amount_after_fee": "0", "fee_amount": "0", "detected_at": "2026-07-13T12:00:00Z", "confirmed_at": "2026-07-13T12:00:00Z" } ] } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `404` | Object not found | Verify the identifier and project. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Invoice not found` - `Project API key is required` ## GET /api/v1/public/invoices/by-hash/{invoice_hash} Get Invoice By Hash Access: No API key A detected transaction does not yet imply credit. Check status, confirmations, required_confirmations and credited where present. ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `invoice_hash` | path · `string` | Required | Public identifier from the checkout URL. Keep customer links private. | No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/public/invoices/by-hash/YOUR_INVOICE_HASH' ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `invoice_id` | `string` | Required | Invoice identifier returned on creation. | | `invoice_hash` | `string` | Required | Public identifier from the checkout URL. Keep customer links private. | | `invoice_url` | `string` | Required | Hosted checkout URL for the customer. | | `requested_usd_amount` | `string` | Required | Requested Usd Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `service_fee_usd_amount` | `string / null` | Optional | Service Fee Usd Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `total_payable_usd_amount` | `string / null` | Optional | Total Payable Usd Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `expires_at` | `string` | Required | Expires At format: date-time | | `status` | `string` | Required | Object state; see the relevant workflow for values and actions. | | `buy_type` | `string` | Required | package: order payment; balance: credit actual confirmed amount after fee. | | `invoice_language` | `string` | Required | Invoice Language | | `resolved_language` | `string` | Required | Resolved Language | | `success_url` | `string / null` | Optional | Absolute HTTP(S) return URL after payment. A redirect does not prove credit. | | `cancel_url` | `string / null` | Optional | Absolute HTTP(S) return URL on cancellation. | | `payment_session_started_at` | `string / null` | Optional | Payment Session Started At format: date-time | | `payment_session_expires_at` | `string / null` | Optional | Payment Session Expires At format: date-time | | `payment_session_active` | `boolean` | Optional | Payment Session Active default: false | | `selected_network` | `string / null` | Optional | Selected Network | | `selected_asset` | `string / null` | Optional | Selected Asset | | `payment_options` | `array` | Required | Payment Options | | `payment_options[].network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `payment_options[].asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `payment_options[].option_key` | `string` | Required | Option Key | | `payment_options[].fee_percent` | `string` | Optional | Fee Percent default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].fee_usd_amount` | `string` | Optional | Fee Usd Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].total_payable_usd_amount` | `string` | Optional | Total Payable Usd Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].amount_crypto` | `string` | Required | Cryptoasset amount for the selected payment route. pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].rate_value` | `string` | Required | Rate Value pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].rate_locked_until` | `string` | Required | Rate Locked Until format: date-time | | `payment_options[].required_confirmations` | `integer` | Required | Confirmation threshold for this network; do not hardcode it. | | `payment_options[].network_logo_url` | `string / null` | Optional | Network Logo Url | | `payment_options[].asset_logo_url` | `string / null` | Optional | Asset Logo Url | | `tracked_payment_option` | `object / null` | Optional | tracked payment option | | `tracked_payment_option.network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `tracked_payment_option.asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `tracked_payment_option.option_key` | `string` | Required | Option Key | | `tracked_payment_option.fee_percent` | `string` | Optional | Fee Percent default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.fee_usd_amount` | `string` | Optional | Fee Usd Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.total_payable_usd_amount` | `string` | Optional | Total Payable Usd Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.amount_crypto` | `string` | Required | Cryptoasset amount for the selected payment route. pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.rate_value` | `string` | Required | Rate Value pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.rate_locked_until` | `string` | Required | Rate Locked Until format: date-time | | `tracked_payment_option.required_confirmations` | `integer` | Required | Confirmation threshold for this network; do not hardcode it. | | `tracked_payment_option.network_logo_url` | `string / null` | Optional | Network Logo Url | | `tracked_payment_option.asset_logo_url` | `string / null` | Optional | Asset Logo Url | | `deposit_addresses` | `array` | Required | Deposit Addresses | | `deposit_addresses[].network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `deposit_addresses[].address` | `string` | Required | Address | ```json { "invoice_id": "inv_demo_001", "invoice_hash": "dd8659b3058a", "invoice_url": "string", "requested_usd_amount": "string", "service_fee_usd_amount": "string", "total_payable_usd_amount": "string", "expires_at": "2026-07-13T12:00:00Z", "status": "ok", "buy_type": "package", "invoice_language": "auto", "resolved_language": "auto", "success_url": "https://merchant.example/payment/success", "cancel_url": "https://merchant.example/payment/cancel", "payment_session_started_at": "2026-07-13T12:00:00Z", "payment_session_expires_at": "2026-07-13T12:00:00Z", "payment_session_active": false, "selected_network": "Tron", "selected_asset": "USDT", "payment_options": [ { "network": "Tron", "asset": "USDT", "option_key": "string", "fee_percent": "0", "fee_usd_amount": "0", "total_payable_usd_amount": "0", "amount_crypto": "string", "rate_value": "string", "rate_locked_until": "2026-07-13T12:00:00Z", "required_confirmations": 1, "network_logo_url": "Tron", "asset_logo_url": "USDT" } ], "tracked_payment_option": { "network": "Tron", "asset": "USDT", "option_key": "string", "fee_percent": "0", "fee_usd_amount": "0", "total_payable_usd_amount": "0", "amount_crypto": "string", "rate_value": "string", "rate_locked_until": "2026-07-13T12:00:00Z", "required_confirmations": 1, "network_logo_url": "Tron", "asset_logo_url": "USDT" }, "deposit_addresses": [ { "network": "Tron", "address": "TQ9ExampleDestinationAddress123456789" } ] } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `404` | Object not found | Verify the identifier and project. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `429` | Rate limit exceeded | Back off with jitter and honor Retry-After when present. | - `Too many public invoice requests` - `Invoice not found` ## POST /api/v1/public/invoices/by-hash/{invoice_hash}/payment-session Start Public Invoice Payment Session Access: Checkout page cookie First open /payment_{invoice_hash} to obtain the access cookie. Normally called by hosted checkout. ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `invoice_hash` | path · `string` | Required | Public identifier from the checkout URL. Keep customer links private. | | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. min length: 1; max length: 32 | | `asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. min length: 1; max length: 32 | ```bash curl --request POST 'https://pay.bitcofy.pro/api/v1/public/invoices/by-hash/YOUR_INVOICE_HASH/payment-session' \ --cookie checkout-cookies.txt \ --header 'Content-Type: application/json' \ --data '{ "network": "Ethereum", "asset": "USDT" }' ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `invoice_id` | `string` | Required | Invoice identifier returned on creation. | | `invoice_hash` | `string` | Required | Public identifier from the checkout URL. Keep customer links private. | | `invoice_url` | `string` | Required | Hosted checkout URL for the customer. | | `requested_usd_amount` | `string` | Required | Requested Usd Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `service_fee_usd_amount` | `string / null` | Optional | Service Fee Usd Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `total_payable_usd_amount` | `string / null` | Optional | Total Payable Usd Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `expires_at` | `string` | Required | Expires At format: date-time | | `status` | `string` | Required | Object state; see the relevant workflow for values and actions. | | `buy_type` | `string` | Required | package: order payment; balance: credit actual confirmed amount after fee. | | `invoice_language` | `string` | Required | Invoice Language | | `resolved_language` | `string` | Required | Resolved Language | | `success_url` | `string / null` | Optional | Absolute HTTP(S) return URL after payment. A redirect does not prove credit. | | `cancel_url` | `string / null` | Optional | Absolute HTTP(S) return URL on cancellation. | | `payment_session_started_at` | `string / null` | Optional | Payment Session Started At format: date-time | | `payment_session_expires_at` | `string / null` | Optional | Payment Session Expires At format: date-time | | `payment_session_active` | `boolean` | Optional | Payment Session Active default: false | | `selected_network` | `string / null` | Optional | Selected Network | | `selected_asset` | `string / null` | Optional | Selected Asset | | `payment_options` | `array` | Required | Payment Options | | `payment_options[].network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `payment_options[].asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `payment_options[].option_key` | `string` | Required | Option Key | | `payment_options[].fee_percent` | `string` | Optional | Fee Percent default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].fee_usd_amount` | `string` | Optional | Fee Usd Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].total_payable_usd_amount` | `string` | Optional | Total Payable Usd Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].amount_crypto` | `string` | Required | Cryptoasset amount for the selected payment route. pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].rate_value` | `string` | Required | Rate Value pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].rate_locked_until` | `string` | Required | Rate Locked Until format: date-time | | `payment_options[].required_confirmations` | `integer` | Required | Confirmation threshold for this network; do not hardcode it. | | `payment_options[].network_logo_url` | `string / null` | Optional | Network Logo Url | | `payment_options[].asset_logo_url` | `string / null` | Optional | Asset Logo Url | | `tracked_payment_option` | `object / null` | Optional | tracked payment option | | `tracked_payment_option.network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `tracked_payment_option.asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `tracked_payment_option.option_key` | `string` | Required | Option Key | | `tracked_payment_option.fee_percent` | `string` | Optional | Fee Percent default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.fee_usd_amount` | `string` | Optional | Fee Usd Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.total_payable_usd_amount` | `string` | Optional | Total Payable Usd Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.amount_crypto` | `string` | Required | Cryptoasset amount for the selected payment route. pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.rate_value` | `string` | Required | Rate Value pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.rate_locked_until` | `string` | Required | Rate Locked Until format: date-time | | `tracked_payment_option.required_confirmations` | `integer` | Required | Confirmation threshold for this network; do not hardcode it. | | `tracked_payment_option.network_logo_url` | `string / null` | Optional | Network Logo Url | | `tracked_payment_option.asset_logo_url` | `string / null` | Optional | Asset Logo Url | | `deposit_addresses` | `array` | Required | Deposit Addresses | | `deposit_addresses[].network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `deposit_addresses[].address` | `string` | Required | Address | ```json { "invoice_id": "inv_demo_001", "invoice_hash": "dd8659b3058a", "invoice_url": "string", "requested_usd_amount": "string", "service_fee_usd_amount": "string", "total_payable_usd_amount": "string", "expires_at": "2026-07-13T12:00:00Z", "status": "ok", "buy_type": "package", "invoice_language": "auto", "resolved_language": "auto", "success_url": "https://merchant.example/payment/success", "cancel_url": "https://merchant.example/payment/cancel", "payment_session_started_at": "2026-07-13T12:00:00Z", "payment_session_expires_at": "2026-07-13T12:00:00Z", "payment_session_active": false, "selected_network": "Tron", "selected_asset": "USDT", "payment_options": [ { "network": "Tron", "asset": "USDT", "option_key": "string", "fee_percent": "0", "fee_usd_amount": "0", "total_payable_usd_amount": "0", "amount_crypto": "string", "rate_value": "string", "rate_locked_until": "2026-07-13T12:00:00Z", "required_confirmations": 1, "network_logo_url": "Tron", "asset_logo_url": "USDT" } ], "tracked_payment_option": { "network": "Tron", "asset": "USDT", "option_key": "string", "fee_percent": "0", "fee_usd_amount": "0", "total_payable_usd_amount": "0", "amount_crypto": "string", "rate_value": "string", "rate_locked_until": "2026-07-13T12:00:00Z", "required_confirmations": 1, "network_logo_url": "Tron", "asset_logo_url": "USDT" }, "deposit_addresses": [ { "network": "Tron", "address": "TQ9ExampleDestinationAddress123456789" } ] } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `400` | Invalid request or state | Inspect detail, parameters, signature and current state; do not retry unchanged. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `404` | Object not found | Verify the identifier and project. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `429` | Rate limit exceeded | Back off with jitter and honor Retry-After when present. | - `Too many public invoice requests` - `Open the hosted invoice page before starting a payment session` - `Invoice not found` ## GET /api/v1/public/invoices/by-hash/{invoice_hash}/payments Get Public Invoice Payments By Hash Access: No API key A detected transaction does not yet imply credit. Check status, confirmations, required_confirmations and credited where present. ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `invoice_hash` | path · `string` | Required | Public identifier from the checkout URL. Keep customer links private. | No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/public/invoices/by-hash/YOUR_INVOICE_HASH/payments' ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `invoice_id` | `string` | Required | Invoice identifier returned on creation. | | `invoice_status` | `string` | Required | Invoice Status | | `items` | `array` | Required | Items | | `items[].network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `items[].asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `items[].confirmations` | `integer` | Required | Current confirmation count for the detected transaction. | | `items[].status` | `string` | Required | Object state; see the relevant workflow for values and actions. | ```json { "invoice_id": "inv_demo_001", "invoice_status": "string", "items": [ { "network": "Tron", "asset": "USDT", "confirmations": 1, "status": "ok" } ] } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `404` | Object not found | Verify the identifier and project. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `429` | Rate limit exceeded | Back off with jitter and honor Retry-After when present. | - `Too many public invoice requests` - `Invoice not found` ## GET /api/v1/projects/{project_id}/invoices/by-order/{order_id} Poll Invoice By Order Access: X-API-Key A detected transaction does not yet imply credit. Check status, confirmations, required_confirmations and credited where present. ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `order_id` | path · `string` | Required | Your order identifier. Reuse in the same project returns the existing invoice. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/invoices/by-order/YOUR_ORDER_ID' \ --header "X-API-Key: $BITCOFY_API_KEY" ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `invoice_id` | `string` | Required | Invoice identifier returned on creation. | | `invoice_hash` | `string` | Required | Public identifier from the checkout URL. Keep customer links private. | | `invoice_url` | `string` | Required | Hosted checkout URL for the customer. | | `requested_usd_amount` | `string` | Required | Requested Usd Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `service_fee_usd_amount` | `string / null` | Optional | Service Fee Usd Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `total_payable_usd_amount` | `string / null` | Optional | Total Payable Usd Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `expires_at` | `string` | Required | Expires At format: date-time | | `status` | `string` | Required | Object state; see the relevant workflow for values and actions. | | `buy_type` | `string` | Required | package: order payment; balance: credit actual confirmed amount after fee. | | `invoice_language` | `string` | Required | Invoice Language | | `resolved_language` | `string` | Required | Resolved Language | | `success_url` | `string / null` | Optional | Absolute HTTP(S) return URL after payment. A redirect does not prove credit. | | `cancel_url` | `string / null` | Optional | Absolute HTTP(S) return URL on cancellation. | | `payment_session_started_at` | `string / null` | Optional | Payment Session Started At format: date-time | | `payment_session_expires_at` | `string / null` | Optional | Payment Session Expires At format: date-time | | `payment_session_active` | `boolean` | Optional | Payment Session Active default: false | | `selected_network` | `string / null` | Optional | Selected Network | | `selected_asset` | `string / null` | Optional | Selected Asset | | `payment_options` | `array` | Required | Payment Options | | `payment_options[].network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `payment_options[].asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `payment_options[].option_key` | `string` | Required | Option Key | | `payment_options[].fee_percent` | `string` | Optional | Fee Percent default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].fee_usd_amount` | `string` | Optional | Fee Usd Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].total_payable_usd_amount` | `string` | Optional | Total Payable Usd Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].amount_crypto` | `string` | Required | Cryptoasset amount for the selected payment route. pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].rate_value` | `string` | Required | Rate Value pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payment_options[].rate_locked_until` | `string` | Required | Rate Locked Until format: date-time | | `payment_options[].required_confirmations` | `integer` | Required | Confirmation threshold for this network; do not hardcode it. | | `payment_options[].network_logo_url` | `string / null` | Optional | Network Logo Url | | `payment_options[].asset_logo_url` | `string / null` | Optional | Asset Logo Url | | `tracked_payment_option` | `object / null` | Optional | tracked payment option | | `tracked_payment_option.network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `tracked_payment_option.asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `tracked_payment_option.option_key` | `string` | Required | Option Key | | `tracked_payment_option.fee_percent` | `string` | Optional | Fee Percent default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.fee_usd_amount` | `string` | Optional | Fee Usd Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.total_payable_usd_amount` | `string` | Optional | Total Payable Usd Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.amount_crypto` | `string` | Required | Cryptoasset amount for the selected payment route. pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.rate_value` | `string` | Required | Rate Value pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `tracked_payment_option.rate_locked_until` | `string` | Required | Rate Locked Until format: date-time | | `tracked_payment_option.required_confirmations` | `integer` | Required | Confirmation threshold for this network; do not hardcode it. | | `tracked_payment_option.network_logo_url` | `string / null` | Optional | Network Logo Url | | `tracked_payment_option.asset_logo_url` | `string / null` | Optional | Asset Logo Url | | `order_id` | `string` | Required | Your order identifier. Reuse in the same project returns the existing invoice. | | `fiat_currency` | `string` | Required | Fiat Currency | | `amount_fiat` | `string` | Required | Amount Fiat pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `deposit_addresses` | `array` | Required | Deposit Addresses | | `deposit_addresses[].network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `deposit_addresses[].address` | `string` | Required | Address | | `deposit_addresses[].derivation_path` | `string` | Required | Derivation Path | | `deposit_addresses[].wallet_status` | `string` | Required | Wallet Status | | `project_id` | `string` | Required | Project identifier; must belong to the API key. | ```json { "invoice_id": "inv_demo_001", "invoice_hash": "dd8659b3058a", "invoice_url": "string", "requested_usd_amount": "string", "service_fee_usd_amount": "string", "total_payable_usd_amount": "string", "expires_at": "2026-07-13T12:00:00Z", "status": "ok", "buy_type": "package", "invoice_language": "auto", "resolved_language": "auto", "success_url": "https://merchant.example/payment/success", "cancel_url": "https://merchant.example/payment/cancel", "payment_session_started_at": "2026-07-13T12:00:00Z", "payment_session_expires_at": "2026-07-13T12:00:00Z", "payment_session_active": false, "selected_network": "Tron", "selected_asset": "USDT", "payment_options": [ { "network": "Tron", "asset": "USDT", "option_key": "string", "fee_percent": "0", "fee_usd_amount": "0", "total_payable_usd_amount": "0", "amount_crypto": "string", "rate_value": "string", "rate_locked_until": "2026-07-13T12:00:00Z", "required_confirmations": 1, "network_logo_url": "Tron", "asset_logo_url": "USDT" } ], "tracked_payment_option": { "network": "Tron", "asset": "USDT", "option_key": "string", "fee_percent": "0", "fee_usd_amount": "0", "total_payable_usd_amount": "0", "amount_crypto": "string", "rate_value": "string", "rate_locked_until": "2026-07-13T12:00:00Z", "required_confirmations": 1, "network_logo_url": "Tron", "asset_logo_url": "USDT" }, "order_id": "order_1001", "fiat_currency": "USD", "amount_fiat": "string", "deposit_addresses": [ { "network": "Tron", "address": "TQ9ExampleDestinationAddress123456789", "derivation_path": "string", "wallet_status": "string" } ], "project_id": "project_demo_001" } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `404` | Object not found | Verify the identifier and project. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Invoice not found` - `Project API key is required` ## GET /api/v1/invoices/{invoice_id}/qr Get Invoice Qr Access: X-API-Key A detected transaction does not yet imply credit. Check status, confirmations, required_confirmations and credited where present. ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `invoice_id` | path · `string` | Required | Invoice identifier returned on creation. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/invoices/YOUR_INVOICE_ID/qr' \ --header "X-API-Key: $BITCOFY_API_KEY" ``` ### 200 · image/svg+xml Shape illustration: values are examples; actual state may differ. ```xml … ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `404` | Object not found | Verify the identifier and project. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Invoice not found` - `Project API key is required` ## GET /api/v1/public/invoices/by-hash/{invoice_hash}/payment-qr Get Public Invoice Payment Qr Access: No API key A detected transaction does not yet imply credit. Check status, confirmations, required_confirmations and credited where present. ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `invoice_hash` | path · `string` | Required | Public identifier from the checkout URL. Keep customer links private. | | `network` | query · `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `asset` | query · `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/public/invoices/by-hash/YOUR_INVOICE_HASH/payment-qr?network=tron&asset=USDT' ``` ### 200 · image/svg+xml Shape illustration: values are examples; actual state may differ. ```xml … ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `404` | Object not found | Verify the identifier and project. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `429` | Rate limit exceeded | Back off with jitter and honor Retry-After when present. | - `Too many public invoice requests` - `Invoice not found` - `Payment option not found` ## Project & keys ## GET /api/v1/projects/{project_id}/api-keys List Project Api Keys Access: X-API-Key Creation returns the key and secret once. Listing exposes prefixes and state. ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/api-keys' \ --header "X-API-Key: $BITCOFY_API_KEY" ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `[].key_id` | `string` | Required | Key identifier from the project key list. | | `[].project_id` | `string` | Required | Project identifier; must belong to the API key. | | `[].name` | `string` | Required | Human-readable key label. | | `[].key_prefix` | `string` | Required | Key Prefix | | `[].secret_prefix` | `string / null` | Optional | Secret Prefix | | `[].api_key` | `string / null` | Optional | Project API access key; store immediately on creation. | | `[].api_secret` | `string / null` | Optional | Write API secret; returned on creation, keep on your server. | | `[].is_active` | `boolean` | Required | Is Active | | `[].last_used_at` | `string / null` | Optional | Last Used At format: date-time | | `[].created_at` | `string` | Required | Created At format: date-time | ```json [ { "key_id": "string", "project_id": "project_demo_001", "name": "string", "key_prefix": "string", "secret_prefix": "secret_123456", "api_key": "string", "api_secret": "secret_123456", "is_active": false, "last_used_at": "2026-07-13T12:00:00Z", "created_at": "2026-07-13T12:00:00Z" } ] ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Project API key is required` ## POST /api/v1/projects/{project_id}/api-keys Create Project Api Key Access: X-API-Key + X-API-Secret Creation returns the key and secret once. Listing exposes prefixes and state. ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | | `X-API-Secret` | header | Required | API secret for this key; required for writes. | | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `name` | `string` | Required | Human-readable key label. min length: 1; max length: 128 | ```bash curl --request POST 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/api-keys' \ --header "X-API-Key: $BITCOFY_API_KEY" \ --header "X-API-Secret: $BITCOFY_API_SECRET" \ --header 'Content-Type: application/json' \ --data '{ "name": "Integration key" }' ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `key_id` | `string` | Required | Key identifier from the project key list. | | `project_id` | `string` | Required | Project identifier; must belong to the API key. | | `name` | `string` | Required | Human-readable key label. | | `key_prefix` | `string` | Required | Key Prefix | | `secret_prefix` | `string / null` | Optional | Secret Prefix | | `api_key` | `string` | Required | Project API access key; store immediately on creation. | | `api_secret` | `string` | Required | Write API secret; returned on creation, keep on your server. | | `is_active` | `boolean` | Required | Is Active | | `last_used_at` | `string / null` | Optional | Last Used At format: date-time | | `created_at` | `string` | Required | Created At format: date-time | ```json { "key_id": "string", "project_id": "project_demo_001", "name": "string", "key_prefix": "string", "secret_prefix": "secret_123456", "api_key": "string", "api_secret": "secret_123456", "is_active": false, "last_used_at": "2026-07-13T12:00:00Z", "created_at": "2026-07-13T12:00:00Z" } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `400` | Invalid request or state | Inspect detail, parameters, signature and current state; do not retry unchanged. | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` ## POST /api/v1/projects/{project_id}/api-keys/{key_id}/deactivate Deactivate Project Api Key Access: X-API-Key + X-API-Secret ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `key_id` | path · `string` | Required | Key identifier from the project key list. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | | `X-API-Secret` | header | Required | API secret for this key; required for writes. | No request body. ```bash curl --request POST 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/api-keys/YOUR_KEY_ID/deactivate' \ --header "X-API-Key: $BITCOFY_API_KEY" \ --header "X-API-Secret: $BITCOFY_API_SECRET" ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `key_id` | `string` | Required | Key identifier from the project key list. | | `project_id` | `string` | Required | Project identifier; must belong to the API key. | | `name` | `string` | Required | Human-readable key label. | | `key_prefix` | `string` | Required | Key Prefix | | `secret_prefix` | `string / null` | Optional | Secret Prefix | | `api_key` | `string / null` | Optional | Project API access key; store immediately on creation. | | `api_secret` | `string / null` | Optional | Write API secret; returned on creation, keep on your server. | | `is_active` | `boolean` | Required | Is Active | | `last_used_at` | `string / null` | Optional | Last Used At format: date-time | | `created_at` | `string` | Required | Created At format: date-time | ```json { "key_id": "string", "project_id": "project_demo_001", "name": "string", "key_prefix": "string", "secret_prefix": "secret_123456", "api_key": "string", "api_secret": "secret_123456", "is_active": false, "last_used_at": "2026-07-13T12:00:00Z", "created_at": "2026-07-13T12:00:00Z" } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `400` | Invalid request or state | Inspect detail, parameters, signature and current state; do not retry unchanged. | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `404` | Object not found | Verify the identifier and project. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` ## POST /api/v1/projects/{project_id}/security/payout-key Register Payout Key Access: X-API-Key + X-API-Secret ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | | `X-API-Secret` | header | Required | API secret for this key; required for writes. | | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `public_key` | `string` | Required | Ed25519 public key, 32 bytes encoded as Base64. min length: 32 | | `algorithm` | `string` | Optional | Ed25519. default: "Ed25519" | | `name` | `string / null` | Optional | Human-readable key label. max length: 128 | ```bash curl --request POST 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/security/payout-key' \ --header "X-API-Key: $BITCOFY_API_KEY" \ --header "X-API-Secret: $BITCOFY_API_SECRET" \ --header 'Content-Type: application/json' \ --data '{ "public_key": "BASE64_ED25519_PUBLIC_KEY", "algorithm": "Ed25519", "name": "string" }' ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `key_id` | `string` | Required | Key identifier from the project key list. | | `project_id` | `string` | Required | Project identifier; must belong to the API key. | | `name` | `string` | Required | Human-readable key label. | | `algorithm` | `string` | Required | Ed25519. | | `public_key` | `string` | Required | Ed25519 public key, 32 bytes encoded as Base64. | | `public_key_preview` | `string` | Required | Public Key Preview | | `origin` | `string` | Required | Origin | | `is_active` | `boolean` | Required | Is Active | | `created_at` | `string` | Required | Created At format: date-time | | `private_key` | `string / null` | Optional | Private key: returned only on generation. Store securely immediately. | | `signing_message_example` | `string` | Required | Canonical message example; sign your actual operation values. | ```json { "key_id": "string", "project_id": "project_demo_001", "name": "string", "algorithm": "string", "public_key": "BASE64_ED25519_PUBLIC_KEY", "public_key_preview": "BASE64_ED25519_PUBLIC_KEY", "origin": "string", "is_active": false, "created_at": "2026-07-13T12:00:00Z", "private_key": "BASE64_ED25519_PRIVATE_KEY", "signing_message_example": "string" } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `400` | Invalid request or state | Inspect detail, parameters, signature and current state; do not retry unchanged. | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` ## GET /api/v1/projects/{project_id}/payout-keys List Project Payout Keys Access: X-API-Key ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/payout-keys' \ --header "X-API-Key: $BITCOFY_API_KEY" ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `[].key_id` | `string` | Required | Key identifier from the project key list. | | `[].project_id` | `string` | Required | Project identifier; must belong to the API key. | | `[].name` | `string` | Required | Human-readable key label. | | `[].algorithm` | `string` | Required | Ed25519. | | `[].public_key` | `string` | Required | Ed25519 public key, 32 bytes encoded as Base64. | | `[].public_key_preview` | `string` | Required | Public Key Preview | | `[].origin` | `string` | Required | Origin | | `[].is_active` | `boolean` | Required | Is Active | | `[].created_at` | `string` | Required | Created At format: date-time | ```json [ { "key_id": "string", "project_id": "project_demo_001", "name": "string", "algorithm": "string", "public_key": "BASE64_ED25519_PUBLIC_KEY", "public_key_preview": "BASE64_ED25519_PUBLIC_KEY", "origin": "string", "is_active": false, "created_at": "2026-07-13T12:00:00Z" } ] ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Project API key is required` ## POST /api/v1/projects/{project_id}/payout-keys/generate Generate Project Payout Key Access: X-API-Key + X-API-Secret Returns an Ed25519 private_key once. Alternatively generate locally and register only public_key via /security/payout-key. ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | | `X-API-Secret` | header | Required | API secret for this key; required for writes. | | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `name` | `string / null` | Optional | Human-readable key label. max length: 128 | ```bash curl --request POST 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/payout-keys/generate' \ --header "X-API-Key: $BITCOFY_API_KEY" \ --header "X-API-Secret: $BITCOFY_API_SECRET" \ --header 'Content-Type: application/json' \ --data '{ "name": "string" }' ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `key_id` | `string` | Required | Key identifier from the project key list. | | `project_id` | `string` | Required | Project identifier; must belong to the API key. | | `name` | `string` | Required | Human-readable key label. | | `algorithm` | `string` | Required | Ed25519. | | `public_key` | `string` | Required | Ed25519 public key, 32 bytes encoded as Base64. | | `public_key_preview` | `string` | Required | Public Key Preview | | `origin` | `string` | Required | Origin | | `is_active` | `boolean` | Required | Is Active | | `created_at` | `string` | Required | Created At format: date-time | | `private_key` | `string / null` | Optional | Private key: returned only on generation. Store securely immediately. | | `signing_message_example` | `string` | Required | Canonical message example; sign your actual operation values. | ```json { "key_id": "string", "project_id": "project_demo_001", "name": "string", "algorithm": "string", "public_key": "BASE64_ED25519_PUBLIC_KEY", "public_key_preview": "BASE64_ED25519_PUBLIC_KEY", "origin": "string", "is_active": false, "created_at": "2026-07-13T12:00:00Z", "private_key": "BASE64_ED25519_PRIVATE_KEY", "signing_message_example": "string" } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `400` | Invalid request or state | Inspect detail, parameters, signature and current state; do not retry unchanged. | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` ## POST /api/v1/projects/{project_id}/payout-keys/{key_id}/delete Delete Project Payout Key Access: X-API-Key + X-API-Secret ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `key_id` | path · `string` | Required | Key identifier from the project key list. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | | `X-API-Secret` | header | Required | API secret for this key; required for writes. | No request body. ```bash curl --request POST 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/payout-keys/YOUR_KEY_ID/delete' \ --header "X-API-Key: $BITCOFY_API_KEY" \ --header "X-API-Secret: $BITCOFY_API_SECRET" ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `key_id` | `string` | Required | Key identifier from the project key list. | | `project_id` | `string` | Required | Project identifier; must belong to the API key. | | `name` | `string` | Required | Human-readable key label. | | `algorithm` | `string` | Required | Ed25519. | | `public_key` | `string` | Required | Ed25519 public key, 32 bytes encoded as Base64. | | `public_key_preview` | `string` | Required | Public Key Preview | | `origin` | `string` | Required | Origin | | `is_active` | `boolean` | Required | Is Active | | `created_at` | `string` | Required | Created At format: date-time | ```json { "key_id": "string", "project_id": "project_demo_001", "name": "string", "algorithm": "string", "public_key": "BASE64_ED25519_PUBLIC_KEY", "public_key_preview": "BASE64_ED25519_PUBLIC_KEY", "origin": "string", "is_active": false, "created_at": "2026-07-13T12:00:00Z" } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `400` | Invalid request or state | Inspect detail, parameters, signature and current state; do not retry unchanged. | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `404` | Object not found | Verify the identifier and project. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` ## GET /api/v1/projects/{project_id}/payout-keys/{key_id}/signing-message-example Get Project Payout Key Signing Message Example Access: X-API-Key ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `key_id` | path · `string` | Required | Key identifier from the project key list. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/payout-keys/YOUR_KEY_ID/signing-message-example' \ --header "X-API-Key: $BITCOFY_API_KEY" ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `key_id` | `string` | Required | Key identifier from the project key list. | | `project_id` | `string` | Required | Project identifier; must belong to the API key. | | `algorithm` | `string` | Required | Ed25519. | | `public_key` | `string` | Required | Ed25519 public key, 32 bytes encoded as Base64. | | `origin` | `string` | Required | Origin | | `signing_message_example` | `string` | Required | Canonical message example; sign your actual operation values. | ```json { "key_id": "string", "project_id": "project_demo_001", "algorithm": "string", "public_key": "BASE64_ED25519_PUBLIC_KEY", "origin": "string", "signing_message_example": "string" } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `404` | Object not found | Verify the identifier and project. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Project API key is required` ## GET /api/v1/projects/{project_id}/balances Get Project Balances Access: X-API-Key ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/balances' \ --header "X-API-Key: $BITCOFY_API_KEY" ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `balances` | `array` | Required | Balances | | `balances[].project_id` | `string` | Required | Project identifier; must belong to the API key. | | `balances[].network` | `string / null` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `balances[].asset` | `string / null` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `balances[].account_code` | `string` | Required | Account Code | | `balances[].balance` | `string` | Required | Balance pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `balances[].available_for_withdrawal` | `string / null` | Optional | Available For Withdrawal pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `balances[].pending_aggregation_balance` | `string / null` | Optional | Pending Aggregation Balance pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | ```json { "balances": [ { "project_id": "project_demo_001", "network": "Tron", "asset": "USDT", "account_code": "string", "balance": "string", "available_for_withdrawal": "string", "pending_aggregation_balance": "string" } ] } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Project API key is required` ## GET /api/v1/projects/{project_id}/transactions Get Project Transactions Access: X-API-Key ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/transactions' \ --header "X-API-Key: $BITCOFY_API_KEY" ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `items` | `array` | Required | Items | | `items[].transaction_type` | `string` | Required | Transaction Type | | `items[].reference_id` | `string` | Required | Reference Id | | `items[].status` | `string` | Required | Object state; see the relevant workflow for values and actions. | | `items[].network` | `string / null` | Optional | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `items[].asset` | `string / null` | Optional | Asset code, e.g. USDT. Must be available for this network and project. | | `items[].amount` | `string` | Required | Amount > 0: invoice fiat currency, or payout asset units including fee. Send a decimal string. pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `items[].currency` | `string / null` | Optional | USD or RUB; order price currency, not the cryptoasset. | | `items[].created_at` | `string` | Required | Created At format: date-time | | `items[].meta` | `object` | Optional | Meta | ```json { "items": [ { "transaction_type": "string", "reference_id": "string", "status": "ok", "network": "Tron", "asset": "USDT", "amount": "string", "currency": "USD", "created_at": "2026-07-13T12:00:00Z", "meta": { "example_key": "string" } } ] } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Project API key is required` ## GET /api/v1/projects/{project_id}/transactions/export.csv Export Project Transactions Csv Access: X-API-Key ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/transactions/export.csv' \ --header "X-API-Key: $BITCOFY_API_KEY" ``` ### 200 · text/csv Shape illustration: values are examples; actual state may differ. ```text Transaction CSV file. Columns depend on the export format. ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Project API key is required` ## GET /api/v1/projects/{project_id}/transactions/export-quickbooks.csv Export Project Transactions Quickbooks Csv Access: X-API-Key ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/transactions/export-quickbooks.csv' \ --header "X-API-Key: $BITCOFY_API_KEY" ``` ### 200 · text/csv Shape illustration: values are examples; actual state may differ. ```text Transaction CSV file. Columns depend on the export format. ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Project API key is required` ## Payouts ## GET /api/v1/projects/{project_id}/payout-requests List Project Payout Requests Access: X-API-Key ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/payout-requests' \ --header "X-API-Key: $BITCOFY_API_KEY" ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `[].request_id` | `string` | Required | Payout approval request identifier. | | `[].project_id` | `string` | Required | Project identifier; must belong to the API key. | | `[].network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `[].asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `[].amount` | `string` | Required | Amount > 0: invoice fiat currency, or payout asset units including fee. Send a decimal string. pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `[].destination_address` | `string` | Required | Recipient address in the selected network. Verify the network before signing. | | `[].status` | `string` | Required | Object state; see the relevant workflow for values and actions. | | `[].idempotency_key` | `string` | Required | Your stable identifier for one logical payout; reuse for reconciliation. | | `[].requested_via` | `string` | Required | Requested Via | | `[].requested_by_user_id` | `string / null` | Optional | Requested By User Id | | `[].approved_by_user_id` | `string / null` | Optional | Approved By User Id | | `[].rejected_by_user_id` | `string / null` | Optional | Rejected By User Id | | `[].approved_payout_id` | `string / null` | Optional | Approved Payout Id | | `[].approved_payout_status` | `string / null` | Optional | Approved Payout Status | | `[].rejection_reason` | `string / null` | Optional | Rejection reason; included verbatim in the signed message. | | `[].note` | `string / null` | Optional | Optional note on the payout request. | | `[].created_at` | `string` | Required | Created At format: date-time | | `[].decided_at` | `string / null` | Optional | Decided At format: date-time | ```json [ { "request_id": "req_demo_001", "project_id": "project_demo_001", "network": "Tron", "asset": "USDT", "amount": "string", "destination_address": "TQ9ExampleDestinationAddress123456789", "status": "ok", "idempotency_key": "action_001", "requested_via": "string", "requested_by_user_id": "string", "approved_by_user_id": "string", "rejected_by_user_id": "string", "approved_payout_id": "payout_demo_001", "approved_payout_status": "string", "rejection_reason": "string", "note": "string", "created_at": "2026-07-13T12:00:00Z", "decided_at": "2026-07-13T12:00:00Z" } ] ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Project API key is required` ## POST /api/v1/projects/{project_id}/payout-requests Create Project Payout Request Access: X-API-Key + X-API-Secret Fee is included in amount. API acceptance does not confirm blockchain broadcast; track payout state. ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | | `X-API-Secret` | header | Required | API secret for this key; required for writes. | | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `amount` | `number / string` | Required | Amount > 0: invoice fiat currency, or payout asset units including fee. Send a decimal string. >: 0; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `destination_address` | `string` | Required | Recipient address in the selected network. Verify the network before signing. | | `idempotency_key` | `string` | Required | Your stable identifier for one logical payout; reuse for reconciliation. min length: 1; max length: 255 | | `note` | `string / null` | Optional | Optional note on the payout request. max length: 500 | ```bash curl --request POST 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/payout-requests' \ --header "X-API-Key: $BITCOFY_API_KEY" \ --header "X-API-Secret: $BITCOFY_API_SECRET" \ --header 'Content-Type: application/json' \ --data '{ "network": "Tron", "asset": "USDT", "amount": "50.00", "destination_address": "TQ9ExampleDestinationAddress123456789", "idempotency_key": "withdraw_001", "note": "Manual withdrawal from merchant UI" }' ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `request_id` | `string` | Required | Payout approval request identifier. | | `project_id` | `string` | Required | Project identifier; must belong to the API key. | | `network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `amount` | `string` | Required | Amount > 0: invoice fiat currency, or payout asset units including fee. Send a decimal string. pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `destination_address` | `string` | Required | Recipient address in the selected network. Verify the network before signing. | | `status` | `string` | Required | Object state; see the relevant workflow for values and actions. | | `idempotency_key` | `string` | Required | Your stable identifier for one logical payout; reuse for reconciliation. | | `requested_via` | `string` | Required | Requested Via | | `requested_by_user_id` | `string / null` | Optional | Requested By User Id | | `approved_by_user_id` | `string / null` | Optional | Approved By User Id | | `rejected_by_user_id` | `string / null` | Optional | Rejected By User Id | | `approved_payout_id` | `string / null` | Optional | Approved Payout Id | | `approved_payout_status` | `string / null` | Optional | Approved Payout Status | | `rejection_reason` | `string / null` | Optional | Rejection reason; included verbatim in the signed message. | | `note` | `string / null` | Optional | Optional note on the payout request. | | `created_at` | `string` | Required | Created At format: date-time | | `decided_at` | `string / null` | Optional | Decided At format: date-time | ```json { "request_id": "req_demo_001", "project_id": "project_demo_001", "network": "Tron", "asset": "USDT", "amount": "string", "destination_address": "TQ9ExampleDestinationAddress123456789", "status": "ok", "idempotency_key": "action_001", "requested_via": "string", "requested_by_user_id": "string", "approved_by_user_id": "string", "rejected_by_user_id": "string", "approved_payout_id": "payout_demo_001", "approved_payout_status": "string", "rejection_reason": "string", "note": "string", "created_at": "2026-07-13T12:00:00Z", "decided_at": "2026-07-13T12:00:00Z" } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `400` | Invalid request or state | Inspect detail, parameters, signature and current state; do not retry unchanged. | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `409` | Payout availability conflict | Inspect error_code and available balance. insufficient_project_reserve: insufficient reserve; insufficient_aggregated_balance: funds not ready to send. Reconcile first. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Payout availability conflict; inspect structured error fields` ## GET /api/v1/projects/{project_id}/payout-requests/by-idempotency/{idempotency_key} Poll Project Payout Request By Idempotency Access: X-API-Key ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `idempotency_key` | path · `string` | Required | Your stable identifier for one logical payout; reuse for reconciliation. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/payout-requests/by-idempotency/YOUR_IDEMPOTENCY_KEY' \ --header "X-API-Key: $BITCOFY_API_KEY" ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `request_id` | `string` | Required | Payout approval request identifier. | | `project_id` | `string` | Required | Project identifier; must belong to the API key. | | `network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `amount` | `string` | Required | Amount > 0: invoice fiat currency, or payout asset units including fee. Send a decimal string. pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `destination_address` | `string` | Required | Recipient address in the selected network. Verify the network before signing. | | `status` | `string` | Required | Object state; see the relevant workflow for values and actions. | | `idempotency_key` | `string` | Required | Your stable identifier for one logical payout; reuse for reconciliation. | | `requested_via` | `string` | Required | Requested Via | | `requested_by_user_id` | `string / null` | Optional | Requested By User Id | | `approved_by_user_id` | `string / null` | Optional | Approved By User Id | | `rejected_by_user_id` | `string / null` | Optional | Rejected By User Id | | `approved_payout_id` | `string / null` | Optional | Approved Payout Id | | `approved_payout_status` | `string / null` | Optional | Approved Payout Status | | `rejection_reason` | `string / null` | Optional | Rejection reason; included verbatim in the signed message. | | `note` | `string / null` | Optional | Optional note on the payout request. | | `created_at` | `string` | Required | Created At format: date-time | | `decided_at` | `string / null` | Optional | Decided At format: date-time | ```json { "request_id": "req_demo_001", "project_id": "project_demo_001", "network": "Tron", "asset": "USDT", "amount": "string", "destination_address": "TQ9ExampleDestinationAddress123456789", "status": "ok", "idempotency_key": "action_001", "requested_via": "string", "requested_by_user_id": "string", "approved_by_user_id": "string", "rejected_by_user_id": "string", "approved_payout_id": "payout_demo_001", "approved_payout_status": "string", "rejection_reason": "string", "note": "string", "created_at": "2026-07-13T12:00:00Z", "decided_at": "2026-07-13T12:00:00Z" } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `404` | Object not found | Verify the identifier and project. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Payout request not found` - `Project API key is required` ## POST /api/v1/projects/{project_id}/payout-requests/{request_id}/approve Approve Project Payout Request Via Api Access: X-API-Key + X-API-Secret Requires API key, API secret and Ed25519 signature. See Signatures for canonical message, UTC, nonce and 5-minute freshness. Fee is included in amount. API acceptance does not confirm blockchain broadcast; track payout state. ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `request_id` | path · `string` | Required | Payout approval request identifier. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | | `X-API-Secret` | header | Required | API secret for this key; required for writes. | | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `nonce` | `string` | Required | Unique value for a new signed attempt; prevents signature replay. min length: 1; max length: 255 | | `timestamp` | `string` | Required | UTC date-time within ±5 minutes. Sign canonical +00:00 representation; see Signatures. format: date-time | | `signature` | `string` | Required | Ed25519 signature of the canonical message, 64 bytes encoded as Base64. min length: 32 | ```bash curl --request POST 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/payout-requests/YOUR_REQUEST_ID/approve' \ --header "X-API-Key: $BITCOFY_API_KEY" \ --header "X-API-Secret: $BITCOFY_API_SECRET" \ --header 'Content-Type: application/json' \ --data '{ "nonce": "nonce_20260713_approve_001", "timestamp": "2026-07-13T12:00:00Z", "signature": "BASE64_ED25519_SIGNATURE" }' ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `request_id` | `string` | Required | Payout approval request identifier. | | `project_id` | `string` | Required | Project identifier; must belong to the API key. | | `network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `amount` | `string` | Required | Amount > 0: invoice fiat currency, or payout asset units including fee. Send a decimal string. pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `destination_address` | `string` | Required | Recipient address in the selected network. Verify the network before signing. | | `status` | `string` | Required | Object state; see the relevant workflow for values and actions. | | `idempotency_key` | `string` | Required | Your stable identifier for one logical payout; reuse for reconciliation. | | `requested_via` | `string` | Required | Requested Via | | `requested_by_user_id` | `string / null` | Optional | Requested By User Id | | `approved_by_user_id` | `string / null` | Optional | Approved By User Id | | `rejected_by_user_id` | `string / null` | Optional | Rejected By User Id | | `approved_payout_id` | `string / null` | Optional | Approved Payout Id | | `approved_payout_status` | `string / null` | Optional | Approved Payout Status | | `rejection_reason` | `string / null` | Optional | Rejection reason; included verbatim in the signed message. | | `note` | `string / null` | Optional | Optional note on the payout request. | | `created_at` | `string` | Required | Created At format: date-time | | `decided_at` | `string / null` | Optional | Decided At format: date-time | ```json { "request_id": "req_demo_001", "project_id": "project_demo_001", "network": "Tron", "asset": "USDT", "amount": "string", "destination_address": "TQ9ExampleDestinationAddress123456789", "status": "ok", "idempotency_key": "action_001", "requested_via": "string", "requested_by_user_id": "string", "approved_by_user_id": "string", "rejected_by_user_id": "string", "approved_payout_id": "payout_demo_001", "approved_payout_status": "string", "rejection_reason": "string", "note": "string", "created_at": "2026-07-13T12:00:00Z", "decided_at": "2026-07-13T12:00:00Z" } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `400` | Invalid request or state | Inspect detail, parameters, signature and current state; do not retry unchanged. | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `409` | Payout availability conflict | Inspect error_code and available balance. insufficient_project_reserve: insufficient reserve; insufficient_aggregated_balance: funds not ready to send. Reconcile first. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Payout availability conflict; inspect structured error fields` ## POST /api/v1/projects/{project_id}/payout-requests/{request_id}/reject Reject Project Payout Request Via Api Access: X-API-Key + X-API-Secret Requires API key, API secret and Ed25519 signature. See Signatures for canonical message, UTC, nonce and 5-minute freshness. Fee is included in amount. API acceptance does not confirm blockchain broadcast; track payout state. ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `request_id` | path · `string` | Required | Payout approval request identifier. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | | `X-API-Secret` | header | Required | API secret for this key; required for writes. | | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `nonce` | `string` | Required | Unique value for a new signed attempt; prevents signature replay. min length: 1; max length: 255 | | `timestamp` | `string` | Required | UTC date-time within ±5 minutes. Sign canonical +00:00 representation; see Signatures. format: date-time | | `signature` | `string` | Required | Ed25519 signature of the canonical message, 64 bytes encoded as Base64. min length: 32 | | `rejection_reason` | `string` | Required | Rejection reason; included verbatim in the signed message. min length: 1; max length: 500 | ```bash curl --request POST 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/payout-requests/YOUR_REQUEST_ID/reject' \ --header "X-API-Key: $BITCOFY_API_KEY" \ --header "X-API-Secret: $BITCOFY_API_SECRET" \ --header 'Content-Type: application/json' \ --data '{ "nonce": "nonce_20260713_reject_001", "timestamp": "2026-07-13T12:00:00Z", "signature": "BASE64_ED25519_SIGNATURE", "rejection_reason": "KYC check failed" }' ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `request_id` | `string` | Required | Payout approval request identifier. | | `project_id` | `string` | Required | Project identifier; must belong to the API key. | | `network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `amount` | `string` | Required | Amount > 0: invoice fiat currency, or payout asset units including fee. Send a decimal string. pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `destination_address` | `string` | Required | Recipient address in the selected network. Verify the network before signing. | | `status` | `string` | Required | Object state; see the relevant workflow for values and actions. | | `idempotency_key` | `string` | Required | Your stable identifier for one logical payout; reuse for reconciliation. | | `requested_via` | `string` | Required | Requested Via | | `requested_by_user_id` | `string / null` | Optional | Requested By User Id | | `approved_by_user_id` | `string / null` | Optional | Approved By User Id | | `rejected_by_user_id` | `string / null` | Optional | Rejected By User Id | | `approved_payout_id` | `string / null` | Optional | Approved Payout Id | | `approved_payout_status` | `string / null` | Optional | Approved Payout Status | | `rejection_reason` | `string / null` | Optional | Rejection reason; included verbatim in the signed message. | | `note` | `string / null` | Optional | Optional note on the payout request. | | `created_at` | `string` | Required | Created At format: date-time | | `decided_at` | `string / null` | Optional | Decided At format: date-time | ```json { "request_id": "req_demo_001", "project_id": "project_demo_001", "network": "Tron", "asset": "USDT", "amount": "string", "destination_address": "TQ9ExampleDestinationAddress123456789", "status": "ok", "idempotency_key": "action_001", "requested_via": "string", "requested_by_user_id": "string", "approved_by_user_id": "string", "rejected_by_user_id": "string", "approved_payout_id": "payout_demo_001", "approved_payout_status": "string", "rejection_reason": "string", "note": "string", "created_at": "2026-07-13T12:00:00Z", "decided_at": "2026-07-13T12:00:00Z" } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `400` | Invalid request or state | Inspect detail, parameters, signature and current state; do not retry unchanged. | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` ## POST /api/v1/payouts Create Payout Access: X-API-Key + X-API-Secret Requires API key, API secret and Ed25519 signature. See Signatures for canonical message, UTC, nonce and 5-minute freshness. Fee is included in amount. API acceptance does not confirm blockchain broadcast; track payout state. ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | | `X-API-Secret` | header | Required | API secret for this key; required for writes. | | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | `string` | Required | Project identifier; must belong to the API key. | | `asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `amount` | `number / string` | Required | Amount > 0: invoice fiat currency, or payout asset units including fee. Send a decimal string. >: 0; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `destination_address` | `string` | Required | Recipient address in the selected network. Verify the network before signing. | | `idempotency_key` | `string` | Required | Your stable identifier for one logical payout; reuse for reconciliation. | | `nonce` | `string` | Required | Unique value for a new signed attempt; prevents signature replay. | | `timestamp` | `string` | Required | UTC date-time within ±5 minutes. Sign canonical +00:00 representation; see Signatures. format: date-time | | `signature` | `string` | Required | Ed25519 signature of the canonical message, 64 bytes encoded as Base64. min length: 32 | ```bash curl --request POST 'https://pay.bitcofy.pro/api/v1/payouts' \ --header "X-API-Key: $BITCOFY_API_KEY" \ --header "X-API-Secret: $BITCOFY_API_SECRET" \ --header 'Content-Type: application/json' \ --data '{ "project_id": "project_demo_001", "network": "Tron", "asset": "USDT", "amount": "25.00", "destination_address": "TQ9ExampleDestinationAddress123456789", "idempotency_key": "payout_001", "nonce": "nonce_20260713_001", "timestamp": "2026-07-13T12:00:00Z", "signature": "BASE64_ED25519_SIGNATURE" }' ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `payout_id` | `string` | Required | Payout identifier. | | `project_id` | `string` | Required | Project identifier; must belong to the API key. | | `request_id` | `string / null` | Optional | Payout approval request identifier. | | `note` | `string / null` | Optional | Optional note on the payout request. | | `operational_expense` | `boolean / null` | Optional | Operational Expense | | `source_scope` | `string / null` | Optional | Source Scope | | `network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `amount` | `string` | Required | Amount > 0: invoice fiat currency, or payout asset units including fee. Send a decimal string. pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `gross_amount` | `string / null` | Optional | Gross Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `net_amount` | `string / null` | Optional | Net Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `fee_amount` | `string` | Optional | Fee Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `provider_fee_amount` | `string` | Optional | Provider Fee Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `total_reserved` | `string / null` | Optional | Total Reserved pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `destination_address` | `string` | Required | Recipient address in the selected network. Verify the network before signing. | | `status` | `string` | Required | Object state; see the relevant workflow for values and actions. | | `provider_status` | `string / null` | Optional | Provider Status | | `final` | `boolean` | Optional | Final default: false | | `funds_reserved` | `boolean` | Optional | Funds Reserved default: false | | `funds_released` | `boolean` | Optional | Funds Released default: false | | `idempotency_key` | `string` | Required | Your stable identifier for one logical payout; reuse for reconciliation. | | `request_nonce` | `string` | Required | Request Nonce | | `request_timestamp` | `string` | Required | Request Timestamp format: date-time | | `gas_mode` | `string / null` | Optional | Gas Mode | | `rental_provider` | `string / null` | Optional | Rental Provider | | `rental_order_id` | `string / null` | Optional | Rental Order Id | | `gas_preparation_status` | `string / null` | Optional | Gas Preparation Status | | `payout_submitted_fee_native` | `string / null` | Optional | Payout Submitted Fee Native pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payout_actual_fee_native` | `string / null` | Optional | Payout Actual Fee Native pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payout_gas_fee_source` | `string / null` | Optional | Payout Gas Fee Source | | `payout_native_required_amount` | `string / null` | Optional | Payout Native Required Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payout_native_current_balance` | `string / null` | Optional | Payout Native Current Balance pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `reserve_floor_reached_for_sweeps` | `boolean / null` | Optional | Reserve Floor Reached For Sweeps | | `tx_hash` | `string / null` | Optional | Tx Hash | | `explorer_url` | `string / null` | Optional | Explorer Url | | `processed_at` | `string / null` | Optional | Processed At format: date-time | | `confirmed_at` | `string / null` | Optional | Confirmed At format: date-time | | `error_reason` | `string / null` | Optional | Error Reason | | `status_history` | `array` | Optional | Status History | | `status_history[].status` | `string` | Required | Object state; see the relevant workflow for values and actions. | | `status_history[].provider_status` | `string / null` | Optional | Provider Status | | `status_history[].event_type` | `string / null` | Optional | Event Type | | `status_history[].final` | `boolean` | Optional | Final default: false | | `status_history[].at` | `string` | Required | At format: date-time | | `status_history[].actor` | `string / null` | Optional | Actor | | `status_history[].reason` | `string / null` | Optional | Reason | ```json { "payout_id": "payout_demo_001", "project_id": "project_demo_001", "request_id": "req_demo_001", "note": "string", "operational_expense": false, "source_scope": "string", "network": "Tron", "asset": "USDT", "amount": "string", "gross_amount": "string", "net_amount": "string", "fee_amount": "0", "provider_fee_amount": "0", "total_reserved": "string", "destination_address": "TQ9ExampleDestinationAddress123456789", "status": "ok", "provider_status": "string", "final": false, "funds_reserved": false, "funds_released": false, "idempotency_key": "action_001", "request_nonce": "nonce_20260713_001", "request_timestamp": "2026-07-13T12:00:00Z", "gas_mode": "string", "rental_provider": "string", "rental_order_id": "order_1001", "gas_preparation_status": "string", "payout_submitted_fee_native": "string", "payout_actual_fee_native": "string", "payout_gas_fee_source": "string", "payout_native_required_amount": "string", "payout_native_current_balance": "string", "reserve_floor_reached_for_sweeps": false, "tx_hash": "0xabc123def456", "explorer_url": "string", "processed_at": "2026-07-13T12:00:00Z", "confirmed_at": "2026-07-13T12:00:00Z", "error_reason": "string", "status_history": [ { "status": "ok", "provider_status": "string", "event_type": "string", "final": false, "at": "2026-07-13T12:00:00Z", "actor": "string", "reason": "string" } ] } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `400` | Invalid request or state | Inspect detail, parameters, signature and current state; do not retry unchanged. | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `409` | Payout availability conflict | Inspect error_code and available balance. insufficient_project_reserve: insufficient reserve; insufficient_aggregated_balance: funds not ready to send. Reconcile first. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Payout availability conflict; inspect structured error fields` ## GET /api/v1/payouts/{payout_id} Get Payout Access: X-API-Key ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `payout_id` | path · `string` | Required | Payout identifier. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/payouts/YOUR_PAYOUT_ID' \ --header "X-API-Key: $BITCOFY_API_KEY" ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `payout_id` | `string` | Required | Payout identifier. | | `project_id` | `string` | Required | Project identifier; must belong to the API key. | | `request_id` | `string / null` | Optional | Payout approval request identifier. | | `note` | `string / null` | Optional | Optional note on the payout request. | | `operational_expense` | `boolean / null` | Optional | Operational Expense | | `source_scope` | `string / null` | Optional | Source Scope | | `network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `amount` | `string` | Required | Amount > 0: invoice fiat currency, or payout asset units including fee. Send a decimal string. pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `gross_amount` | `string / null` | Optional | Gross Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `net_amount` | `string / null` | Optional | Net Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `fee_amount` | `string` | Optional | Fee Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `provider_fee_amount` | `string` | Optional | Provider Fee Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `total_reserved` | `string / null` | Optional | Total Reserved pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `destination_address` | `string` | Required | Recipient address in the selected network. Verify the network before signing. | | `status` | `string` | Required | Object state; see the relevant workflow for values and actions. | | `provider_status` | `string / null` | Optional | Provider Status | | `final` | `boolean` | Optional | Final default: false | | `funds_reserved` | `boolean` | Optional | Funds Reserved default: false | | `funds_released` | `boolean` | Optional | Funds Released default: false | | `idempotency_key` | `string` | Required | Your stable identifier for one logical payout; reuse for reconciliation. | | `request_nonce` | `string` | Required | Request Nonce | | `request_timestamp` | `string` | Required | Request Timestamp format: date-time | | `gas_mode` | `string / null` | Optional | Gas Mode | | `rental_provider` | `string / null` | Optional | Rental Provider | | `rental_order_id` | `string / null` | Optional | Rental Order Id | | `gas_preparation_status` | `string / null` | Optional | Gas Preparation Status | | `payout_submitted_fee_native` | `string / null` | Optional | Payout Submitted Fee Native pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payout_actual_fee_native` | `string / null` | Optional | Payout Actual Fee Native pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payout_gas_fee_source` | `string / null` | Optional | Payout Gas Fee Source | | `payout_native_required_amount` | `string / null` | Optional | Payout Native Required Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payout_native_current_balance` | `string / null` | Optional | Payout Native Current Balance pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `reserve_floor_reached_for_sweeps` | `boolean / null` | Optional | Reserve Floor Reached For Sweeps | | `tx_hash` | `string / null` | Optional | Tx Hash | | `explorer_url` | `string / null` | Optional | Explorer Url | | `processed_at` | `string / null` | Optional | Processed At format: date-time | | `confirmed_at` | `string / null` | Optional | Confirmed At format: date-time | | `error_reason` | `string / null` | Optional | Error Reason | | `status_history` | `array` | Optional | Status History | | `status_history[].status` | `string` | Required | Object state; see the relevant workflow for values and actions. | | `status_history[].provider_status` | `string / null` | Optional | Provider Status | | `status_history[].event_type` | `string / null` | Optional | Event Type | | `status_history[].final` | `boolean` | Optional | Final default: false | | `status_history[].at` | `string` | Required | At format: date-time | | `status_history[].actor` | `string / null` | Optional | Actor | | `status_history[].reason` | `string / null` | Optional | Reason | ```json { "payout_id": "payout_demo_001", "project_id": "project_demo_001", "request_id": "req_demo_001", "note": "string", "operational_expense": false, "source_scope": "string", "network": "Tron", "asset": "USDT", "amount": "string", "gross_amount": "string", "net_amount": "string", "fee_amount": "0", "provider_fee_amount": "0", "total_reserved": "string", "destination_address": "TQ9ExampleDestinationAddress123456789", "status": "ok", "provider_status": "string", "final": false, "funds_reserved": false, "funds_released": false, "idempotency_key": "action_001", "request_nonce": "nonce_20260713_001", "request_timestamp": "2026-07-13T12:00:00Z", "gas_mode": "string", "rental_provider": "string", "rental_order_id": "order_1001", "gas_preparation_status": "string", "payout_submitted_fee_native": "string", "payout_actual_fee_native": "string", "payout_gas_fee_source": "string", "payout_native_required_amount": "string", "payout_native_current_balance": "string", "reserve_floor_reached_for_sweeps": false, "tx_hash": "0xabc123def456", "explorer_url": "string", "processed_at": "2026-07-13T12:00:00Z", "confirmed_at": "2026-07-13T12:00:00Z", "error_reason": "string", "status_history": [ { "status": "ok", "provider_status": "string", "event_type": "string", "final": false, "at": "2026-07-13T12:00:00Z", "actor": "string", "reason": "string" } ] } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `404` | Object not found | Verify the identifier and project. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Payout not found` - `Project API key is required` ## GET /api/v1/projects/{project_id}/payouts/by-idempotency/{idempotency_key} Poll Payout By Idempotency Access: X-API-Key ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `idempotency_key` | path · `string` | Required | Your stable identifier for one logical payout; reuse for reconciliation. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/payouts/by-idempotency/YOUR_IDEMPOTENCY_KEY' \ --header "X-API-Key: $BITCOFY_API_KEY" ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `payout_id` | `string` | Required | Payout identifier. | | `project_id` | `string` | Required | Project identifier; must belong to the API key. | | `request_id` | `string / null` | Optional | Payout approval request identifier. | | `note` | `string / null` | Optional | Optional note on the payout request. | | `operational_expense` | `boolean / null` | Optional | Operational Expense | | `source_scope` | `string / null` | Optional | Source Scope | | `network` | `string` | Required | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `asset` | `string` | Required | Asset code, e.g. USDT. Must be available for this network and project. | | `amount` | `string` | Required | Amount > 0: invoice fiat currency, or payout asset units including fee. Send a decimal string. pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `gross_amount` | `string / null` | Optional | Gross Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `net_amount` | `string / null` | Optional | Net Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `fee_amount` | `string` | Optional | Fee Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `provider_fee_amount` | `string` | Optional | Provider Fee Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `total_reserved` | `string / null` | Optional | Total Reserved pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `destination_address` | `string` | Required | Recipient address in the selected network. Verify the network before signing. | | `status` | `string` | Required | Object state; see the relevant workflow for values and actions. | | `provider_status` | `string / null` | Optional | Provider Status | | `final` | `boolean` | Optional | Final default: false | | `funds_reserved` | `boolean` | Optional | Funds Reserved default: false | | `funds_released` | `boolean` | Optional | Funds Released default: false | | `idempotency_key` | `string` | Required | Your stable identifier for one logical payout; reuse for reconciliation. | | `request_nonce` | `string` | Required | Request Nonce | | `request_timestamp` | `string` | Required | Request Timestamp format: date-time | | `gas_mode` | `string / null` | Optional | Gas Mode | | `rental_provider` | `string / null` | Optional | Rental Provider | | `rental_order_id` | `string / null` | Optional | Rental Order Id | | `gas_preparation_status` | `string / null` | Optional | Gas Preparation Status | | `payout_submitted_fee_native` | `string / null` | Optional | Payout Submitted Fee Native pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payout_actual_fee_native` | `string / null` | Optional | Payout Actual Fee Native pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payout_gas_fee_source` | `string / null` | Optional | Payout Gas Fee Source | | `payout_native_required_amount` | `string / null` | Optional | Payout Native Required Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `payout_native_current_balance` | `string / null` | Optional | Payout Native Current Balance pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `reserve_floor_reached_for_sweeps` | `boolean / null` | Optional | Reserve Floor Reached For Sweeps | | `tx_hash` | `string / null` | Optional | Tx Hash | | `explorer_url` | `string / null` | Optional | Explorer Url | | `processed_at` | `string / null` | Optional | Processed At format: date-time | | `confirmed_at` | `string / null` | Optional | Confirmed At format: date-time | | `error_reason` | `string / null` | Optional | Error Reason | | `status_history` | `array` | Optional | Status History | | `status_history[].status` | `string` | Required | Object state; see the relevant workflow for values and actions. | | `status_history[].provider_status` | `string / null` | Optional | Provider Status | | `status_history[].event_type` | `string / null` | Optional | Event Type | | `status_history[].final` | `boolean` | Optional | Final default: false | | `status_history[].at` | `string` | Required | At format: date-time | | `status_history[].actor` | `string / null` | Optional | Actor | | `status_history[].reason` | `string / null` | Optional | Reason | ```json { "payout_id": "payout_demo_001", "project_id": "project_demo_001", "request_id": "req_demo_001", "note": "string", "operational_expense": false, "source_scope": "string", "network": "Tron", "asset": "USDT", "amount": "string", "gross_amount": "string", "net_amount": "string", "fee_amount": "0", "provider_fee_amount": "0", "total_reserved": "string", "destination_address": "TQ9ExampleDestinationAddress123456789", "status": "ok", "provider_status": "string", "final": false, "funds_reserved": false, "funds_released": false, "idempotency_key": "action_001", "request_nonce": "nonce_20260713_001", "request_timestamp": "2026-07-13T12:00:00Z", "gas_mode": "string", "rental_provider": "string", "rental_order_id": "order_1001", "gas_preparation_status": "string", "payout_submitted_fee_native": "string", "payout_actual_fee_native": "string", "payout_gas_fee_source": "string", "payout_native_required_amount": "string", "payout_native_current_balance": "string", "reserve_floor_reached_for_sweeps": false, "tx_hash": "0xabc123def456", "explorer_url": "string", "processed_at": "2026-07-13T12:00:00Z", "confirmed_at": "2026-07-13T12:00:00Z", "error_reason": "string", "status_history": [ { "status": "ok", "provider_status": "string", "event_type": "string", "final": false, "at": "2026-07-13T12:00:00Z", "actor": "string", "reason": "string" } ] } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `404` | Object not found | Verify the identifier and project. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Payout not found` - `Project API key is required` ## GET /api/v1/projects/{project_id}/payouts/reconcile Reconcile Project Payout Access: X-API-Key Supply exactly one of request_id, payout_id, idempotency_key. Reconcile ambiguous writes before retrying. ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `request_id` | query · `string / null` | Optional | Payout approval request identifier. Supply exactly one of the three identifiers. | | `payout_id` | query · `string / null` | Optional | Payout identifier. Supply exactly one of the three identifiers. | | `idempotency_key` | query · `string / null` | Optional | Your stable identifier for one logical payout; reuse for reconciliation. Supply exactly one of the three identifiers. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/payouts/reconcile?idempotency_key=YOUR_IDEMPOTENCY_KEY' \ --header "X-API-Key: $BITCOFY_API_KEY" ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | `string` | Required | Project identifier; must belong to the API key. | | `query_type` | `string` | Required | Query Type | | `request_id` | `string / null` | Optional | Payout approval request identifier. Supply exactly one of the three identifiers. | | `payout_id` | `string / null` | Optional | Payout identifier. Supply exactly one of the three identifiers. | | `idempotency_key` | `string / null` | Optional | Your stable identifier for one logical payout; reuse for reconciliation. Supply exactly one of the three identifiers. | | `request_status` | `string / null` | Optional | Request Status | | `payout_status` | `string / null` | Optional | Payout Status | | `status` | `string` | Required | Object state; see the relevant workflow for values and actions. | | `provider_status` | `string / null` | Optional | Provider Status | | `final` | `boolean` | Optional | Final default: false | | `funds_reserved` | `boolean` | Optional | Funds Reserved default: false | | `funds_released` | `boolean` | Optional | Funds Released default: false | | `network` | `string / null` | Optional | Network code from /api/v1/public/networks. For payment use the invoice payment_options. | | `asset` | `string / null` | Optional | Asset code, e.g. USDT. Must be available for this network and project. | | `gross_amount` | `string / null` | Optional | Gross Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `fee_amount` | `string` | Optional | Fee Amount default: "0"; pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `net_amount` | `string / null` | Optional | Net Amount pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$ | | `destination_address` | `string / null` | Optional | Recipient address in the selected network. Verify the network before signing. | | `tx_hash` | `string / null` | Optional | Tx Hash | | `explorer_url` | `string / null` | Optional | Explorer Url | | `processed_at` | `string / null` | Optional | Processed At format: date-time | | `confirmed_at` | `string / null` | Optional | Confirmed At format: date-time | | `rejection_reason` | `string / null` | Optional | Rejection reason; included verbatim in the signed message. | | `error_reason` | `string / null` | Optional | Error Reason | | `status_history` | `array` | Optional | Status History | | `status_history[].status` | `string` | Required | Object state; see the relevant workflow for values and actions. | | `status_history[].provider_status` | `string / null` | Optional | Provider Status | | `status_history[].event_type` | `string / null` | Optional | Event Type | | `status_history[].final` | `boolean` | Optional | Final default: false | | `status_history[].at` | `string` | Required | At format: date-time | | `status_history[].actor` | `string / null` | Optional | Actor | | `status_history[].reason` | `string / null` | Optional | Reason | ```json { "project_id": "project_demo_001", "query_type": "string", "request_id": "req_demo_001", "payout_id": "payout_demo_001", "idempotency_key": "action_001", "request_status": "string", "payout_status": "string", "status": "ok", "provider_status": "string", "final": false, "funds_reserved": false, "funds_released": false, "network": "Tron", "asset": "USDT", "gross_amount": "string", "fee_amount": "0", "net_amount": "string", "destination_address": "TQ9ExampleDestinationAddress123456789", "tx_hash": "0xabc123def456", "explorer_url": "string", "processed_at": "2026-07-13T12:00:00Z", "confirmed_at": "2026-07-13T12:00:00Z", "rejection_reason": "string", "error_reason": "string", "status_history": [ { "status": "ok", "provider_status": "string", "event_type": "string", "final": false, "at": "2026-07-13T12:00:00Z", "actor": "string", "reason": "string" } ] } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `400` | Invalid request or state | Inspect detail, parameters, signature and current state; do not retry unchanged. | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `404` | Object not found | Verify the identifier and project. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Provide exactly one of request_id, payout_id, or idempotency_key` - `Payout not found` - `Payout request not found` - `Project API key is required` ## Webhooks ## POST /api/v1/projects/{project_id}/webhook/config Configure Project Webhook Access: X-API-Key + X-API-Secret Saves webhook_url. The compatibility callback_secret field does not rotate the project secret. ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | | `X-API-Secret` | header | Required | API secret for this key; required for writes. | | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `webhook_url` | `string` | Required | Public HTTPS webhook handler URL; no URL user credentials. | | `callback_secret` | `string / null` | Optional | Compatibility field: this endpoint does not rotate the webhook signing secret. min length: 6 | ```bash curl --request POST 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/webhook/config' \ --header "X-API-Key: $BITCOFY_API_KEY" \ --header "X-API-Secret: $BITCOFY_API_SECRET" \ --header 'Content-Type: application/json' \ --data '{ "webhook_url": "https://merchant.example/webhooks/bitcofy" }' ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | `string` | Required | Project identifier; must belong to the API key. | | `webhook_url` | `string` | Required | Public HTTPS webhook handler URL; no URL user credentials. | | `callback_secret_masked` | `string` | Required | Callback Secret Masked | ```json { "project_id": "project_demo_001", "webhook_url": "https://merchant.example/api/bitcofy/webhook", "callback_secret_masked": "secret_123456" } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `400` | Invalid request or state | Inspect detail, parameters, signature and current state; do not retry unchanged. | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `404` | Object not found | Verify the identifier and project. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Project not found` ## POST /api/v1/projects/{project_id}/webhook/test Queue Test Webhook Access: X-API-Key + X-API-Secret Queues an event. Success does not mean your receiver has already accepted it. ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | | `X-API-Secret` | header | Required | API secret for this key; required for writes. | No request body. ```bash curl --request POST 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/webhook/test' \ --header "X-API-Key: $BITCOFY_API_KEY" \ --header "X-API-Secret: $BITCOFY_API_SECRET" ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `event_id` | `string` | Required | Event Id | | `event_type` | `string` | Required | Event Type | | `delivered` | `boolean` | Required | Delivered | | `dead` | `boolean` | Required | Dead | | `attempts` | `integer` | Required | Attempts | | `last_error` | `string / null` | Optional | Last Error | | `last_response_status` | `integer / null` | Optional | Last Response Status | | `next_attempt_at` | `string / null` | Optional | Next Attempt At format: date-time | | `delivered_at` | `string / null` | Optional | Delivered At format: date-time | | `payload` | `object` | Required | Payload | ```json { "event_id": "string", "event_type": "string", "delivered": false, "dead": false, "attempts": 1, "last_error": "string", "last_response_status": 1, "next_attempt_at": "2026-07-13T12:00:00Z", "delivered_at": "2026-07-13T12:00:00Z", "payload": { "example_key": "string" } } ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `400` | Invalid request or state | Inspect detail, parameters, signature and current state; do not retry unchanged. | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `404` | Object not found | Verify the identifier and project. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Project not found` - `Project webhook_url or callback_secret is not configured` ## GET /api/v1/projects/{project_id}/webhook/events List Project Webhook Events Access: X-API-Key ### Parameters | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `project_id` | path · `string` | Required | Project identifier; must belong to the API key. | | `X-API-Key` | header | Required* | Project key. Alternative: Authorization: Bearer . | No request body. ```bash curl --request GET 'https://pay.bitcofy.pro/api/v1/projects/YOUR_PROJECT_ID/webhook/events' \ --header "X-API-Key: $BITCOFY_API_KEY" ``` ### 200 · application/json Shape illustration: values are examples; actual state may differ. | Field | Type | Presence | Meaning & constraints | | --- | --- | --- | --- | | `[].event_id` | `string` | Required | Event Id | | `[].event_type` | `string` | Required | Event Type | | `[].delivered` | `boolean` | Required | Delivered | | `[].dead` | `boolean` | Required | Dead | | `[].attempts` | `integer` | Required | Attempts | | `[].last_error` | `string / null` | Optional | Last Error | | `[].last_response_status` | `integer / null` | Optional | Last Response Status | | `[].next_attempt_at` | `string / null` | Optional | Next Attempt At format: date-time | | `[].delivered_at` | `string / null` | Optional | Delivered At format: date-time | | `[].payload` | `object` | Required | Payload | ```json [ { "event_id": "string", "event_type": "string", "delivered": false, "dead": false, "attempts": 1, "last_error": "string", "last_response_status": 1, "next_attempt_at": "2026-07-13T12:00:00Z", "delivered_at": "2026-07-13T12:00:00Z", "payload": { "example_key": "string" } } ] ``` ### Errors Handler errors are listed below. detail depends on validation and state; its text is not a stable error code. After a 5xx, a write outcome may be unknown: reconcile first. | HTTP | Meaning | Action | | --- | --- | --- | | `401` | Invalid credentials | Check the API key, active state and write secret. | | `403` | Access denied | Check project ownership and activation; checkout session calls also need the invoice cookie. | | `422` | Validation failed | detail is an array: loc identifies the field, msg explains the error, type is its code. Correct required fields and types. | | `423` | Project locked | Check project activation and restrictions in the dashboard. Do not retry unchanged. | - `API key does not have access to this project` - `Project API key is required`