Skip to content



For more detailed API specs, see our OpenAPI Docs

Posting and enriching transactions

You can POST transactions to the /transactions endpoint, where the body of the expected request is of the following format:

  "transactions": [
      "description": "string",
      "amount": -50.00,
      "currency": "USD",
      "timestamp": "2020-11-24T18:46:13.683Z",
      "end_user_id": "string",
      "account_id": "string",
      "reference_id": "string",
      "transaction_code": "string",
      "mcc_code": "7641",
      "categories_default": "string"

Where the fields are as follows:

  • description (string)* Transaction description.
  • amount (float)* Transaction amount. We expect account inflows (credits) to be positive, account outflows (debits) to be negative. For transactions pulled with Plaid, please flip the amount sign for all transactions.
  • currency (string)* 3 letter ISO code for currency, e.g., USD
  • timestamp (timestamp)* Timestamp of the transaction
  • end_user_id (string)* Unique identifier for the end user (i.e. your customer or applicant) who generated this transaction
  • account_id (string) Unique identifier for the account of the end user that contains the transaction. (Plaid: transactions.account_id; Yodlee: transaction.accountId; Finicity: transaction.accountId; Truelayer: account_id)
  • reference_id (string) Unique identifier for the transaction
  • transaction_code (string) Refers a general description of the payment method. (Plaid: payment_channel; Yodlee: transaction.type; Finicity: transaction.type; Truelayer: results.transaction_category)
  • mcc_code (string) is the 4 digit Merchant category code
  • categories_default (string or list of string) Can be be used to pass any categories provided with the data. (Plaid: transactions.category; Yodlee: transaction.category, Finicity: transaction.categorisation.category; Truelayer:results.transaction_classification)

* Required

Example request:

curl --location --request POST '' \
--header '<your-authorisation>' \
--header 'Content-Type: application/json' \
--data-raw '{
    "transactions": [
        "amount": -4000,
        "currency": "USD",
        "description": "STRIPE TRANSFER ST-CY098123KA TECHNOLOGY INC"

Response includes a summary and transactions field:

  "_summary": {
    "transactions_loaded": 1,
    "transactions_categorised": 1
  "transactions": [
        "description_clean": "cleaner_description",
        "merchant": {
            "heron_id": "mrc_nF5uQ1LPBJn5RErH8QGeTH",
            "name": "merchant_name",
            "url": "",
            "logo_url": ""
        "is_recurring": true,
        "has_matching_transaction": true,
        "is_potential_duplicate": false,
        "categories": [
                "label": "some_category_label",
                "annotator_priority_type": "annotator_source_for_label",
                "confidence": 0.9,
                "model_version": "string",
                "heron_id": "ctg_nF5uQxLPBJn5RErH8QGeTH"


  • description_clean (string) is a substring of the original description string.
  • merchant (dict) contains the clean name of the merchant (not necessarily a substring of the original description) and the associated url for display back to your customer. We also return a heron_id which is a unique identifier for the merchant.
  • is_recurring (boolean) indicates recurrence of transactions
  • has_matching_transaction (boolean) indicates whether a corresponding transaction (inverse amount with timestamp in close proximity) exists
  • is_potential_duplicate (boolean) flags whether this transaction may be duplicated in the batch of transactions
  • categories (dict) contains the category label (from your specific taxonomy), the source of the annotation (manual_review, heuristics or classifier), the confidence where applicable, model version, and heron_id which is a unique identifier for the category.

Here, you can use the task_id to retrieve transactions for asynchronous categorisation jobs and labels with improved accuracy / confidence at a later point in time

Reading transactions

As expected, you can also issue GET requests to the /transactions endpoint. This returns a paginated response. You can modify the request with the following optional query parameters:

  • from_date (date) filters for earliest uploaded date for transaction of form YYYY-MM-DD, inclusive
  • to_date (date) filters for latest uploaded date for transaction of form YYYY-MM-DD, inclusive
  • end_user_id (string) filters for end_user_id (if any) associated uploaded transactions
  • task_id (string) filters for task ID associated with the POST request that uploaded the transaction
  • page (integer) page number for pagination, default 1
  • limit (integer) items to return per page, default 100

An example request would look like:

curl --location --request GET '' \
--header '<your-authorisation>'

Which would yield a response similar to:

    "_summary": {
        "transactions": 0,
        "returned_transactions": 0
    "_meta": {
        "page": 2,
        "pages": 0,
        "per_page": 20,
        "next_url": null,
        "prev_url": "/api/transactions?from_date=2020-11-15&page=1&limit=20&to_date=2020-11-20&task_id=8f1a7b43-b650-47dd-b04f-efeaf457ab01"
    "transactions": [

Where _meta contains the information necessary to navigate through the pagination.