Turn raw financial transactions
into structured merchant intelligence.

One API call takes the messy string from a bank or card statement and returns the merchant, category, logo and a confidence score.

Input
NETFLIX.COM 4029357689

A subscription charge with a reference number appended.

POST /v1/enrich → output
{
  "merchant_name": "Netflix",
  "category": "Subscriptions & OTT",
  "subcategory": "OTT - International",
  "country": null,
  "logo_url": "https://www.google.com/s2/favicons?domain=netflix.com&sz=128",
  "confidence": 0.99
}
1,219merchants with full profiles
9,136name variants recognised
43categories
3.2.0+af7d1cc4current engine

Get a test API key

Instant and free. No approval step.


It's now filled into the snippets below and the playground.

Make your first request

curl -X POST https://financial-core-production.up.railway.app/v1/enrich \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"description": "NETFLIX.COM 4029357689"}'
import requests

resp = requests.post(
    "https://financial-core-production.up.railway.app/v1/enrich",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={"description": "NETFLIX.COM 4029357689"},
    timeout=10,
)
resp.raise_for_status()
print(resp.json()["merchant_name"])
const res = await fetch("https://financial-core-production.up.railway.app/v1/enrich", {
  method: "POST",
  headers: {
    "Authorization": "Bearer YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ description: "NETFLIX.COM 4029357689" }),
});
const data = await res.json();
console.log(data.merchant_name);
package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
)

func main() {
	body := bytes.NewBufferString(`{"description": "NETFLIX.COM 4029357689"}`)
	req, _ := http.NewRequest("POST", "https://financial-core-production.up.railway.app/v1/enrich", body)
	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
	req.Header.Set("Content-Type", "application/json")
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	out, _ := io.ReadAll(resp.Body)
	fmt.Println(string(out))
}
require "net/http"
require "json"

uri = URI("https://financial-core-production.up.railway.app/v1/enrich")
req = Net::HTTP::Post.new(uri, "Authorization" => "Bearer YOUR_API_KEY", "Content-Type" => "application/json")
req.body = { description: "NETFLIX.COM 4029357689" }.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") { |http| http.request(req) }
puts JSON.parse(res.body)["merchant_name"]
<?php
$ch = curl_init("https://financial-core-production.up.railway.app/v1/enrich");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ["Authorization: Bearer YOUR_API_KEY", "Content-Type: application/json"],
    CURLOPT_POSTFIELDS => json_encode(["description" => "NETFLIX.COM 4029357689"]),
]);
$data = json_decode(curl_exec($ch), true);
echo $data["merchant_name"];
import java.net.URI;
import java.net.http.*;

public class Main {
    public static void main(String[] args) throws Exception {
        HttpRequest req = HttpRequest.newBuilder(URI.create("https://financial-core-production.up.railway.app/v1/enrich"))
            .header("Authorization", "Bearer YOUR_API_KEY")
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString("{\"description\": \"NETFLIX.COM 4029357689\"}"))
            .build();
        HttpResponse<String> res = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());
        System.out.println(res.body());
    }
}
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "YOUR_API_KEY");
var content = new StringContent("{\"description\": \"NETFLIX.COM 4029357689\"}", Encoding.UTF8, "application/json");
var res = await client.PostAsync("https://financial-core-production.up.railway.app/v1/enrich", content);
Console.WriteLine(await res.Content.ReadAsStringAsync());

Built to drop into any stack

Plain REST + JSON

One endpoint, one header. If your language can make an HTTPS request, you can integrate.

OpenAPI spec

Download it to generate a typed client in any language, or import into Postman.

Stable by contract

v1 never removes or renames fields, so the engine can keep improving without breaking you.

Batch & limits

Up to 100 transactions per call, clear rate-limit headers, safe retries.

Consistent errors

Every failure has a machine-readable code and a request_id.

Explainable

Each result says how it matched and what it matched on.