Skip to main content

7. Transaction History

GET /api/v1/transactions

Returns PayIn and PayOut operations that belong to the authenticated merchant and selected shop. The examples on this page use a BDT shop.

Currency and shop scope

The endpoint does not accept a currency filter. It reads one shop that belongs to the authenticated merchant: shop_code selects it, or the configured default shop is used. The API does not enforce the currency of this documentation site; the request, amount filters, and returned rows use the selected shop's currency. The examples below use BDT. Historical reads also work for an inactive shop.

Authentication

Canonical HMAC v2 is recommended for this endpoint because it signs the HTTP method, path, filters, timestamp, request ID, and body hash.

HeaderRequiredDescription
X-API-KeyYesAPI key issued to the merchant.
X-TimestampYesISO-8601 timestamp, for example 2026-07-16T12:00:00Z. The default allowed skew is ±60 seconds. UNIX timestamps are not accepted.
X-Request-IdFor HMAC v2Unique value of 1–128 characters matching [A-Za-z0-9._:-]+.
X-Signature-VersionFor HMAC v2Send v2.
X-SignatureYesLowercase hexadecimal HMAC-SHA256 signature.

The v2 signature payload is:

v2
GET
/api/v1/transactions
CANONICAL_QUERY
X_TIMESTAMP
X_REQUEST_ID
SHA256_HEX_OF_EMPTY_BODY

Join these seven values with a single LF byte (0x0A) and no trailing LF. CANONICAL_QUERY is recursively sorted by key and encoded using RFC 3986. For the recommended request below it is:

date_from=2026-07-01&date_to=2026-07-16&pagination_mode=cursor&per_page=5&shop_code=your_bdt_shop&transaction_type=all

The lowercase SHA-256 hex digest of an empty GET body is e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855. Compute the lowercase hex HMAC-SHA256 of the canonical payload with the API secret. Use a fresh timestamp, request ID, and signature for every page request; reusing a request ID is rejected as replay.

The merchant IP whitelist is enforced when it is enabled. A disallowed source IP receives HTTP 403. During the staged migration, the server may temporarily accept the legacy HMAC_SHA256(secret, timestamp + body) signature. New integrations should always implement v2, and an environment may require it for this endpoint.

Query parameters

ParameterTypeRequiredDescription
transaction_typestringNopayout, payin, or all. Default: payout.
shop_codestringNoSelected merchant shop code, maximum 64 characters. The configured default shop is used when omitted.
statusstringNoExternal merchant status from Statuses, maximum 64 characters. It must be valid for the selected transaction type; with all, it may belong to either type. Internal statuses are rejected.
idsCSVNo1–100 unique positive HRS operation IDs; raw query value maximum 4096 characters.
transaction_idsCSVNo1–100 unique merchant external_id values; each maximum 255 and raw value maximum 8192 characters.
cardsCSVNo1–100 unique exact card numbers, each containing 6–19 digits; raw value maximum 4096 characters.
date_from, date_toYYYY-MM-DDNoInclusive operation creation-date range in UTC.
finalization_from, finalization_toYYYY-MM-DDNoInclusive finalization-date range in UTC.
amount_min, amount_maxdecimal stringNoInclusive non-negative amount range in the selected shop's currency. Maximum 64 characters; signs and exponent notation are not accepted.
pagination_modestringNooffset (default) or cursor. Cursor mode avoids page shifts caused by ordinary newer inserts but is not a snapshot.
pageintegerNoOffset page, starting from 1. Not allowed in cursor mode.
cursorstringNoOpaque next_cursor or prev_cursor, maximum 2048 characters; only valid in cursor mode.
per_pageintegerNoRecords per page. Default: 50; maximum: 100.

Unknown parameters, invalid ranges, duplicate/empty CSV values, and amount_min > amount_max return HTTP 422.

Unsupported filters

There is no tag filter and no currency parameter. Unknown parameters such as tags, currency, phones, or recipients are rejected instead of being ignored.

GET /api/v1/transactions?transaction_type=all&shop_code=your_bdt_shop&date_from=2026-07-01&date_to=2026-07-16&pagination_mode=cursor&per_page=5
Accept: application/json
X-API-Key: YOUR_API_KEY
X-Timestamp: 2026-07-16T12:00:00Z
X-Request-Id: 019f6b40-c562-77b2-bc42-11b9ac4db85c
X-Signature-Version: v2
X-Signature: CALCULATED_HMAC_SHA256

Example response

This example contains five operations and assumes that another page is available.

{
"transactions": {
"data": [
{"id":105,"status":"success","external_id":"PIN-BDT-002","amount":"7500.00","currency":"BDT","shop_code":"your_bdt_shop","transaction_type":"payin","created_at":"2026-07-16T09:05:00+00:00","updated_at":"2026-07-16T09:06:00+00:00","finalization_date":"2026-07-16T09:06:00+00:00","type":"payIn"},
{"id":104,"status":"pending","external_id":"PAY-BDT-003","amount":"12000.00","currency":"BDT","shop_code":"your_bdt_shop","card_number":"411111******1111","transaction_type":"payout","created_at":"2026-07-16T09:04:00+00:00","updated_at":"2026-07-16T09:04:00+00:00","type":"payOut"},
{"id":103,"status":"pending","external_id":"PIN-BDT-001","amount":"5000.00","currency":"BDT","shop_code":"your_bdt_shop","transaction_type":"payin","created_at":"2026-07-16T09:03:00+00:00","updated_at":"2026-07-16T09:03:00+00:00","type":"payIn"},
{"id":102,"status":"success","external_id":"PAY-BDT-002","amount":"25000.00","currency":"BDT","shop_code":"your_bdt_shop","card_number":"555555******4444","transaction_type":"payout","created_at":"2026-07-16T09:02:00+00:00","updated_at":"2026-07-16T09:02:30+00:00","finalization_date":"2026-07-16T09:02:30+00:00","type":"payOut"},
{"id":101,"status":"pending","external_id":"PAY-BDT-001","amount":"10000.00","currency":"BDT","shop_code":"your_bdt_shop","card_number":"411111******1111","transaction_type":"payout","created_at":"2026-07-16T09:01:00+00:00","updated_at":"2026-07-16T09:01:00+00:00","type":"payOut"}
],
"path": "https://api.payfield.io/api/v1/transactions",
"per_page": 5,
"next_cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNi0wNy0xNlQwOTowMTowMCswMDowMCIsImlkIjoxMDEsIl9wb2ludHNUb05leHRJdGVtcyI6dHJ1ZX0",
"next_page_url": "https://api.payfield.io/api/v1/transactions?transaction_type=all&shop_code=your_bdt_shop&date_from=2026-07-01&date_to=2026-07-16&pagination_mode=cursor&per_page=5&cursor=eyJjcmVhdGVkX2F0IjoiMjAyNi0wNy0xNlQwOTowMTowMCswMDowMCIsImlkIjoxMDEsIl9wb2ludHNUb05leHRJdGVtcyI6dHJ1ZX0",
"prev_cursor": null,
"prev_page_url": null
}
}

Rows are ordered by created_at descending and then by id descending. The response is generated from the selected shop's merchant response schema. Optional fields with no value are omitted, and configured safe fields can vary by shop. The canonical type field is reserved and is always payIn or payOut.

Pagination behavior

ModeRequestResponse
OffsetOmit pagination_mode or send offset; use page.Calculates total and returns Laravel length-aware pagination metadata.
CursorSend pagination_mode=cursor; repeat all filters with the returned cursor.Includes next_cursor, prev_cursor, and cursor URLs. It does not calculate total.

The exact offset envelope contains current_page, data, first_page_url, from, last_page, last_page_url, links, next_page_url, path, per_page, prev_page_url, to, and total inside transactions.

Cursor mode is recommended for long exports because new rows inserted ahead of the current cursor do not shift later pages. It is not a database snapshot: status, amount, or finalization changes between requests can change the matching set. Keep all filters unchanged and create a fresh X-Timestamp, X-Request-Id, and HMAC v2 signature for every page request.

If the cards filter is used, page-navigation fields first_page_url, last_page_url, next_page_url, prev_page_url, and URLs inside links are null; the non-sensitive path remains. Repeat the card filter explicitly together with page or cursor.

Response fields

FieldApplies toDescription
idBothInternal HRS operation ID.
external_idBothMerchant operation identifier.
statusBothExternal merchant status, never an internal processing status.
amount, old_amountBothDecimal strings in the operation currency; old_amount is omitted when unavailable.
currencyBothISO currency code; BDT in this example.
shop_codeBothShop that owns the operation.
card_numberPayOutCard-number representation returned by the selected shop's merchant response schema, when available.
merchant_user_id, merchant_user_ipBothMerchant-side user references when supplied.
callback_urlBothCallback URL when supplied.
transaction_typeBothTechnical value: payin or payout.
typeBothReserved canonical value: payIn or payOut; always present.
created_at, updated_atBothISO-8601 timestamps with UTC offset.
finalization_dateBothFinalization timestamp in UTC, when available.
paymentDataPayIn/configured schemasMerchant-visible payment data after schema filtering.
payment_page_url, payment_page_expires_atPayIn payment pageHosted page URL and UTC expiry time when available.

Errors

HTTPCondition and response
401Missing/invalid API key, timestamp, signature, signature version, or request ID; expired timestamp; invalid signature; or replay. Authentication responses can contain only message.
403{"message":"IP not allowed"} when the merchant IP whitelist is enabled and the source is not allowed.
422Invalid/unknown filters or shop resolution failure. Filter validation uses code: validation_error; shop failures use code: shop_resolution_failed.
429Rate limit exceeded. The response contains error.code: rate_limit_exceeded, error.retry_after, and the Retry-After header.
503{"message":"Replay protection unavailable"} when HMAC v2 replay storage is unavailable.

Example validation response for an unsupported tags filter:

{
"message": "Unsupported query parameters: tags",
"code": "validation_error",
"error": {
"code": "validation_error",
"message": "Unsupported query parameters: tags",
"details": {"errors":{"query":["Unsupported query parameters: tags"]}}
},
"details": {"errors":{"query":["Unsupported query parameters: tags"]}},
"errors": {"query":["Unsupported query parameters: tags"]}
}

See API Errors for errors shared with other merchant endpoints.