# Enigma > Trusted business data and intelligence, built on unparalleled entity resolution. Enigma helps fintechs, payment processors, lenders, and banks verify business customers, identify prospects, manage risk, and power AI applications with reliable SMB intelligence. Enigma aggregates data from hundreds of public and third-party sources to create comprehensive profiles on small and medium businesses across the United States. The core technology is an Identity Graph that links brands, DBAs, locations, and legal entities into unified business records — powered by 750M+ anonymized cards and 30B+ annual transactions. ## Products & Solutions - [Data API](https://www.enigma.com/data): GraphQL API for embedding business intelligence into workflows and data warehouses - [KYB & Onboarding](https://www.enigma.com/solutions/onboarding-and-kyb): Business verification using government sources to streamline customer onboarding and reduce manual reviews - [Payment Risk & Underwriting](https://www.enigma.com/solutions/payment-risk-and-underwriting): Merchant insights powered by 750M+ anonymized cards and 30B+ annual transactions - [GTM Solutions](https://www.enigma.com/solutions/gtm-solutions): Lead generation and ICP definition using revenue signals and growth data - [Customer & Transaction Screening](https://www.enigma.com/solutions/customer-and-transaction-screening): Sanctions and risk screening for persons and business entities ## Resources - [Blog](https://www.enigma.com/resources/blog): Articles on KYB, payments, GTM, SMB data, engineering, and compliance — 150+ posts - [Case Studies](https://www.enigma.com/resources/case-studies): Client success stories (Wisetack, Findigs, Curia, and others) - [Reports & Guides](https://www.enigma.com/resources/reports-and-guides): Industry benchmarks, KYB optimization guides, recession insights - [Knowledge Base](https://www.enigma.com/resources/knowledge): 80+ glossary entries covering AML, KYC, sanctions screening, and compliance concepts - [Experiments](https://www.enigma.com/resources/experiments): Interactive data tools and SMB economy charts ## Company - [Pricing](https://www.enigma.com/pricing): Plan and pricing information - [Privacy Policy](https://www.enigma.com/company/privacy-policy): Data handling and privacy - [Partners](https://www.enigma.com/partners): Integration and channel partners - [Contact](https://www.enigma.com/contact-us): Get in touch --- ## API Overview Enigma offers two main APIs: 1. **GraphQL API** — Query business data (brands, locations, legal entities, card transactions, industries) 2. **KYB REST API** — Verify business identity and compliance status ## GraphQL API - Endpoint: `POST https://api.enigma.com/graphql` - Authentication: `x-api-key: YOUR_API_KEY` header - Specification: Standard GraphQL conforming to the GraphQL Specification - Rate limits apply per API key ### Entity Types There are three core entity types: - **BRAND** — A customer-facing business identity (e.g., "Starbucks"). Has names, websites, operating locations, legal entities, affiliated brands, card transactions, industries, revenue quality metrics, high-risk activity flags, and marketability indicators. - **OPERATING_LOCATION** — A physical business location with an address. Has names, addresses, phone numbers, brands, operating statuses, card transactions, legal entities, roles, review summaries, technologies used, websites, ranks, revenue quality, marketability, and location types. - **LEGAL_ENTITY** — A U.S. government-recognized business registration (corporation, LLC, etc.). Has names, registered entities, brands, roles, persons, addresses, TINs, operating locations, types, bankruptcies, and watchlist entries. ### Search Patterns The `search` query supports four patterns: 1. **Text Search** — Search by `name`, `address`, `person`, `website`, `phoneNumber`, or `tin` 2. **Lookup** — Retrieve by entity `id` (UUID). Takes precedence over all other fields. 3. **Prompt Search** — Natural language query via `prompt` field (e.g., "pizza restaurants in New York"). Only supports `entityType: BRAND`. 4. **Segmentation** — Async file export for large datasets. Uses `output` field with `filename`, `format` (CSV or PARQUET), and optional `s3Path`. ### SearchInput Fields ``` searchInput: { id: ID # Entity UUID, takes precedence over all other fields name: String # Business name prompt: String # Natural language search (BRAND only) website: String # Business website (can be sole criterion) phoneNumber: String # 10-digit U.S. phone: "1234567890" or "123-456-7890" address: { # Address filter street1: String street2: String city: String state: String # Two-letter abbreviation postalCode: String } person: { # Person search firstName: String lastName: String dateOfBirth: String # ISO 8601: YYYY-MM-DD address: AddressInput tin: { tin: String, tinType: String } # Requires firstName and lastName } tin: { tin: String, tinType: String } # Requires name to also be provided entityType: EntityType # BRAND (default), OPERATING_LOCATION, LEGAL_ENTITY matchThreshold: Float # 0.0 to 1.0 confidence threshold conditions: { # Top-level conditions filter: FilterExpression orderBy: [String] # e.g., ["field1 ASC", "field2 DESC"] limit: Int pageToken: String # Numeric offset as string } output: { # Async file output for segmentation filename: String # Required format: String # "CSV" or "PARQUET" s3Path: String # S3 destination } } ``` Minimum requirements: `search` queries should have `id`, `name`, or `website`; otherwise use `prompt` with `output`. ### Brand Fields Scalar fields: - `id: ID!` — Unique identifier - `internalId: String` — Internal identifier - `enigmaId: String` — Public-facing identifier (typically matches id) Connection fields (all accept `first`, `last`, `after`, `before`, `conditions`): - `names` → BrandNameConnection — Node: `name: String`, `rank: Int` (0 = primary), `firstObservedDate`, `lastObservedDate` - `websites` → BrandWebsiteConnection — Node: `url: String`, `firstObservedDate`, `lastObservedDate` - `operatingLocations` → BrandOperatingLocationConnection — Each node is a full OperatingLocation entity - `legalEntities` → BrandLegalEntityConnection — Each node is a full LegalEntity entity - `affiliatedBrands` → BrandBrandConnection — Related/sub-brands - `cardTransactions` → BrandCardTransactionConnection — Node: `quantityType`, `period`, `projectedQuantity: Float`, `periodStartDate`, `periodEndDate`, `firstObservedDate`, `lastObservedDate` (Brand level does NOT have `rawQuantity`) - `industries` → BrandIndustryConnection — Node: `industryDesc`, `industryCode`, `industryType` - `activities` → BrandActivityConnection — High-risk activity classifications (~130K brands) - `revenueQualities` → BrandRevenueQualityConnection — Revenue data quality warnings - `locationDescriptions` → BrandLocationDescriptionConnection — Geographic summary - `isMarketables` → BrandIsMarketableConnection — Whether brand is a real consumer-facing business ### OperatingLocation Fields Scalar fields: - `id: ID!`, `internalId: String`, `enigmaId: String` Connection fields: - `names` → OperatingLocationNameConnection — Node: `name`, `rank`, `firstObservedDate`, `lastObservedDate` - `addresses` → OperatingLocationAddressConnection — Node: `fullAddress`, `streetAddress1`, `streetAddress2`, `city`, `state`, `zip`, `county`, `msa`, `csa`, `latitude: Float`, `longitude: Float`, `h3Index`, `country`, `firstObservedDate`, `lastObservedDate` - `phoneNumbers` → OperatingLocationPhoneNumberConnection — Node: `phoneNumber` - `brands` → OperatingLocationBrandConnection — Each node is a full Brand entity - `operatingStatuses` → OperatingLocationOperatingStatusConnection — Node: `operatingStatus: String` (values: "Open", "Closed", "Temporarily Closed", "Unknown"), `firstObservedDate`, `lastObservedDate` - `cardTransactions` → OperatingLocationCardTransactionConnection — Node: `quantityType`, `period`, `rawQuantity: Float`, `projectedQuantity: Float`, `periodStartDate`, `periodEndDate` (Location level HAS `rawQuantity`) - `legalEntities` → OperatingLocationLegalEntityConnection - `roles` → OperatingLocationRoleConnection — People with roles at this location - `reviewSummaries` → OperatingLocationReviewSummaryConnection — Aggregated customer reviews - `websites` → OperatingLocationWebsiteConnection - `technologiesUseds` → OperatingLocationTechnologiesUsedConnection — POS systems, payment processors, etc. - `ranks` → OperatingLocationRankConnection — Competitive revenue ranking - `revenueQualities` → OperatingLocationRevenueQualityConnection - `isMarketables` → OperatingLocationIsMarketableConnection - `locationTypes` → OperatingLocationLocationTypeConnection ### LegalEntity Fields Scalar fields: - `id: ID!`, `internalId: String`, `enigmaId: String` Connection fields: - `names` → LegalEntityNameConnection — Node: `name`, `rank`, `firstObservedDate`, `lastObservedDate` - `registeredEntities` → LegalEntityRegisteredEntityConnection — Node: `registeredEntityType` ("Corporation", "Limited Liability Company", "Limited Partnership"), `formationDate`, `name` - `brands` → LegalEntityBrandConnection - `roles` → LegalEntityRoleConnection — Officers, directors, registered agents - `persons` → LegalEntityPersonConnection — Associated people - `addresses` → LegalEntityAddressConnection — Registered agent address, principal office - `tins` → LegalEntityTinConnection — Tax IDs (EIN, SSN, TIN) - `operatingLocations` → LegalEntityOperatingLocationConnection - `types` → LegalEntityTypeConnection — Entity type classification - `bankruptcies` → LegalEntityBankruptcyConnection — Bankruptcy filings - `isFlaggedByWatchlistEntries` → Watchlist entries flagging this entity (OFAC) - `appearsOnWatchlistEntries` → Watchlist entries entity appears on ### Filter Operators Used in `conditions.filter`: Comparison: `EQ` (equals), `NE` (not equals), `GT`, `GTE`, `LT`, `LTE` — all take 2 args: [fieldPath, value] Set: `IN` (value in list), `NOT_IN` — take 2 args: [fieldPath, [values]] String: `LIKE` (case-sensitive, `%` wildcards), `ILIKE` (case-insensitive) — take 2 args Logical: `AND` (>=2 expressions), `OR` (>=2 expressions), `NOT` (1 expression) Existence: `HAS` (field has value) — takes 1 arg: [fieldPath] Arithmetic: `ADD`, `SUB`, `MUL`, `DIV` — take 2 args Nested fields use dot notation in filters: `addresses.city`, `addresses.state`, `operatingStatuses.operatingStatus`, `operatingStatuses.lastObservedDate`, `cardTransactions.period`, `industries.industryType`, `reviewSummaries.reviewCount` ### Pagination Relay Connection specification with cursor-based pagination: - Forward: `first: Int` + `after: String` (cursor) - Backward: `last: Int` + `before: String` (cursor) - Cannot mix `first` and `last` in the same query - Response: `edges[{ node, cursor }]`, `pageInfo { hasNextPage, hasPreviousPage, startCursor, endCursor }` ### Math Functions Available on all entity types. All accept `field: String` (required) and `conditions` (optional). - `count(field)` → Int — Count related records - `sum(field)` → Int — Sum numeric values - `min(field)` → Int — Minimum value - `max(field)` → Int — Maximum value - `avg(field)` → Float — Average value - `collect(field, separator)` → String — Concatenate values (requires `output` in SearchInput) - `minDateTime(field)` → DateTime — Earliest datetime - `maxDateTime(field)` → DateTime — Latest datetime Field paths for math functions use dot notation: `"websites"`, `"names.rank"`, `"operatingLocations.brands.id"`, `"reviewSummaries.reviewCount"`, `"addresses.firstObservedDate"` ### Aggregate Query For counting operating locations and associated brands/legal entities: - Only supports `entityType: OPERATING_LOCATION` - Only filter: `{EQ: ["operatingStatuses.operatingStatus", "Open"]}` - Countable fields: `"brand"`, `"operatingLocation"`, `"legalEntity"` ```graphql query Aggregate { aggregate(searchInput: { entityType: OPERATING_LOCATION, address: { city: "NEW YORK", state: "NY" } }) { brandsCount: count(field: "brand") locationsCount: count(field: "operatingLocation") } } ``` ### Background Tasks For async segmentation queries: - Poll with: `backgroundTask(id: "UUID") { status, result }` - Status values: `PROCESSING` (keep polling), `SUCCESS` (download URLs in `result`), `FAILED`, `CANCELLED` ### Enum Values **quantityType**: `card_revenue_amount`, `avg_transaction_size`, `refunds_amount`, `card_revenue_prior_period_growth`, `card_customers_average_daily_count` **period**: `1m` (monthly), `3m` (quarterly), `12m` (annual) **operatingStatus**: `Open`, `Closed`, `Temporarily Closed`, `Unknown` **industryType**: `enigma_industry_description`, `naics_2017`, `naics_2022`, `sic`, `mcc` **registeredEntityType**: `Corporation`, `Limited Liability Company`, `Limited Partnership` **tinType**: `TIN`, `EIN`, `SSN` **entityType**: `BRAND`, `OPERATING_LOCATION`, `LEGAL_ENTITY` ### Key Concepts - **projectedQuantity vs rawQuantity**: Enigma observes ~1/3 of U.S. credit card transactions. `rawQuantity` is the direct observation; `projectedQuantity` is the statistical estimate of total market volume. Use `projectedQuantity` for business analysis. - **rank field**: On card transactions, `rank: 0` indicates the most recent/primary data point for that metric and period combination. - **Brands ↔ OperatingLocations ↔ LegalEntities**: These three entity types are interconnected. A Brand has many OperatingLocations and LegalEntities. An OperatingLocation belongs to Brand(s) and LegalEntity(ies). A LegalEntity is associated with Brand(s) and OperatingLocation(s). Card transactions exist on Brand and OperatingLocation but NOT directly on LegalEntity — traverse through brands or operatingLocations to reach them. ### Example Queries Search for a brand by name: ```graphql query { search(searchInput: { name: "Starbucks", entityType: BRAND }) { ... on Brand { id names(first: 1) { edges { node { name } } } count(field: "operatingLocations") } } } ``` Get brand locations with revenue: ```graphql query { search(searchInput: { entityType: BRAND, id: "BRAND_UUID" }) { ... on Brand { operatingLocations(first: 10, conditions: { filter: { EQ: ["operatingStatuses.operatingStatus", "Open"] } }) { edges { node { addresses(first: 1) { edges { node { fullAddress } } } cardTransactions(first: 1, conditions: { filter: { AND: [{ EQ: ["period", "12m"] }, { EQ: ["quantityType", "card_revenue_amount"] }, { EQ: ["rank", 0] }] } }) { edges { node { projectedQuantity } } } } } } } } } ``` Search operating locations directly: ```graphql query { search(searchInput: { name: "McDonald's", entityType: OPERATING_LOCATION }) { ... on OperatingLocation { addresses { edges { node { fullAddress } } } cardTransactions(conditions: { filter: { AND: [{ EQ: ["period", "1m"] }, { EQ: ["quantityType", "card_revenue_amount"] }] } }) { edges { node { projectedQuantity rawQuantity periodStartDate periodEndDate } } } } } } ``` Get legal entities for a brand: ```graphql query { search(searchInput: { id: "BRAND_UUID" }) { ... on Brand { legalEntities(first: 10) { edges { node { registeredEntities { edges { node { registeredEntityType formationDate name } } } } } } } } } ``` Natural language discovery: ```graphql query { search(searchInput: { prompt: "Mexican restaurants", entityType: BRAND, conditions: { limit: 3 } }) { ... on Brand { names { edges { node { name } } } } } } ``` ## KYB REST API - Endpoint: `POST https://api.enigma.com/v2/kyb/` - Authentication: `x-api-key: YOUR_API_KEY` header - Content-Type: `application/json` ### Packages - **identify** — Basic identity matching and data enrichment. Returns entity name, type, formation date, registration details, brand attributes. - **verify** (default) — Full compliance validation. Adds jurisdiction type, home jurisdiction, registration status/sub-status/detail, person verification, domestic registration verification. ### Request Format Single query (requires at least 2 of: name, address, person): ```json { "name": "string", "website": "string", "address": { "street_address1": "string", "street_address2": "string", "city": "string", "state": "string", "postal_code": "string" }, "tin": "string (9 digits)", "person": { "first_name": "string", "last_name": "string", "ssn": "string (9 digits)" } } ``` Multiple query (higher match rates): ```json { "data": { "names": ["string"] (max 2), "addresses": [AddressObject] (max 2), "persons": [PersonObject] (max 1), "websites": ["string"] (max 1), "tins": ["string"] (max 1), "persons_to_screen": [PersonObject] (max 4) } } ``` ### Query Parameters - `package`: "identify" or "verify" (default) - `attrs`: Comma-delimited add-on attributes (e.g., "watchlist") - `match_threshold`: 0 to 1 minimum confidence - `top_n`: Max matches to return (default 1; if >1, tasks not returned) ### Add-On Tasks - TIN (EIN) Verification — validates EIN matches business name - Watchlist (OFAC Sanctions) Screening — checks U.S. government sanctions lists - SSN Verification — validates SSN matches person's name ## Documentation - Full docs: https://documentation.enigma.com/ - GraphQL quickstart: https://documentation.enigma.com/guides/graphql/api - KYB quickstart: https://documentation.enigma.com/docs/kyb-api-quickstart - Attribute reference: https://documentation.enigma.com/reference/attributes - GraphQL API reference: https://documentation.enigma.com/reference/graphql_api/