> ## Documentation Index
> Fetch the complete documentation index at: https://docs.context.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Transaction Enrichment

> Turn raw card and bank statement descriptors into a structured company profile with logos, colors, industry codes, and socials using the Brand API.

Context.dev's Transaction Enrichment API takes a raw card or ACH descriptor (e.g., `AMZN*MKTP US`) and returns:

* `title` and `domain`: clean company name and domain
* `logos`: SVG/PNG variants in light, dark, and on-background modes
* `colors`: hex codes of colors from the merchant's logo
* `industries.eic`: industry + subindustry classification
* `stock`: ticker and exchange for publicly traded merchants
* And more: `socials`, `address`, `links`, `description`, `slogan`

Our database has 50M+ identified merchants. You can also find small and local merchants by passing `mcc`, `city`, `country_gl`, or `phone`.

<Prompt description="Integrate Context.dev's Transaction Enrichment in your app" icon="sparkles" actions={["copy", "cursor"]}>
  I'm integrating Context.dev's transaction lookup through `POST /brand/retrieve` into my app. Help me:

  1. Install the official SDK for my language (`context.dev` on npm / PyPI / RubyGems, `context-dev/context-dev-php` on Packagist, `github.com/context-dot-dev/context-go-sdk` for Go).
  2. Read the API key from the `CONTEXT_DEV_API_KEY` environment variable. Never hardcode it.
  3. Call `client.brand.retrieve({ transaction_info, mcc?, country_gl?, city?, phone?, high_confidence_only? })`. The response is the standard `brand` envelope.
  4. Always pass `mcc` (4-digit Merchant Category Code) and `country_gl` (ISO 3166-1 alpha-2) when I have them. They sharply disambiguate small merchants and regional variants.
  5. Set `high_confidence_only: true` for spend analytics or compliance flows where a wrong match is worse than no match.
  6. Treat HTTP 400 ("could not be identified") as a normal outcome. Fall back to a cleaned descriptor + MCC-based category icon, and cache misses for at least 24 hours.
  7. Cache successful matches by a normalized merchant key (strip terminal IDs, ticket numbers, store numbers) so `STARBUCKS #12345` and `STARBUCKS #67890` share the same enrichment.

  Docs: [https://docs.context.dev/guides/enrich-transaction-codes](https://docs.context.dev/guides/enrich-transaction-codes)
</Prompt>

## Prerequisites

* **A Context.dev API key.** Sign up at [context.dev/signup](https://context.dev/signup), copy the key from the [dashboard](https://context.dev/dashboard) (prefix `ctxt_secret_`), and export it:

  ```bash theme={null}
  export CONTEXT_DEV_API_KEY="ctxt_secret_..."
  ```

* **An SDK (optional).** Install for your language, or skip the install and call directly with `curl`:

  <CodeGroup>
    ```bash TypeScript theme={null}
    npm install context.dev
    ```

    ```bash Python theme={null}
    pip install context.dev
    ```

    ```bash Ruby theme={null}
    gem install context.dev
    ```

    ```bash Go theme={null}
    go get github.com/context-dot-dev/context-go-sdk
    ```

    ```bash PHP theme={null}
    composer require context-dev/context-dev-php
    ```
  </CodeGroup>

## Identify a transaction

`POST /brand/retrieve` takes a raw descriptor in `transaction_info` and resolves it to a merchant brand. Pass MCC and geography hints when you have them: they collapse ambiguity sharply on small or regional merchants.

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.context.dev/v1/brand/retrieve \
    -X POST \
    -H "Authorization: Bearer $CONTEXT_DEV_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "transaction_info": "STARBUCKS STORE 12345",
      "mcc": "5814",
      "country_gl": "us"
    }'
  ```

  ```typescript TypeScript theme={null}
  import ContextDev from "context.dev";

  const client = new ContextDev({ apiKey: process.env.CONTEXT_DEV_API_KEY });

  const response = await client.brand.retrieve({
    transaction_info: "STARBUCKS STORE 12345",
    mcc: "5814",
    country_gl: "us",
  });

  console.log(response.brand.domain, response.brand.title);
  ```

  ```python Python theme={null}
  import os
  from context.dev import ContextDev

  client = ContextDev(api_key=os.environ["CONTEXT_DEV_API_KEY"])

  response = client.brand.retrieve(
      transaction_info="STARBUCKS STORE 12345",
      mcc="5814",
      country_gl="us",
  )

  print(response.brand.domain, response.brand.title)
  ```

  ```ruby Ruby theme={null}
  require "context_dev"

  client = ContextDev::Client.new(api_key: ENV.fetch("CONTEXT_DEV_API_KEY"))

  response = client.brand.retrieve(
    transaction_info: "STARBUCKS STORE 12345",
    mcc: "5814",
    country_gl: :us,
  )

  puts "#{response.brand.domain} #{response.brand.title}"
  ```

  ```go Go theme={null}
  package main

  import (
      "context"
      "fmt"
      "os"

      contextdev "github.com/context-dot-dev/context-go-sdk"
      "github.com/context-dot-dev/context-go-sdk/option"
      "github.com/context-dot-dev/context-go-sdk/packages/param"
  )

  func main() {
      client := contextdev.NewClient(
          option.WithAPIKey(os.Getenv("CONTEXT_DEV_API_KEY")),
      )

      response, err := client.Brand.Retrieve(context.TODO(), contextdev.BrandRetrieveParams{
          TransactionInfo: "STARBUCKS STORE 12345",
          Mcc:             param.NewOpt("5814"),
          CountryGl:       contextdev.BrandRetrieveParamsCountryGlUs,
      })
      if err != nil {
          panic(err)
      }

      fmt.Printf("%s %s\n", response.Brand.Domain, response.Brand.Title)
  }
  ```

  ```php PHP theme={null}
  <?php

  use ContextDev\Client;

  $client = new Client(apiKey: getenv('CONTEXT_DEV_API_KEY'));

  $response = $client->brand->retrieve(
      transactionInfo: 'STARBUCKS STORE 12345',
      mcc: '5814',
      countryGl: 'us',
  );

  echo $response->brand->domain, ' ', $response->brand->title, PHP_EOL;
  ```
</CodeGroup>

<Badge color="blue" icon="coins">
  10 credits per successful call
</Badge>

### Request Parameters

| Parameter              | Type                                   | Description                                                                                                                                                                                                                                                                                        |
| ---------------------- | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `transaction_info`     | string                                 | **Required.** Raw transaction descriptor (e.g. `AMZN MKTP US*2X7Y8Z`, `SQ *COFFEE SHOP NYC`).                                                                                                                                                                                                      |
| `mcc`                  | string                                 | 4-digit Merchant Category Code. The resolver maintains an MCC database with specific descriptions; otherwise it falls back to a general category based on the code range. Examples: `5411` grocery, `5814` fast food / takeout, `5812` restaurants, `5942` book stores, `4121` taxis & limousines. |
| `country_gl`           | string (ISO 3166-1 alpha-2, lowercase) | Country hint for geographic disambiguation. Examples: `us`, `gb`, `ca`, `au`. Every alpha-2 code is supported.                                                                                                                                                                                     |
| `city`                 | string                                 | City hint to prioritize local branches or regional brand variants. Free-form; standard names work best (e.g. `San Francisco`, `New York`).                                                                                                                                                         |
| `phone`                | number                                 | Phone number from the transaction descriptor, when present, to help verify the brand match.                                                                                                                                                                                                        |
| `high_confidence_only` | boolean                                | When `true`, runs additional verification and returns 400 instead of a low-confidence match. Use for spend analytics, compliance, or expense flows. Defaults to `false`.                                                                                                                           |
| `force_language`       | string                                 | Force the language of the retrieved brand data.                                                                                                                                                                                                                                                    |
| `maxSpeed`             | boolean                                | Skip time-consuming operations for a faster, less complete response. Defaults to `false`.                                                                                                                                                                                                          |
| `timeoutMS`            | integer                                | Abort with a 408 if the request exceeds this many milliseconds. Min `1000`, max `300000` (5 min).                                                                                                                                                                                                  |

### Response

```json expandable theme={null}
{
  "status": "ok",
  "code": 200,
  "brand": {
    "domain": "starbucks.com",
    "title": "Starbucks",
    "description": "Starbucks is a global coffee company that puts people at the heart of its business…",
    "slogan": "Inspiring and nurturing the human spirit — one person, one cup",
    "colors": [
      { "hex": "#0bac66", "name": "Secret Garden" },
      { "hex": "#7cd4b4", "name": "Seafoam Blue" }
    ],
    "logos": [
      {
        "url": "https://media.brand.dev/67dc7846-2ca2-4a7b-9877-6bb5a5e2c0e0.png",
        "mode": "has_opaque_background",
        "type": "icon",
        "colors": [{ "hex": "#0bac66", "name": "Secret Garden" }],
        "resolution": { "width": 180, "height": 180, "aspect_ratio": 1 }
      }
    ],
    "socials": [
      { "type": "x", "url": "https://x.com/starbucks" },
      { "type": "facebook", "url": "https://facebook.com/starbucks" },
      { "type": "instagram", "url": "https://instagram.com/starbucks" }
    ],
    "address": {
      "street": "2401 Utah Avenue South",
      "city": "Seattle",
      "state_province": "Washington",
      "state_code": "WA",
      "country": "United States",
      "country_code": "US",
      "postal_code": "98134"
    },
    "stock": { "ticker": "SBUX", "exchange": "NASDAQ" },
    "industries": {
      "eic": [
        {
          "industry": "Retail & E-commerce",
          "subindustry": "Omnichannel & In-Store Retail"
        }
      ]
    },
    "primary_language": "english",
    "is_nsfw": false
  }
}
```

| Field                    | Type    | Description                                                                                                                                                    |
| ------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `status`                 | string  | `"ok"` on success.                                                                                                                                             |
| `code`                   | integer | HTTP status code, echoed for convenience.                                                                                                                      |
| `brand.domain`           | string  | Canonical merchant domain.                                                                                                                                     |
| `brand.title`            | string  | Clean company name.                                                                                                                                            |
| `brand.description`      | string  | One-paragraph company description.                                                                                                                             |
| `brand.slogan`           | string  | Marketing tagline, when available.                                                                                                                             |
| `brand.colors[]`         | array   | Brand colors ordered by visual prominence. Each has `hex` and a human-readable `name`.                                                                         |
| `brand.logos[]`          | array   | Logo variants: `url`, `mode` (`light` / `dark` / `has_opaque_background`), `type` (`logo` / `icon`), `colors`, and `resolution.{width, height, aspect_ratio}`. |
| `brand.socials[]`        | array   | Social profile URLs. `type` is one of `x`, `facebook`, `instagram`, `linkedin`, `youtube`, `tiktok`, `github`, and 20+ more.                                   |
| `brand.address`          | object  | HQ address: `street`, `city`, `state_province`, `state_code`, `country`, `country_code`, `postal_code`.                                                        |
| `brand.stock`            | object  | `ticker` and `exchange` for publicly traded merchants. `null` for private companies.                                                                           |
| `brand.industries.eic[]` | array   | EIC industry tags with `industry` and `subindustry`. For NAICS / SIC codes, call `/web/naics` or `/web/sic`.                                                   |
| `brand.links`            | object  | Non-social URLs: `blog`, `pricing`, `careers`, `contact`, `privacy`, `terms`, `login`, `signup`.                                                               |
| `brand.primary_language` | string  | Detected language of the merchant's website (e.g. `english`, `spanish`).                                                                                       |
| `brand.is_nsfw`          | boolean | Safe-content flag.                                                                                                                                             |

## Handle errors

| Status | Meaning                                                                                                                                                  | What to do                                                                                                                          |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| 400    | The descriptor couldn't be identified (no confident brand match), `high_confidence_only` blocked a low-confidence hit, or `transaction_info` is missing. | Fall back to a cleaned descriptor + an MCC-based category icon. Cache the miss for at least 24 hours so retries don't burn credits. |
| 401    | Missing or invalid API key.                                                                                                                              | Re-check the env var and the dashboard.                                                                                             |
| 429    | Rate limit.                                                                                                                                              | Back off exponentially.                                                                                                             |

A fallback pattern that surfaces 400 as a "no match" outcome instead of an exception:

<CodeGroup>
  ```typescript TypeScript theme={null}
  import ContextDev from "context.dev";

  const client = new ContextDev({ apiKey: process.env.CONTEXT_DEV_API_KEY });

  async function enrichOrFallback(transaction: {
    description: string;
    mcc?: string;
    country?: string;
  }) {
    try {
      const { brand } = await client.brand.retrieve({
        transaction_info: transaction.description,
        mcc: transaction.mcc,
        country_gl: transaction.country,
      });
      return brand;
    } catch (err: any) {
      if (err.status === 400) return null; // no confident match
      throw err;
    }
  }
  ```

  ```python Python theme={null}
  import os
  from context.dev import ContextDev, APIError

  client = ContextDev(api_key=os.environ["CONTEXT_DEV_API_KEY"])

  def enrich_or_fallback(transaction):
      try:
          r = client.brand.retrieve(
              transaction_info=transaction["description"],
              mcc=transaction.get("mcc"),
              country_gl=transaction.get("country"),
          )
          return r.brand
      except APIError as e:
          if e.status_code == 400:
              return None  # no confident match
          raise
  ```

  ```ruby Ruby theme={null}
  require "context_dev"

  def enrich_or_fallback(transaction)
    client = ContextDev::Client.new(api_key: ENV.fetch("CONTEXT_DEV_API_KEY"))
    r = client.brand.retrieve(
      transaction_info: transaction[:description],
      mcc: transaction[:mcc],
      country_gl: transaction[:country],
    )
    r.brand
  rescue ContextDev::Errors::APIError => e
    return nil if e.status == 400
    raise
  end
  ```

  ```php PHP theme={null}
  <?php

  use ContextDev\Client;
  use ContextDev\Core\Exceptions\APIStatusException;

  function enrichOrFallback(array $transaction) {
      $client = new Client(apiKey: getenv('CONTEXT_DEV_API_KEY'));

      try {
          $response = $client->brand->retrieve(
              transactionInfo: $transaction['description'],
              mcc: $transaction['mcc'] ?? null,
              countryGl: $transaction['country'] ?? null,
          );
          return $response->brand;
      } catch (APIStatusException $e) {
          if ($e->status === 400) {
              return null; // no confident match
          }
          throw $e;
      }
  }
  ```
</CodeGroup>

For the full error code catalog, see [Troubleshooting](/optimization/troubleshooting).

## Use cases

* **Personal finance apps**: show actual company logos and clean names for every merchant and subscription.
* **Reconcile employee expense reports automatically**: match messy expense entries to clean company names, logos, and categories.

## Next steps

<CardGroup cols={2}>
  <Card title="Prefetch for Faster Response" icon="bolt" href="/optimization/prefetching">
    Hide cold-hit latency from your users.
  </Card>

  <Card title="Handle Rate Limits" icon="gauge-high" href="/optimization/rate-limits">
    Backoff strategies, client cache, and prefetch fallbacks.
  </Card>

  <Card title="Best Practices" icon="list-check" href="/optimization/best-practices">
    Caching, error handling, and key hygiene.
  </Card>

  <Card title="Troubleshooting" icon="bug" href="/optimization/troubleshooting">
    Status codes, retry patterns, and common errors.
  </Card>
</CardGroup>
