Transaction is a private beta. Contact sales to turn it on, then open the Transaction Playground.
Get your beta key
Access belongs to your Logo.dev account. When the beta is on, everyone on the account can use it. Each person has their own key. Copy yours from the Transaction Playground, and keep it on your server. The key starts withtx_beta_ and works only with Transaction. Your Logo.dev secret keys do not work here.
To replace your key, select Regenerate in the playground. The old key stops working immediately. Your daily usage does not reset.
Identify a merchant
Send aPOST request to https://www.logo.dev/api/transaction with the descriptor in transaction. country_code is optional. It is a hint for ambiguous names, not a filter.
logo_url has no token. Add your publishable key before you show the logo: https://img.logo.dev/starbucks.com?token=LOGO_DEV_PUBLISHABLE_KEY.
Read the row
Every row has astatus. Handle the two values differently.
matched: the API identified a merchant domain. Shownameand the logo.cleaned: the API tidied the descriptor into a display name and identified no merchant.domain,entity_id, andlogo_urlarenull. Shownamewithout a logo.
status === "matched" covers every case, because the API returns no third status.
- Key your records on
entity_id. It is the merchant’s Logo.dev brand id, the same id Brand uses. A brand keeps its id when its domain changes, so a rebrand stays one merchant. - Branch on
entity_id, not onconfidence. A row with an id has two sources that agree: the pipeline identified the merchant, and Brand resolves a brand for the same domain. Amatchedrow can still have anullid, for example when Logo.dev has not indexed the domain yet. - Rank on
confidence. Use the score to sort a review queue or to hold the bottom of a batch for a person. Logo.dev publishes no cut-off and can recalibrate the score.
match_type names the pipeline stage that produced the row. Read it from the row and do not predict it from the descriptor. The reference lists each value.
Group by owner and by platform
Two fields name companies that sit beside the merchant. Neither one replaces the merchant indomain.
parentis the company that owns the merchant. A lookup for Facebook returns Facebook, with Meta inparent. Group totals onparent.entity_idto add up one company’s brands. Coverage is thin, so most rows returnnull. Anulldoes not mean the merchant is independent.intermediaryis the platform the purchase ran through. A coffee paid through Square returns the coffee shop, with Square inintermediary. Group totals onintermediary.entity_idto add up spend by platform.
domain, name, entity_id, and logo_url.
Add transaction context (optional)
Sendtransaction_context in these cases:
- The account holder matters. Without context, the API does not detect people, so
Jane Doecan match an organization with a similar name. - You need the platform named reliably. Without context, the API fills
intermediaryonly for some prefixed descriptors, such asSQ*.
date, amount, currency, and entry_type are required. account_holder is optional.
With context, the response adds entity_type: person, organization, or null. A person always comes back as a cleaned row.
The merchant string, the context, and the account holder details go to Logo.dev’s enrichment provider. The beta keeps no account history across lookups.
Daily allowance
Each person gets 1,000 requests per UTC day, shared between the playground and their beta key. The allowance resets at midnight UTC. Beta requests do not spend API credits. Every request that passes validation counts. This includes cleaned rows, provider errors, timeouts, and repeats served from a saved result. Invalid input and rejected keys do not count. A burst limit also applies: more than about 60 requests in one minute returns429. Each response that counts carries X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset.
Handle errors
Transaction does not use the Logo.dev API error object. An error has oneerror string, for example {"error":"Daily limit of beta requests reached"}. The reference lists every status code with an example.
400: fix the request body. It does not count against your allowance.401: check the key. A regenerated key replaces the old one.403: the beta is not on for your account. Contact sales.409: another request is already looking up the same transaction. Wait for the number of seconds inRetry-After, then retry to read the saved result.429: wait for the number of seconds inRetry-After.503: a dependency is unavailable. Retry later. The API returns this error instead of a cleaned row.
Changes for existing callers
The response shape changed during the beta:statusno longer returnsnot_found. Those rows now returncleaned. Code that checks fornot_foundmatches nothing, so any fallback behind it stops running.brand_urlandverifiedare gone.verifiedwastrueexactly whenentity_idis set. Testentity_idinstead.- New fields.
name,confidence,match_type,logo_url,entity_id,parent, andintermediaryare on every response. A parser that rejects unknown fields needs an update. - New
match_typevalues.descriptor_domainandsearched_nameappear on rows that returnedcleaned_descriptorbefore. Add them before you upgrade.