Enigma's Public API SDK
Project description
Enigma API Client
Python SDK for the Enigma GraphQL business intelligence API. Query Enigma's database of 250M+ businesses using raw GraphQL or natural language prompts.
Installation
# Core client (raw GraphQL only)
pip install enigma-api-client
# With Claude agent (skill-based generation, requires Anthropic API key)
pip install enigma-api-client[anthropic]
Quick Start
The client supports both raw GraphQL queries and natural language queries.
- Below example showcases the raw GraphQL approach.
- Subseqent examples show how to use the natural language strategies.
Using GraphQL Queries
import asyncio
from enigma_api_client import Client, ClientConfig
client = Client(ClientConfig(enigma_api_key="your-api-key"))
async def main():
# Example, sending off a handwritten GraphQL query
response = await client.search(
query="""query {
search(searchInput: { name: "Starbucks", entityType: BRAND }) {
... on Brand {
id
names(first: 1) { edges { node { name } } }
}
}
}"""
)
print(response.data)
asyncio.run(main())
Natural Language Query strategies
The client supports three strategies for converting natural language prompts into GraphQL queries. Pass a strategy via ClientConfig.query_strategy to enable client.search(prompt="...").
All strategies require the ANTHROPIC_API_KEY environment variable. The AgentStrategy additionally requires the claude_agent_sdk package (pip install enigma-api-client[anthropic]).
Service Strategy (default)
Will execute a http request to perform query generation using any of the strategies below on the server side.
import asyncio
from enigma_api_client import Client, ClientConfig
client = Client(ClientConfig(
enigma_api_key="your-api-key",
# will use ServiceStrategy by default
))
async def main():
# Brand lookup
response = await client.search(prompt="Tell me about Chipotle")
print(response.data)
# Location search
response = await client.search(prompt="Find Starbucks locations in California")
print(response.data)
# Business discovery
response = await client.search(prompt="Find coffee shops in Denver")
print(response.data)
# Person search
response = await client.search(prompt="Find companies owned by Elon Musk")
print(response.data)
# KYB verification
response = await client.search(prompt="Verify legal entity for Enigma Technologies in NY")
print(response.data)
asyncio.run(main())
TemplateStrategy — LLM-classified, template-built
Uses an LLM (via Anthropic Messages API) to classify the user's prompt into one of 13 pre-defined query templates and extract parameters, then assembles the GraphQL query deterministically from the matching template. Fast and reliable — no hallucinated field names since the GraphQL is built from verified templates.
import asyncio
from enigma_api_client import Client, ClientConfig
from enigma_api_client.strategies import TemplateStrategy
client = Client(ClientConfig(
enigma_api_key="your-api-key",
query_strategy=TemplateStrategy(),
))
async def main():
# Brand lookup
response = await client.search(prompt="Tell me about Chipotle")
print(response.data)
# Location search
response = await client.search(prompt="Find Starbucks locations in California")
print(response.data)
# Business discovery
response = await client.search(prompt="Find coffee shops in Denver")
print(response.data)
# Person search
response = await client.search(prompt="Find companies owned by Elon Musk")
print(response.data)
# KYB verification
response = await client.search(prompt="Verify legal entity for Enigma Technologies in NY")
print(response.data)
asyncio.run(main())
The template strategy covers 13 query templates: brand profiles, brand lookups by website, locations, revenue, business discovery, person search, corporate officers, legal entity verification, contacts, watchlist screening, operating location profiles, aggregate counts, and risk assessment. Prompts that don't map to any template raise an EnigmaClientException.
GenerativeStrategy — end-to-end LLM query generation
Uses a single LLM call (via Anthropic Messages API) to generate the full GraphQL query and variables directly. The LLM receives the complete Enigma GraphQL API skill reference as context. More flexible than TemplateStrategy for complex or unusual queries that don't fit neatly into pre-defined templates, but slower and carries some risk of hallucinated field names.
import asyncio
from enigma_api_client import Client, ClientConfig
from enigma_api_client.strategies import GenerativeStrategy
client = Client(ClientConfig(
enigma_api_key="your-api-key",
query_strategy=GenerativeStrategy(),
))
async def main():
response = await client.search(
prompt="Find all open Dunkin' Donuts locations in Massachusetts with phone numbers and revenue data"
)
print(response.data)
asyncio.run(main())
AgentStrategy — Claude Agent SDK with skill
Uses the Claude Agent SDK (claude_agent_sdk) to generate GraphQL queries via an interactive agent that has access to the full enigma-graphql skill — including the schema, examples, field corrections, and pagination templates. The agent can read skill files, reason about the query, and iteratively refine its output. Produces the highest quality queries for complex scenarios but is the slowest option.
Requires: pip install enigma-api-client[anthropic]
import asyncio
from enigma_api_client import Client, ClientConfig
from enigma_api_client.strategies import AgentStrategy
client = Client(ClientConfig(
enigma_api_key="your-api-key",
query_strategy=AgentStrategy(),
))
async def main():
response = await client.search(
prompt="Find all open Dunkin' Donuts locations in Massachusetts with phone numbers"
)
print(response.data)
asyncio.run(main())
Strategy comparison
| Strategy | Approach | Speed | Quality | Extra deps |
|---|---|---|---|---|
TemplateStrategy |
LLM classifies → deterministic template build | ~1-3s | Reliable, no hallucination | None |
GenerativeStrategy |
LLM generates full GraphQL end-to-end | ~3-10s | Flexible, some hallucination risk | None |
AgentStrategy |
Claude agent with skill + tool access | ~10-60s | Highest quality, iterative refinement | claude_agent_sdk |
When to use which:
- TemplateStrategy (default): Best for production use. Covers 13 common query patterns with zero hallucination risk. The LLM only classifies and extracts parameters — the GraphQL is deterministic.
- GenerativeStrategy: Best for complex or unusual queries that don't fit the 13 templates. The LLM sees the full API reference and generates custom GraphQL. Good for prototyping and exploratory queries.
- AgentStrategy: Best for maximum quality when latency is not a concern. The agent can read examples, check field corrections, and reason about the query. Good for batch processing or one-off complex queries.
Caveats: LLM-generated GraphQL
The Enigma GraphQL schema has several non-obvious conventions that make LLM-generated queries unreliable without guardrails. Understanding these is important regardless of which strategy you use.
Why this is hard for LLMs
The Enigma schema has ~50 field names, 4 entity types, 10+ filter operators, and 6 connection patterns. Many field names are unintuitive — LLMs consistently guess wrong:
| LLMs guess | Actual field name |
|---|---|
status |
operatingStatus |
url |
website |
description |
industryDesc |
title |
jobTitle |
amount |
projectedQuantity |
averageRating |
reviewScoreAvg |
formationDate |
formationYear (Int, not Date) |
These cause HTTP 400 errors ("Cannot query field") that are silent failures if not handled.
Structural pitfalls
Beyond field names, the graph structure has patterns that LLMs regularly get wrong:
searchreturns a flat list, not a connection. LLMs writesearch { edges { node { ... } } }— the correct form issearch { ... on Brand { ... } }.LegalEntity.personsis almost always empty. To find officers, you must traverseregisteredEntities → registrations → roles → legalEntities. LLMs take the direct (empty) path.- Searching
OPERATING_LOCATIONby brand name returns nothing. You must searchBRANDand filter itsoperatingLocationsconnection. LLMs don't know this. namevsprompton SearchInput are completely different modes.namedoes entity resolution ("Starbucks");promptdoes semantic discovery ("coffee shop"). Usingname: "coffee shop"returns nothing useful.totalCountdoes not exist on connections. Requesting it causes HTTP 400. Useaggregatequeries instead.- Cursor pagination has a first-page bug. The first page must NOT declare
$cursoras a variable; subsequent pages must. Requires two separate query strings.
Data quality traps
Even syntactically valid queries can return silently wrong data:
- Missing
IS_NULL: ["platformBrandId"]on brand-level card transactions inflates revenue 2-5x due to aggregate + per-platform records being summed. - Franchise resolution: Searching
BRANDfor a local franchise (e.g., a single Days Inn) returns the parent chain's data — $646M revenue across 1,969 locations instead of the single location's ~$331K. websiteContentsis a connection, not a scalar. Must usewebsiteContents(first: 1) { edges { node { httpStatusCode } } }.
How the strategies handle this
TemplateStrategy avoids all of the above. The LLM only classifies the prompt into a template and extracts parameters (company name, state, city, etc.). The actual GraphQL is assembled from 13 hand-written, tested templates. Zero hallucination risk, but limited to the patterns those templates cover.
GenerativeStrategy sends the full API skill reference (~600 lines of documentation, guardrails, and examples) as system prompt context. This covers most pitfalls, but the LLM can still hallucinate field names or miss structural rules — especially for unusual queries. Validate generated queries before using them in production.
AgentStrategy has full access to the skill files, examples, field corrections reference, and can iteratively refine queries. Highest quality, but slowest and most expensive. The agent can introspect the schema if it encounters errors.
Recommendations
- For production automation, use
TemplateStrategyor raw GraphQL. The 13 templates cover the most common query patterns and are guaranteed correct. - For prototyping or one-off complex queries, use
GenerativeStrategyorAgentStrategybut always review the generated query before trusting the results — particularly revenue data. - Always check
response.is_success()and inspectresponse.errorsbefore usingresponse.data. A plausible-looking query can still fail at the API level.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file enigma_api_client-0.3.5-py3-none-any.whl.
File metadata
- Download URL: enigma_api_client-0.3.5-py3-none-any.whl
- Upload date:
- Size: 254.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
887969ec5be4926fc0a78888819521a2ef2369f9d0d0181dc5f1934ea2680c01
|
|
| MD5 |
87b7d8fb9a542243f0a321bd6ea3db6a
|
|
| BLAKE2b-256 |
7e8fe5f6c46f263aa9c0a2426d2c4f22486fafe6d45f40418d73f2a66f0da13d
|