Search & metadata

Search via Typesense

Turn on Typesense and run a full-text search across your ledger.

Blnk supports Typesense for search and indexing. You can use it to retrieve ledgers, balances, transactions, and identities with filtering, sorting, faceting, and full-text search.

To enable Typesense search and indexing, set up your Typesense configuration. Until you do, Typesense search and indexing stay disabled by default.

Once Typesense is enabled, use the Search API when you need to:

  • Filter large datasets efficiently
  • Perform full-text searches across your data
  • Aggregate and count values with faceting
  • Sort and paginate results for better performance
  • Combine multiple search conditions in a single request

Searchable collections

The Search API works with four main collections in your Blnk ledger:

CollectionEndpointDescription
Transactions/search/transactionsSearch through all transaction records
Balances/search/balancesFind balance records across all ledgers
Ledgers/search/ledgersLocate specific ledgers by name or metadata
Identities/search/identitiesSearch customer identity records

Quick start

To get started with the Search API, use the endpoint: /search/{collection} where collection can be ledgers, balances, identities, or transactions.

Here’s how a full search request looks:

curl -X POST "http://localhost:5001/search/transactions" \
  -H "X-blnk-key: <api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "q": "bulk_baaea495-148a-4b16-b171-68c92fb911a6",
    "query_by": "parent_transaction",
    "filter_by": "status:=APPLIED && currency:=USD",
    "sort_by": "created_at:desc",
    "page": 1,
    "per_page": 10
  }'
const response = await blnk.Search.search(
  {
    q: 'bulk_baaea495-148a-4b16-b171-68c92fb911a6',
    query_by: 'parent_transaction',
    filter_by: 'status:=APPLIED && currency:=USD',
    sort_by: 'created_at:desc',
    page: 1,
    per_page: 10,
  },
  'transactions',
);
results, _, _ := client.Search.SearchDocument(
    blnkgo.SearchParams{
        Q: "bulk_baaea495-148a-4b16-b171-68c92fb911a6",
        QueryBy: "parent_transaction",
        FilterBy: "status:=APPLIED && currency:=USD",
        SortBy: "created_at:desc",
        Page: 1,
        PerPage: 10,
    },
    blnkgo.Transactions,
)
response = blnk.search.search(
  {
    "q": "bulk_baaea495-148a-4b16-b171-68c92fb911a6",
    "query_by": "parent_transaction",
    "filter_by": "status:=APPLIED && currency:=USD",
    "sort_by": "created_at:desc",
    "page": 1,
    "per_page": 10,
  },
  "transactions",
)
ApiResponse<JsonNode> response = blnk.search().search(
    SearchParams.create()
        .q("bulk_baaea495-148a-4b16-b171-68c92fb911a6")
        .queryBy("parent_transaction")
        .filterBy("status:=APPLIED && currency:=USD")
        .sortBy("created_at:desc")
        .page(1)
        .perPage(10),
    "transactions"
);
{
  "facet_counts": [],
  "found": 2,
  "hits": [
    {
      "document": {
        "amount": 532,
        "amount_string": "532",
        "atomic": false,
        "created_at": 1758116489,
        "currency": "USD",
        "description": "Test bulk",
        "destination": "bln_20666087-1355-4736-ba04-3ba92a7542b9",
        "effective_date": 1758116489,
        "id": "txn_cd728825-a6e1-4fae-9277-c3235a045ea5",
        "parent_transaction": "bulk_baaea495-148a-4b16-b171-68c92fb911a6",
        "precise_amount": 53200,
        "precision": 100,
        "reference": "bulk-search-1d2",
        "source": "bln_93fb50c2-969e-49c2-bb61-ef5ed245516e",
        "status": "APPLIED",
        "transaction_id": "txn_cd728825-a6e1-4fae-9277-c3235a045ea5"
      },
      "highlights": [
        {
          "field": "parent_transaction",
          "matched_tokens": ["bulk_baaea495-148a-4b16-b171-68c92fb911a6"],
          "snippet": "<mark>bulk_baaea495-148a-4b16-b171-68c92fb911a6</mark>"
        }
      ],
      "text_match": 578730123365711993
    },
    {
      "document": {
        "amount": 100,
        "amount_string": "100",
        "atomic": false,
        "created_at": 1758116489,
        "currency": "USD",
        "description": "Test bulk",
        "destination": "bln_d298f2b8-fdd6-4d0e-ade7-3cddcea90a8d",
        "effective_date": 1758116489,
        "id": "txn_0ae624a5-7fbc-4c67-831d-f888e928d4bc",
        "parent_transaction": "bulk_baaea495-148a-4b16-b171-68c92fb911a6",
        "precise_amount": 10000,
        "precision": 100,
        "reference": "bulk-search-2d3",
        "source": "bln_6592f225-f8fe-48cd-8974-51974dc83a3a",
        "status": "APPLIED",
        "transaction_id": "txn_0ae624a5-7fbc-4c67-831d-f888e928d4bc"
      },
      "highlights": [
        {
          "field": "parent_transaction",
          "matched_tokens": ["bulk_baaea495-148a-4b16-b171-68c92fb911a6"],
          "snippet": "<mark>bulk_baaea495-148a-4b16-b171-68c92fb911a6</mark>"
        }
      ],
      "text_match": 578730123365711993
    }
  ],
  "out_of": 232,
  "page": 1,
  "request_params": {
    "collection_name": "transactions",
    "per_page": 10,
    "q": "bulk_baaea495-148a-4b16-b171-68c92fb911a6"
  },
  "search_cutoff": false,
  "search_time_ms": 2
}

Request parameters

ParameterDescriptionRequiredType
qThe search query text. Use * to return all records. Learn moreYesstring
query_byComma-separated list of fields to search in. Learn moreNostring
filter_byFilter conditions to refine results. Learn moreNostring
facet_byComma-separated list of fields to aggregate and count. Learn moreNostring
sort_bySorting conditions for ordering results. Learn moreNostring
pagePage number for pagination. Starts at 1. Learn moreNointeger
per_pageNumber of results per page. Maximum 250, default 10. Learn moreNointeger

Response structure

FieldDescriptionType
foundTotal number of matching records.integer
hitsArray of search results, each containing a document with the record data.array
out_ofTotal number of records in the collection.integer
pageCurrent page number.integer
search_time_msTime taken to execute the search in milliseconds.integer
facet_countsAggregated counts for faceted fields. Only present when using facet_by. Learn morearray
highlightsSearch term highlighting information for matched fields.array

Common use cases

1. Transaction analysis

Find all transactions for a specific account

Get a complete transaction history by searching for all transactions where a particular balance ID appears as either source or destination.

curl -X POST "http://localhost:5001/search/transactions" \
  -H "X-blnk-key: <api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "q": "bln_28f25ef6-2e0d-4fa6-891c-37fc409d654e",
    "query_by": "source,destination",
    "sort_by": "created_at:desc"
  }'
const response = await blnk.Search.search(
  {
    q: "bln_28f25ef6-2e0d-4fa6-891c-37fc409d654e",
    query_by: "source,destination",
    sort_by: "created_at:desc",
  },
  'transactions',
);
results, _, _ := client.Search.SearchDocument(
    blnkgo.SearchParams{
        Q: "bln_28f25ef6-2e0d-4fa6-891c-37fc409d654e",
        QueryBy: "source,destination",
        SortBy: "created_at:desc",
    },
    blnkgo.Transactions,
)
response = blnk.search.search(
  {
    "q": "bln_28f25ef6-2e0d-4fa6-891c-37fc409d654e",
    "query_by": "source,destination",
    "sort_by": "created_at:desc",
  },
  "transactions",
)
ApiResponse<JsonNode> response = blnk.search().search(
    SearchParams.create()
        .q("bln_28f25ef6-2e0d-4fa6-891c-37fc409d654e")
        .queryBy("source,destination")
        .sortBy("created_at:desc"),
    "transactions"
);

Get recent high-value transactions

Find transactions above a certain amount threshold to monitor large money movements or flag suspicious activity.

curl -X POST "http://localhost:5001/search/transactions" \
  -H "X-blnk-key: <api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "q": "*",
    "filter_by": "amount:>10000",
    "sort_by": "created_at:desc",
    "per_page": 50
  }'
const response = await blnk.Search.search(
  {
    q: "*",
    filter_by: "amount:>10000",
    sort_by: "created_at:desc",
    per_page: 50,
  },
  'transactions',
);
results, _, _ := client.Search.SearchDocument(
    blnkgo.SearchParams{
        Q: "*",
        FilterBy: "amount:>10000",
        SortBy: "created_at:desc",
        PerPage: 50,
    },
    blnkgo.Transactions,
)
response = blnk.search.search(
  {
    "q": "*",
    "filter_by": "amount:>10000",
    "sort_by": "created_at:desc",
    "per_page": 50,
  },
  "transactions",
)
ApiResponse<JsonNode> response = blnk.search().search(
    SearchParams.create()
        .q("*")
        .filterBy("amount:>10000")
        .sortBy("created_at:desc")
        .perPage(50),
    "transactions"
);

Search transactions by date range

Retrieve all transactions that occurred within a specific time period for reporting or audit purposes. Use Unix timestamps for date filtering.

curl -X POST "http://localhost:5001/search/transactions" \
  -H "X-blnk-key: <api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "q": "*",
    "filter_by": "created_at:[1704067200..1706745599]",
    "sort_by": "created_at:desc"
  }'
const response = await blnk.Search.search(
  {
    q: "*",
    filter_by: "created_at:[1704067200..1706745599]",
    sort_by: "created_at:desc",
  },
  'transactions',
);
results, _, _ := client.Search.SearchDocument(
    blnkgo.SearchParams{
        Q: "*",
        FilterBy: "created_at:[1704067200..1706745599]",
        SortBy: "created_at:desc",
    },
    blnkgo.Transactions,
)
response = blnk.search.search(
  {
    "q": "*",
    "filter_by": "created_at:[1704067200..1706745599]",
    "sort_by": "created_at:desc",
  },
  "transactions",
)
ApiResponse<JsonNode> response = blnk.search().search(
    SearchParams.create()
        .q("*")
        .filterBy(
            "created_at:[1704067200..1706745599]"
        )
        .sortBy("created_at:desc"),
    "transactions"
);

Find rejected transactions

Filter transactions by status to identify failed payments that were rejected due to insufficient funds or validation errors.

curl -X POST "http://localhost:5001/search/transactions" \
  -H "X-blnk-key: <api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "q": "*",
    "filter_by": "status:=REJECTED",
    "sort_by": "created_at:desc"
  }'
const response = await blnk.Search.search(
  {
    q: "*",
    filter_by: "status:=REJECTED",
    sort_by: "created_at:desc",
  },
  'transactions',
);
results, _, _ := client.Search.SearchDocument(
    blnkgo.SearchParams{
        Q: "*",
        FilterBy: "status:=REJECTED",
        SortBy: "created_at:desc",
    },
    blnkgo.Transactions,
)
response = blnk.search.search(
  {
    "q": "*",
    "filter_by": "status:=REJECTED",
    "sort_by": "created_at:desc",
  },
  "transactions",
)
ApiResponse<JsonNode> response = blnk.search().search(
    SearchParams.create()
        .q("*")
        .filterBy("status:=REJECTED")
        .sortBy("created_at:desc"),
    "transactions"
);

Search by transaction type or description

Use full-text search to find transactions based on transaction type in metadata or descriptions for customer support.

curl -X POST "http://localhost:5001/search/transactions" \
  -H "X-blnk-key: <api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "q": "payment",
    "query_by": "meta_data.transaction_type,description",
    "sort_by": "created_at:desc"
  }'
const response = await blnk.Search.search(
  {
    q: "payment",
    query_by: "meta_data.transaction_type,description",
    sort_by: "created_at:desc",
  },
  'transactions',
);
results, _, _ := client.Search.SearchDocument(
    blnkgo.SearchParams{
        Q: "payment",
        QueryBy: "meta_data.transaction_type,description",
        SortBy: "created_at:desc",
    },
    blnkgo.Transactions,
)
response = blnk.search.search(
  {
    "q": "payment",
    "query_by": "meta_data.transaction_type,description",
    "sort_by": "created_at:desc",
  },
  "transactions",
)
ApiResponse<JsonNode> response = blnk.search().search(
    SearchParams.create()
        .q("payment")
        .queryBy("meta_data.transaction_type,description")
        .sortBy("created_at:desc"),
    "transactions"
);

Find transactions between specific accounts

Search for transactions that occurred between two particular balance IDs to track money flow or analyze trading patterns.

curl -X POST "http://localhost:5001/search/transactions" \
  -H "X-blnk-key: <api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "q": "*",
    "filter_by": "source:=bln_28f25ef6-2e0d-4fa6-891c-37fc409d654e && '\
'destination:=bln_86ba7976-499d-4282-955e-a7c2abf5db12",
    "sort_by": "created_at:desc"
  }'
const filterBy =
  "source:=bln_28f25ef6-2e0d-4fa6-891c-37fc409d654e" +
  " && destination:=bln_86ba7976-499d-4282-955e-a7c2abf5db12";

const response = await blnk.Search.search(
  {
    q: "*",
    filter_by: filterBy,
    sort_by: "created_at:desc",
  },
  'transactions',
);
filterBy := "source:=bln_28f25ef6-2e0d-4fa6-891c-37fc409d654e" +
    " && destination:=bln_86ba7976-499d-4282-955e-a7c2abf5db12"

results, _, _ := client.Search.SearchDocument(
    blnkgo.SearchParams{
        Q: "*",
        FilterBy: filterBy,
        SortBy: "created_at:desc",
    },
    blnkgo.Transactions,
)
filter_by = (
  "source:=bln_28f25ef6-2e0d-4fa6-891c-37fc409d654e"
  " && destination:=bln_86ba7976-499d-4282-955e-a7c2abf5db12"
)

response = blnk.search.search(
  {
    "q": "*",
    "filter_by": filter_by,
    "sort_by": "created_at:desc",
  },
  "transactions",
)
String filterBy =
    "source:=bln_28f25ef6-2e0d-4fa6-891c-37fc409d654e"
        + " && destination:=bln_86ba7976-499d-4282-955e-a7c2abf5db12";

ApiResponse<JsonNode> response = blnk.search().search(
    SearchParams.create()
        .q("*")
        .filterBy(filterBy)
        .sortBy("created_at:desc"),
    "transactions"
);

2. Account management

Get balances above/below a threshold

Find all balances with amounts greater than or less than specific values for risk management or account monitoring.

curl -X POST "http://localhost:5001/search/balances" \
  -H "X-blnk-key: <api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "q": "*",
    "filter_by": "balance:>100000",
    "sort_by": "balance:desc"
  }'
const response = await blnk.Search.search(
  {
    q: "*",
    filter_by: "balance:>100000",
    sort_by: "balance:desc",
  },
  'balances',
);
results, _, _ := client.Search.SearchDocument(
    blnkgo.SearchParams{
        Q: "*",
        FilterBy: "balance:>100000",
        SortBy: "balance:desc",
    },
    blnkgo.Balances,
)
response = blnk.search.search(
  {
    "q": "*",
    "filter_by": "balance:>100000",
    "sort_by": "balance:desc",
  },
  "balances",
)
ApiResponse<JsonNode> response = blnk.search().search(
    SearchParams.create()
        .q("*")
        .filterBy("balance:>100000")
        .sortBy("balance:desc"),
    "balances"
);

Fetch all balances belonging to an identity

Retrieve all balances associated with a specific identity ID to get a complete view of a user’s accounts and wallets.

curl -X POST "http://localhost:5001/search/balances" \
  -H "X-blnk-key: <api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "q": "*",
    "filter_by": "identity_id:=idt_28f25ef6-2e0d-4fa6-891c-37fc409d654e",
    "sort_by": "created_at:desc"
  }'
const response = await blnk.Search.search(
  {
    q: "*",
    filter_by:
      "identity_id:=idt_28f25ef6-2e0d-4fa6-891c-37fc409d654e",
    sort_by: "created_at:desc",
  },
  'balances',
);
results, _, _ := client.Search.SearchDocument(
    blnkgo.SearchParams{
        Q: "*",
        FilterBy: "identity_id:=idt_28f25ef6-2e0d-4fa6-891c-37fc409d654e",
        SortBy: "created_at:desc",
    },
    blnkgo.Balances,
)
response = blnk.search.search(
  {
    "q": "*",
    "filter_by": "identity_id:=idt_28f25ef6-2e0d-4fa6-891c-37fc409d654e",
    "sort_by": "created_at:desc",
  },
  "balances",
)
ApiResponse<JsonNode> response = blnk.search().search(
    SearchParams.create()
        .q("*")
        .filterBy(
            "identity_id:=idt_28f25ef6-2e0d-4fa6-891c-37fc409d654e"
        )
        .sortBy("created_at:desc"),
    "balances"
);

Search ledgers by name or metadata

Find specific ledgers using partial name matching or metadata filters to locate the right ledger for operations.

curl -X POST "http://localhost:5001/search/ledgers" \
  -H "X-blnk-key: <api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "q": "customer savings",
    "query_by": "name",
    "sort_by": "created_at:desc"
  }'
const response = await blnk.Search.search(
  {
    q: "customer savings",
    query_by: "name",
    sort_by: "created_at:desc",
  },
  'ledgers',
);
results, _, _ := client.Search.SearchDocument(
    blnkgo.SearchParams{
        Q: "customer savings",
        QueryBy: "name",
        SortBy: "created_at:desc",
    },
    blnkgo.Ledgers,
)
response = blnk.search.search(
  {
    "q": "customer savings",
    "query_by": "name",
    "sort_by": "created_at:desc",
  },
  "ledgers",
)
ApiResponse<JsonNode> response = blnk.search().search(
    SearchParams.create()
        .q("customer savings")
        .queryBy("name")
        .sortBy("created_at:desc"),
    "ledgers"
);

3. Customer support

Search identities by name or email

Find specific customer identities using partial name matching or email addresses for customer support and account verification.

curl -X POST "http://localhost:5001/search/identities" \
  -H "X-blnk-key: <api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "q": "john doe",
    "query_by": "first_name,last_name,email",
    "sort_by": "created_at:desc"
  }'
const response = await blnk.Search.search(
  {
    q: "john doe",
    query_by: "first_name,last_name,email",
    sort_by: "created_at:desc",
  },
  'identities',
);
results, _, _ := client.Search.SearchDocument(
    blnkgo.SearchParams{
        Q: "john doe",
        QueryBy: "first_name,last_name,email",
        SortBy: "created_at:desc",
    },
    blnkgo.Identities,
)
response = blnk.search.search(
  {
    "q": "john doe",
    "query_by": "first_name,last_name,email",
    "sort_by": "created_at:desc",
  },
  "identities",
)
ApiResponse<JsonNode> response = blnk.search().search(
    SearchParams.create()
        .q("john doe")
        .queryBy("first_name,last_name,email")
        .sortBy("created_at:desc"),
    "identities"
);