Quickstart
No SDK, no account needed for public listings. Send a JSON body to /graphql and get a snapshot back.
Step 1 — Get a listing slug
The slug is the stable public identifier for a location. It looks like green-cafe or main-street-bakery. The listing owner sets it inside MyBusiness.
Step 2 — Send a GraphQL request
curl -X POST "https://publix-api.mateality.com/graphql" \
-H "content-type: application/json" \
-d '{
"query": "query Listing($slug: String!) { listing(slug: $slug) { id slug visibility location { displayName city country logo { url alt } } business { displayName websiteUrl } menus { id name categories { id name products { id name pricing { price currencyCode } availability { status available } } } } } }",
"variables": { "slug": "green-cafe" }
}'
Step 3 — Read the response
Successful responses wrap the listing under data.listing. If the slug does not exist or the listing is not public, data.listing is null.
{
"data": {
"listing": {
"slug": "green-cafe",
"visibility": "public",
"location": {
"displayName": "Green Cafe",
"city": "Bucharest",
"country": "RO",
"logo": {
"url": "https://publix-api.mateality.com/api/v1/public/media/logos/logo.png",
"alt": "Green Cafe"
}
},
"business": {
"displayName": "Green Cafe SRL",
"websiteUrl": "https://greencafe.ro"
},
"menus": []
}
}
}
Render logo.url, menu cover.url, category cover.url, and product media.iconUrl values directly — do not reconstruct storage paths.
Fetch in TypeScript
async function fetchListing(slug: string, embedKey?: string) {
const headers: Record<string, string> = {
"content-type": "application/json",
};
if (embedKey) {
headers["x-publix-embed-key"] = embedKey;
}
const response = await fetch("https://publix-api.mateality.com/graphql", {
method: "POST",
headers,
body: JSON.stringify({
query: `
query Listing($slug: String!) {
listing(slug: $slug) {
id
slug
visibility
discoveryEnabled
location {
displayName
brandColor
city
country
currencyCode
logo { url alt }
}
business {
displayName
websiteUrl
phone
}
menus {
id
name
categories {
id
name
products {
id
name
description
pricing { price currencyCode unitOfMeasure }
availability { status available }
media { iconUrl }
allergens
}
}
}
}
}
`,
variables: { slug },
}),
});
const body = await response.json();
return body.data?.listing ?? null;
}
Fetch in Python
import httpx
def fetch_listing(slug: str, embed_key: str | None = None) -> dict | None:
headers = {"content-type": "application/json"}
if embed_key:
headers["x-publix-embed-key"] = embed_key
query = """
query Listing($slug: String!) {
listing(slug: $slug) {
id slug visibility
location { displayName city country }
menus {
id name
categories {
id name
products { id name pricing { price currencyCode } }
}
}
}
}
"""
response = httpx.post(
"https://publix-api.mateality.com/graphql",
json={"query": query, "variables": {"slug": slug}},
headers=headers,
)
response.raise_for_status()
return response.json().get("data", {}).get("listing")
Access a private listing
Private listings require an embed key issued from MyBusiness. Pass it in the X-Publix-Embed-Key header:
curl -X POST "https://publix-api.mateality.com/graphql" \
-H "content-type: application/json" \
-H "x-publix-embed-key: mbpub_your_key_here" \
-d '{
"query": "query Listing($slug: String!) { listing(slug: $slug) { slug location { displayName } } }",
"variables": { "slug": "private-listing" }
}'
See Authentication for embed key security and allowed-origins configuration.
Check service health
curl "https://publix-api.mateality.com/health"
{ "service": "@mybusiness/publix-api", "status": "ok" }
Next steps
- Authentication — embed keys, allowed origins, security practices
- API reference — full data model, all fields, status codes
- Errors — what each error means and how to handle it