Restaurants
Find restaurants near a location, search dishes across restaurants near a location (GET /v1.2/menu-items), or list one restaurant's menu by the id a restaurant search returns (GET /v1.2/restaurants/{restaurant_id}/menu-items).
Each operation's description states what it costs — see Credits and pricing.
API key or client token.
Costs 2 credits per successful call.
Search restaurants matching query around (latitude, longitude), ranked by proximity. Every result is a restaurant — type is always restaurant. To search the dishes those restaurants serve, use GET /v1.2/menu-items.
Callable with a client token carrying the restaurants:read scope.
Your credential, sent as Authorization: Bearer <credential>. Two kinds reach this API, and the prefix tells them apart.
API key (sk-…) — created in the Developer Dashboard, it authenticates your whole account. Use it only where you control the machine — never inside a mobile app or a browser. Every endpoint accepts it.
Client token (ct-…) — a short-lived credential bound to one of your end users, minted from your API key by POST /v1.2/auth/client-tokens on your backend and relayed to the device. Safe to hold on a phone: it expires within 2 hours and acts only as the user it was minted for. Endpoints that open with API key or client token accept one and name the scope it must carry; endpoints that open with API key only refuse it.
Search radius in meters around (latitude, longitude), e.g. 5000 = 5 kilometers. A fractional value is accepted and rounded. Default 8000 meters (about 5 miles); maximum 50000 (about 31 miles).
8000Example: 5000Maximum number of results to return.
10Restaurant name to search for.
sweetgreenLatitude of the search location, e.g. 37.7749 (San Francisco).
37.7749Longitude of the search location, e.g. -122.4194 (San Francisco).
-122.4194Restaurants matching the query near the location, ranked by proximity. Empty when nothing matches.
A parameter is missing or invalid; the message names the parameter and the accepted values.
The request carried no Authorization header, or the credential in it was rejected.
unauthorized — the header is missing or malformed, or the key is not one we recognise. A valid key belonging to the other API version is 403 forbidden instead.
A client token is rejected in one of three ways, and only the first should be handled automatically:
token_expired— the token is past its TTL. Mint a fresh one from your backend and retry the request once. This is routine and expected once per TTL window.token_invalid— no such token: it was never issued, or it has been purged, which happens shortly after it expires. This code is not an automatic token-refresh signal.token_revoked— the token was revoked, byPOST /v1.2/auth/client-token-revocationsor from the dashboard. The end user signs in again in your app, and your backend decides whether to mint another; a device that just re-mints defeats the revocation.
The credential is valid but is not allowed to make this request. forbidden is the general case — a key issued for the other API version, for example. A client token adds client_token_not_allowed, meaning the endpoint takes only an sk- API key — its description opens with API key only. (in this API: POST /v1.2/auth/client-tokens, POST /v1.2/auth/client-token-revocations, POST /v1.2/chat/completions, POST /v1.2/literature/search, POST /v1.2/extractions, GET /v1.2/extractions/{job_id}, GET /v1.2/patients/{patient_id}/snapshot, and GET /v1.2/credits).
On an endpoint that opens with API key or client token., scope_insufficient means the token was minted without the scope named at the end of that endpoint’s description.
Two failures share this status; use code to choose the response.
rate_limited— a rolling abuse window was reached: the partner-wide v1.2 minute cap, a configured short-window limit, or a client-token limit. Back off and retry;Retry-Aftercarries the wait when Redis reports it.credit_limit_exceeded— this call costs more credits than you have left for the billing period, or they are spent. Never returned to an Enterprise account, whose usage past the allowance is billed as overage instead.
Credits reset at the end of your billing period; GET /v1.2/credits reports that instant as resets_at and remains available when either limit refuses other operations.
Any other error: the HTTP status plus { code, message }. Retry only rate_limited and the transient 5xx codes.
GET /v1.2/restaurants?query=sweetgreen&latitude=37.7749&longitude=-122.4194 HTTP/1.1
Host: partners.january.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"items": [
{
"type": "restaurant",
"id": "94293e99-ee95-40bf-98bd-508402af9f9e",
"name": "McDonald's",
"is_chain": false,
"distance_meters": 124,
"city": "San Francisco",
"address1": "123 Main Street",
"address2": "Suite 100"
}
]
}API key or client token.
Costs 2 credits per successful call.
Search dishes across restaurants near (latitude, longitude), with the nutrition each menu source publishes. Use radius_meters to widen or narrow the search, e.g. radius_meters=5000 for 5 kilometers; each result reports its own distance_meters. To find the restaurants themselves, use GET /v1.2/restaurants.
Callable with a client token carrying the restaurants:read scope.
Your credential, sent as Authorization: Bearer <credential>. Two kinds reach this API, and the prefix tells them apart.
API key (sk-…) — created in the Developer Dashboard, it authenticates your whole account. Use it only where you control the machine — never inside a mobile app or a browser. Every endpoint accepts it.
Client token (ct-…) — a short-lived credential bound to one of your end users, minted from your API key by POST /v1.2/auth/client-tokens on your backend and relayed to the device. Safe to hold on a phone: it expires within 2 hours and acts only as the user it was minted for. Endpoints that open with API key or client token accept one and name the scope it must carry; endpoints that open with API key only refuse it.
Search radius in meters around (latitude, longitude), e.g. 5000 = 5 kilometers. A fractional value is accepted and rounded. Default 8000 meters (about 5 miles); maximum 50000 (about 31 miles).
8000Example: 5000Maximum number of results to return.
10Dish or restaurant name to search for.
burgerLatitude of the search location, e.g. 37.7749 (San Francisco).
37.7749Longitude of the search location, e.g. -122.4194 (San Francisco).
-122.4194Dishes near the location matching the query, ranked by proximity, each with the nutrition its source publishes. Empty when nothing matches.
A parameter is missing or invalid; the message names the parameter and the accepted values.
The request carried no Authorization header, or the credential in it was rejected.
unauthorized — the header is missing or malformed, or the key is not one we recognise. A valid key belonging to the other API version is 403 forbidden instead.
A client token is rejected in one of three ways, and only the first should be handled automatically:
token_expired— the token is past its TTL. Mint a fresh one from your backend and retry the request once. This is routine and expected once per TTL window.token_invalid— no such token: it was never issued, or it has been purged, which happens shortly after it expires. This code is not an automatic token-refresh signal.token_revoked— the token was revoked, byPOST /v1.2/auth/client-token-revocationsor from the dashboard. The end user signs in again in your app, and your backend decides whether to mint another; a device that just re-mints defeats the revocation.
The credential is valid but is not allowed to make this request. forbidden is the general case — a key issued for the other API version, for example. A client token adds client_token_not_allowed, meaning the endpoint takes only an sk- API key — its description opens with API key only. (in this API: POST /v1.2/auth/client-tokens, POST /v1.2/auth/client-token-revocations, POST /v1.2/chat/completions, POST /v1.2/literature/search, POST /v1.2/extractions, GET /v1.2/extractions/{job_id}, GET /v1.2/patients/{patient_id}/snapshot, and GET /v1.2/credits).
On an endpoint that opens with API key or client token., scope_insufficient means the token was minted without the scope named at the end of that endpoint’s description.
Two failures share this status; use code to choose the response.
rate_limited— a rolling abuse window was reached: the partner-wide v1.2 minute cap, a configured short-window limit, or a client-token limit. Back off and retry;Retry-Aftercarries the wait when Redis reports it.credit_limit_exceeded— this call costs more credits than you have left for the billing period, or they are spent. Never returned to an Enterprise account, whose usage past the allowance is billed as overage instead.
Credits reset at the end of your billing period; GET /v1.2/credits reports that instant as resets_at and remains available when either limit refuses other operations.
Any other error: the HTTP status plus { code, message }. Retry only rate_limited and the transient 5xx codes.
GET /v1.2/menu-items?query=burger&latitude=37.7749&longitude=-122.4194 HTTP/1.1
Host: partners.january.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"items": [
{
"type": "menu_item",
"id": "228990954",
"name": "burger",
"restaurant_name": "morning due cafe",
"is_chain": false,
"nutrients": {
"calories": {
"value": 300,
"unit": "g"
},
"protein": {
"value": 300,
"unit": "g"
},
"carbohydrates": {
"value": 300,
"unit": "g"
},
"net_carbohydrates": {
"value": 300,
"unit": "g"
},
"total_fat": {
"value": 300,
"unit": "g"
},
"trans_fat": {
"value": 300,
"unit": "g"
},
"saturated_fat": {
"value": 300,
"unit": "g"
},
"fiber": {
"value": 300,
"unit": "g"
},
"total_sugars": {
"value": 300,
"unit": "g"
},
"added_sugars": {
"value": 300,
"unit": "g"
},
"cholesterol": {
"value": 300,
"unit": "g"
},
"calcium": {
"value": 300,
"unit": "g"
},
"iron": {
"value": 300,
"unit": "g"
},
"potassium": {
"value": 300,
"unit": "g"
},
"sodium": {
"value": 300,
"unit": "g"
},
"vitamin_d": {
"value": 300,
"unit": "g"
}
},
"glycemic_index": 1,
"glycemic_load": 1,
"image_url": "text",
"distance_meters": 124,
"servings": [
{
"id": "68051535",
"quantity": 1,
"unit": "oz",
"scaling_factor": 1,
"weight_grams": 28,
"is_primary": true
}
]
}
]
}API key or client token.
Costs 2 credits per successful call.
The menu of one restaurant, by the id a GET /v1.2/restaurants result carries — a listing, not a search. Items come ordered by name with the nutrition their menu source publishes; each carries one serving, and GET /v1.2/foods/{food_id} returns the complete list. Page a long menu with limit and offset: a page shorter than limit is the last one. To find dishes across restaurants near a location, use GET /v1.2/menu-items.
Callable with a client token carrying the restaurants:read scope.
Your credential, sent as Authorization: Bearer <credential>. Two kinds reach this API, and the prefix tells them apart.
API key (sk-…) — created in the Developer Dashboard, it authenticates your whole account. Use it only where you control the machine — never inside a mobile app or a browser. Every endpoint accepts it.
Client token (ct-…) — a short-lived credential bound to one of your end users, minted from your API key by POST /v1.2/auth/client-tokens on your backend and relayed to the device. Safe to hold on a phone: it expires within 2 hours and acts only as the user it was minted for. Endpoints that open with API key or client token accept one and name the scope it must carry; endpoints that open with API key only refuse it.
Restaurant id from a GET /v1.2/restaurants result.
94293e99-ee95-40bf-98bd-508402af9f9ePattern: ^[A-Za-z0-9_-]{1,64}$Maximum number of menu items to return. Raise it, or page with offset, for a long menu.
100Number of menu items to skip, for paging: a page shorter than limit is the last one.
0The restaurant's menu items, by name. Empty when the restaurant has no menu on record or offset is past its end.
restaurant_id, limit or offset is malformed; the message names the parameter and the accepted values.
The request carried no Authorization header, or the credential in it was rejected.
unauthorized — the header is missing or malformed, or the key is not one we recognise. A valid key belonging to the other API version is 403 forbidden instead.
A client token is rejected in one of three ways, and only the first should be handled automatically:
token_expired— the token is past its TTL. Mint a fresh one from your backend and retry the request once. This is routine and expected once per TTL window.token_invalid— no such token: it was never issued, or it has been purged, which happens shortly after it expires. This code is not an automatic token-refresh signal.token_revoked— the token was revoked, byPOST /v1.2/auth/client-token-revocationsor from the dashboard. The end user signs in again in your app, and your backend decides whether to mint another; a device that just re-mints defeats the revocation.
The credential is valid but is not allowed to make this request. forbidden is the general case — a key issued for the other API version, for example. A client token adds client_token_not_allowed, meaning the endpoint takes only an sk- API key — its description opens with API key only. (in this API: POST /v1.2/auth/client-tokens, POST /v1.2/auth/client-token-revocations, POST /v1.2/chat/completions, POST /v1.2/literature/search, POST /v1.2/extractions, GET /v1.2/extractions/{job_id}, GET /v1.2/patients/{patient_id}/snapshot, and GET /v1.2/credits).
On an endpoint that opens with API key or client token., scope_insufficient means the token was minted without the scope named at the end of that endpoint’s description.
No restaurant with this id.
Two failures share this status; use code to choose the response.
rate_limited— a rolling abuse window was reached: the partner-wide v1.2 minute cap, a configured short-window limit, or a client-token limit. Back off and retry;Retry-Aftercarries the wait when Redis reports it.credit_limit_exceeded— this call costs more credits than you have left for the billing period, or they are spent. Never returned to an Enterprise account, whose usage past the allowance is billed as overage instead.
Credits reset at the end of your billing period; GET /v1.2/credits reports that instant as resets_at and remains available when either limit refuses other operations.
Any other error: the HTTP status plus { code, message }. Retry only rate_limited and the transient 5xx codes.
GET /v1.2/restaurants/{restaurant_id}/menu-items HTTP/1.1
Host: partners.january.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"items": [
{
"id": "228990954",
"name": "Cheeseburger",
"nutrients": {
"calories": {
"value": 300,
"unit": "g"
},
"protein": {
"value": 300,
"unit": "g"
},
"carbohydrates": {
"value": 300,
"unit": "g"
},
"net_carbohydrates": {
"value": 300,
"unit": "g"
},
"total_fat": {
"value": 300,
"unit": "g"
},
"trans_fat": {
"value": 300,
"unit": "g"
},
"saturated_fat": {
"value": 300,
"unit": "g"
},
"fiber": {
"value": 300,
"unit": "g"
},
"total_sugars": {
"value": 300,
"unit": "g"
},
"added_sugars": {
"value": 300,
"unit": "g"
},
"cholesterol": {
"value": 300,
"unit": "g"
},
"calcium": {
"value": 300,
"unit": "g"
},
"iron": {
"value": 300,
"unit": "g"
},
"potassium": {
"value": 300,
"unit": "g"
},
"sodium": {
"value": 300,
"unit": "g"
},
"vitamin_d": {
"value": 300,
"unit": "g"
}
},
"glycemic_index": 1,
"glycemic_load": 1,
"servings": [
{
"id": "68051535",
"quantity": 1,
"unit": "oz",
"scaling_factor": 1,
"weight_grams": 28,
"is_primary": true
}
]
}
]
}Last updated
Was this helpful?