Skip to content
Documentation

Account operations

These endpoints cover balances, refunds, payouts and dispute responses. They use the same keys and request helpers as the payment endpoints.

EndpointPurpose
GET /api/account/balanceBalance
GET /api/account/available-balanceWithdrawable balance
POST /api/account/refundsRefund or void a payment
GET /api/account/refunds[/{id}]List or retrieve refunds
POST /api/account/withdrawalsRequest a USDT payout
GET /api/account/withdrawals[/{id}]List or retrieve payouts
GET /api/account/disputes[/{id}]List or retrieve disputes
POST /api/account/disputes/{id}/evidenceRespond to a dispute

Conventions

  • Signing, headers and Idempotency-Key work as described in Authentication.
  • A single item is returned as a plain JSON object; lists are returned as { "data": [...], "meta": {...} }.
  • Payment, refund, withdrawal and dispute IDs use LUVEI-ABCD-123456. Store the complete ID.
  • Balances and payouts use the system main currency; refunds and disputes use the currency of the payment.
  • 201 or 202 means that the request was accepted, not completed. Track the status or the webhooks.
  • To test outcomes with a sandbox key, see Sandbox and test cards.

Pagination

FieldTypeRequiredDescription
pageinteger · queryOptionalPage number, starting at 1.
per_pageinteger · queryOptionalItems per page, from 1 to 100. Default: 20.
statusstring · queryOptionalReturns only items with this status.
FieldTypeDescription
pageintegerCurrent page.
per_pageintegerItems per page.
totalintegerNumber of matching items.
total_pagesintegerNumber of pages (0 if the list is empty).

Items are sorted newest first. A page beyond the last one returns 200 with an empty data. A page below 1, a per_page outside 1–100, an unknown status or an unknown parameter returns 422 1000001. Date filters are not supported.

List response · Example

{
  "data": [
    {
      "id": "LUVEI-RFND-100001",
      "operation": "refund",
      "status": "requested",
      "amount": "100.00",
      "currency": "USD",
      "reason": "Customer requested a full refund",
      "provider_reference": null,
      "provider_refunded_at": null,
      "created_at": "2026-11-02T09:00:00.000Z",
      "updated_at": null,
      "payment_id": "LUVEI-PAYN-123456",
      "environment": "live"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 20,
    "total": 1,
    "total_pages": 1
  }
}
GET/api/account/balance

Balance

Retrieve your balance and the amount currently available for withdrawal. Both calls are read-only and report your API wallet, which holds the funds collected through this API. Other wallets in your panel are neither shown nor included.

FieldTypeDescription
currency_codestringCurrency of all amounts: the system main currency.
available_amountstringSettled funds in your API wallet that are available for use now. Unsettled and held amounts are excluded.
pending_settlement_amountstringFunds from payments that have not yet settled. Always 0.00 in sandbox.
environmentstringsandbox or live.
./payniko.sh GET '/api/account/balance'
import {api} from './payniko.mjs';

const balance = await api('GET', '/api/account/balance');
console.log(balance);
<?php
require __DIR__ . '/payniko.php';

$balance = payniko_api('GET', '/api/account/balance');
print_r($balance);
from payniko import api

balance = api("GET", "/api/account/balance")
print(balance)

Response · Example

{
  "currency_code": "USD",
  "available_amount": "1250.00",
  "pending_settlement_amount": "300.00",
  "environment": "live"
}

Payments in other currencies are converted to the main currency. Fees and settlement dates are not included in this response.

GET/api/account/available-balance

Withdrawable balance

FieldTypeDescription
currency_codestringThe system main currency.
withdrawable_amountstringSettled funds in your API wallet that can be withdrawn now. This is exactly the amount that POST /api/account/withdrawals allows you to pay out.
can_withdrawbooleanfalse while any of your balances is negative, in which case no payout is possible. true does not guarantee a payout.
environmentstringsandbox or live.
./payniko.sh GET '/api/account/available-balance'
import {api} from './payniko.mjs';

const available = await api('GET', '/api/account/available-balance');
console.log(available);
<?php
require __DIR__ . '/payniko.php';

$available = payniko_api('GET', '/api/account/available-balance');
print_r($available);
from payniko import api

available = api("GET", "/api/account/available-balance")
print(available)

Response · Example

{
  "currency_code": "USD",
  "withdrawable_amount": "1250.00",
  "can_withdraw": true,
  "environment": "live"
}

Amounts reserved for open payouts, unsettled funds and holds are excluded. The balance is checked again when you request a payout, so the request can still fail with 409 9000020.

POST/api/account/refundsIdempotency-Key required

Request a refund or void

Return the full amount of a successful payment to the payer. Each request is reviewed and processed by Payniko; 202 only confirms that the request was accepted.

Request body

FieldTypeRequiredDescriptionExample
payment_idstring · LUVEI-ABCD-123456RequiredA succeeded payment created through /api/payments in the same environment. Any other ID returns 404 9000009.LUVEI-PAYN-123456
operation_typestringRequiredThe requested operation.
refundvoid
refund
reasonstringRequired3–500 characters. Reviewed by the Payniko operations team.Customer requested a full refund

There is no amount field; the full payment amount is returned. A payment can have only one refund or void at a time. While one is open or completed, or while the payment has a dispute that was not won, a new request returns 409 9000014.

KEY="$(openssl rand -hex 16)"  # store with the order before sending; reuse it after network errors
./payniko.sh POST '/api/account/refunds' '{
  "payment_id": "LUVEI-PAYN-123456",
  "operation_type": "refund",
  "reason": "Customer requested a full refund"
}' "$KEY"
import {api, randomUUID} from './payniko.mjs';

const key = randomUUID(); // Store this key with the order before sending; reuse it after network errors.
const refund = await api('POST', '/api/account/refunds', {
  "payment_id": "LUVEI-PAYN-123456",
  "operation_type": "refund",
  "reason": "Customer requested a full refund"
}, key);
console.log(refund);
<?php
require __DIR__ . '/payniko.php';

$key = bin2hex(random_bytes(16)); // store with the order; reuse it after network errors
$refund = payniko_api('POST', '/api/account/refunds', [
    "payment_id" => 'LUVEI-PAYN-123456',
    "operation_type" => 'refund',
    "reason" => 'Customer requested a full refund',
], $key);
print_r($refund);
from payniko import api
import uuid

key = str(uuid.uuid4())  # store with the order; reuse it after network errors
refund = api("POST", "/api/account/refunds", {
    "payment_id": "LUVEI-PAYN-123456",
    "operation_type": "refund",
    "reason": "Customer requested a full refund"
}, key)
print(refund)

Response · Example

{
  "id": "LUVEI-RFND-100001",
  "operation": "refund",
  "status": "requested",
  "amount": "100.00",
  "currency": "USD",
  "reason": "Customer requested a full refund",
  "provider_reference": null,
  "provider_refunded_at": null,
  "created_at": "2026-11-02T09:00:00.000Z",
  "updated_at": null,
  "payment_id": "LUVEI-PAYN-123456",
  "environment": "live"
}

Response · 202

Returns the refund. Resending the same key and body returns 202 with the same refund.

Possible errors

List and retrieve refunds

./payniko.sh GET '/api/account/refunds?status=completed&page=1&per_page=20'
import {api} from './payniko.mjs';

const refunds = await api('GET', '/api/account/refunds?status=completed&page=1&per_page=20');
console.log(refunds);
<?php
require __DIR__ . '/payniko.php';

$refunds = payniko_api('GET', '/api/account/refunds?status=completed&page=1&per_page=20');
print_r($refunds);
from payniko import api

refunds = api("GET", "/api/account/refunds?status=completed&page=1&per_page=20")
print(refunds)
FieldTypeRequiredDescription
pageinteger · queryOptionalPage number, starting at 1.
per_pageinteger · queryOptionalItems per page, from 1 to 100. Default: 20.
statusstring · queryOptionalReturns only refunds with this status.
operation_typestring · queryOptionalrefund or void.

GET /api/account/refunds/{id} returns a single refund (404 9000009 if it does not exist). The list contains the refunds requested through the API.

Refund object

FieldTypeDescription
idstring · LUVEI-ABCD-123456Refund ID.
operationstringrefund or void, as sent in operation_type.
statusstringSee the table below.
amountstringFull amount of the payment.
currencystringCurrency of the payment.
reasonstringThe reason provided in the request.
provider_referencestring | nullReference of the processed refund, once available.
provider_refunded_atstring · date-time | nullTime at which the refund was processed, if known.
created_atstring · date-timeTime of the request.
updated_atstring · date-time | nullTime of the last change.
payment_idstring · LUVEI-ABCD-123456 | nullThe refunded payment.
environmentstringsandbox or live.
StatusMeaning
requestedAccepted but not yet processed.
processingBeing processed.
awaiting_provider_manualBeing completed manually; this can take longer.
completedCompleted. Final status.
rejectedRejected. Final status.
failedFailed. Final status.
cancelledCancelled. Final status.

GET /api/account/refunds/{id} always returns the current status. The outcome is also delivered as a webhook.

POST/api/account/withdrawalsIdempotency-Key required

Request a payout

Pay out funds from your API wallet as USDT on the TRON network (TRC20). The amount is reserved and sent after review.

Request body

FieldTypeRequiredDescriptionExample
amountstringRequiredTwo decimal places, for example 50.00; must not be 0.00 and must be at least your minimum. Together with today's requested and sent payouts, it must stay within your daily limit."50.00"
addressstringRequiredTRC20 address: 34 characters, starting with T, with a valid checksum.YOUR_VERIFIED_TRC20_ADDRESS
address_acknowledgedbooleanRequiredMust be true, confirming that the address is correct.true
webhook_urlstring · uriRequiredEndpoint that receives the webhooks for this payout. The same rules as for payments apply.https://merchant.example/webhooks/withdrawals

success_url and fail_url are not permitted in this request.

# Replace YOUR_VERIFIED_TRC20_ADDRESS with the address you confirmed with its owner.
KEY="$(openssl rand -hex 16)"  # store with the order before sending; reuse it after network errors
./payniko.sh POST '/api/account/withdrawals' '{
  "amount": "50.00",
  "address": "YOUR_VERIFIED_TRC20_ADDRESS",
  "address_acknowledged": true,
  "webhook_url": "https://merchant.example/webhooks/withdrawals"
}' "$KEY"
import {api, randomUUID} from './payniko.mjs';

// Replace YOUR_VERIFIED_TRC20_ADDRESS with the address you confirmed with its owner.
const key = randomUUID(); // Store this key with the order before sending; reuse it after network errors.
const withdrawal = await api('POST', '/api/account/withdrawals', {
  "amount": "50.00",
  "address": "YOUR_VERIFIED_TRC20_ADDRESS",
  "address_acknowledged": true,
  "webhook_url": "https://merchant.example/webhooks/withdrawals"
}, key);
console.log(withdrawal);
<?php
require __DIR__ . '/payniko.php';

// Replace YOUR_VERIFIED_TRC20_ADDRESS with the address you confirmed with its owner.
$key = bin2hex(random_bytes(16)); // store with the order; reuse it after network errors
$withdrawal = payniko_api('POST', '/api/account/withdrawals', [
    "amount" => '50.00',
    "address" => 'YOUR_VERIFIED_TRC20_ADDRESS',
    "address_acknowledged" => true,
    "webhook_url" => 'https://merchant.example/webhooks/withdrawals',
], $key);
print_r($withdrawal);
from payniko import api
import uuid

# Replace YOUR_VERIFIED_TRC20_ADDRESS with the address you confirmed with its owner.
key = str(uuid.uuid4())  # store with the order; reuse it after network errors
withdrawal = api("POST", "/api/account/withdrawals", {
    "amount": "50.00",
    "address": "YOUR_VERIFIED_TRC20_ADDRESS",
    "address_acknowledged": True,
    "webhook_url": "https://merchant.example/webhooks/withdrawals"
}, key)
print(withdrawal)

Response · Example

{
  "id": "LUVEI-WTHD-100002",
  "status": "requested",
  "amount": "50.00",
  "currency": "USD",
  "asset": "USDT",
  "network": "TRC20",
  "address": "YOUR_VERIFIED_TRC20_ADDRESS",
  "usdt_amount": "49.950000",
  "tx_hash": null,
  "rejection_reason": null,
  "requested_at": "2026-11-02T10:00:00.000Z",
  "processed_at": null,
  "created_at": "2026-11-02T10:00:00.000Z",
  "environment": "live"
}

Response · 201

Returns the payout with its status, usually requested. Resending the same key and body returns 201 with the same payout.

Possible errors

List and retrieve payouts

./payniko.sh GET '/api/account/withdrawals?status=requested&page=1&per_page=20'
import {api} from './payniko.mjs';

const withdrawals = await api('GET', '/api/account/withdrawals?status=requested&page=1&per_page=20');
console.log(withdrawals);
<?php
require __DIR__ . '/payniko.php';

$withdrawals = payniko_api('GET', '/api/account/withdrawals?status=requested&page=1&per_page=20');
print_r($withdrawals);
from payniko import api

withdrawals = api("GET", "/api/account/withdrawals?status=requested&page=1&per_page=20")
print(withdrawals)

Filter by status. GET /api/account/withdrawals/{id} returns a single payout (404 9000023 if it does not exist).

Withdrawal object

FieldTypeDescription
idstring · LUVEI-ABCD-123456Payout ID.
statusstringSee the table below.
requestedsentrejected
amountstringRequested amount in the main currency.
currencystringThe main currency.
assetstringAlways USDT.
networkstringAlways TRC20.
addressstringDestination address.
usdt_amountstringUSDT amount to be sent (six decimal places).
tx_hashstring | nullBlockchain transaction hash, once known.
rejection_reasonstring | nullReason for the rejection.
requested_atstring · date-timeTime of the request.
processed_atstring · date-time | nullTime at which the payout was sent or rejected.
created_atstring · date-timeTime of creation.
environmentstringsandbox or live.
StatusMeaning
requestedCreated; the amount is reserved but not yet sent.
sentSent. Final status. tx_hash can initially be null and is added later.
rejectedNot sent; the reserved amount is returned to your available balance. See rejection_reason. Final status.

The Payniko team sends or rejects each payout and then sets processed_at, together with tx_hash or rejection_reason. During maintenance, a new payout request can return 503 1000014.

GET/api/account/disputes

List and retrieve disputes

A dispute (chargeback) is opened when a cardholder contests a payment with their bank. When the dispute opens, the amount is usually deducted from your balance; it is returned if you win and remains deducted if you lose. Respond before the deadline.

./payniko.sh GET '/api/account/disputes?status=open&page=1&per_page=20'
import {api} from './payniko.mjs';

const disputes = await api('GET', '/api/account/disputes?status=open&page=1&per_page=20');
console.log(disputes);
<?php
require __DIR__ . '/payniko.php';

$disputes = payniko_api('GET', '/api/account/disputes?status=open&page=1&per_page=20');
print_r($disputes);
from payniko import api

disputes = api("GET", "/api/account/disputes?status=open&page=1&per_page=20")
print(disputes)

Response · Example

{
  "data": [
    {
      "id": "LUVEI-DSPT-100003",
      "service": "api",
      "amount": "100.00",
      "currency": "USD",
      "status": "open",
      "reason": "product_not_delivered",
      "reason_note": null,
      "occurred_on": "2026-11-03",
      "evidence_due_at": "2026-11-10T09:00:00.000Z",
      "evidence_submitted_at": null,
      "merchant_evidence_note": null,
      "merchant_evidence_submitted_at": null,
      "resolved_at": null,
      "created_at": "2026-11-03T09:00:00.000Z",
      "payment_id": "LUVEI-PAYN-123456",
      "environment": "sandbox"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 20,
    "total": 1,
    "total_pages": 1
  }
}

Filter by status. GET /api/account/disputes/{id} returns a single dispute (404 9000015 if it does not exist). The list contains all disputes on your account; payment_id is set when the dispute relates to an API payment.

Dispute object

FieldTypeDescription
idstring · LUVEI-ABCD-123456Dispute ID.
servicestringOrigin of the payment, for example api.
amountstringDisputed amount in the payment currency.
currencystringCurrency of the payment.
statusstringSee the table below.
openunder_reviewwonlost
reasonstringReason provided by the bank. Handle unknown values as well.
fraudunauthorizedproduct_not_deliveredduplicateamount_mismatchother
reason_notestring | nullNote from the bank, if any.
occurred_onstring · dateDate of the dispute (YYYY-MM-DD).
evidence_due_atstring · date-time | nullDeadline for your response.
evidence_submitted_atstring · date-time | nullTime at which the defence was submitted to the bank.
merchant_evidence_notestring | nullYour most recent response.
merchant_evidence_submitted_atstring · date-time | nullTime at which you submitted your response.
resolved_atstring · date-time | nullTime at which the dispute was decided.
created_atstring · date-timeTime of creation.
payment_idstring · LUVEI-ABCD-123456 | nullThe disputed API payment; otherwise null.
environmentstringsandbox or live.
StatusMeaning
openNew dispute. You can respond until evidence_due_at.
under_reviewThe defence has been submitted to the bank and a decision is pending. You can still respond until the deadline.
wonDecided in your favour. Final status.
lostDecided against you. Final status.
POST/api/account/disputes/{id}/evidenceIdempotency-Key required

Respond to a dispute

Request body

FieldTypeRequiredDescription
notestringRequiredYour response, 3–4000 characters: delivery details, communication with the customer and the evidence you hold.
KEY="$(openssl rand -hex 16)"  # store with the order before sending; reuse it after network errors
./payniko.sh POST '/api/account/disputes/LUVEI-DSPT-100003/evidence' '{
  "note": "The order was delivered on 2026-10-28; tracking number and signed receipt are available."
}' "$KEY"
import {api, randomUUID} from './payniko.mjs';

const key = randomUUID(); // Store this key with the order before sending; reuse it after network errors.
const dispute = await api('POST', '/api/account/disputes/LUVEI-DSPT-100003/evidence', {
  "note": "The order was delivered on 2026-10-28; tracking number and signed receipt are available."
}, key);
console.log(dispute);
<?php
require __DIR__ . '/payniko.php';

$key = bin2hex(random_bytes(16)); // store with the order; reuse it after network errors
$dispute = payniko_api('POST', '/api/account/disputes/LUVEI-DSPT-100003/evidence', [
    "note" => 'The order was delivered on 2026-10-28; tracking number and signed receipt are available.',
], $key);
print_r($dispute);
from payniko import api
import uuid

key = str(uuid.uuid4())  # store with the order; reuse it after network errors
dispute = api("POST", "/api/account/disputes/LUVEI-DSPT-100003/evidence", {
    "note": "The order was delivered on 2026-10-28; tracking number and signed receipt are available."
}, key)
print(dispute)

Response · Example

{
  "id": "LUVEI-DSPT-100003",
  "service": "api",
  "amount": "100.00",
  "currency": "USD",
  "status": "open",
  "reason": "product_not_delivered",
  "reason_note": null,
  "occurred_on": "2026-11-03",
  "evidence_due_at": "2026-11-10T09:00:00.000Z",
  "evidence_submitted_at": null,
  "merchant_evidence_note": "The order was delivered on 2026-10-28; tracking number and signed receipt are available.",
  "merchant_evidence_submitted_at": "2026-11-04T08:00:00.000Z",
  "resolved_at": null,
  "created_at": "2026-11-03T09:00:00.000Z",
  "payment_id": "LUVEI-PAYN-123456",
  "environment": "sandbox"
}

Response · 200

Returns the dispute including your note.

  • Accepted only while the dispute is open or under_review and before evidence_due_at; otherwise the request returns 409 9000016.
  • A new request with a new Idempotency-Key replaces your previous note.
  • File uploads are not supported through the API. Describe the available evidence in the note.

Possible errors

To test disputes with a sandbox key, create one with POST /api/sandbox/disputes.