# Tandoor Recipes > Open-source, self-hostable recipe management, meal planning, shopping-list and pantry software > built on Django and django-rest-framework, offered both as free self-hosted software and as a paid > hosted service at app.tandoor.dev. Every product feature is driven by one REST API of 462 > operations, described by a live OpenAPI 3.0.3 document that is served WITHOUT authentication at > /openapi/ on every instance. Generated by API Evangelist from the provider's own published surface on 2026-08-27. Method: generated. Tandoor publishes no llms.txt of its own (probed 2026-08-27: tandoor.dev/llms.txt 404, docs.tandoor.dev/llms.txt 404, app.tandoor.dev/llms.txt 302 to login). ## What you need to know first - Tandoor is SELF-HOSTED FIRST. There is no single API base URL. The base is `https:///api/`. The vendor's own hosted instance is `https://app.tandoor.dev/api/`. - The contract for the instance you are calling is at `https:///openapi/` and needs no credentials. Read it before you integrate — the API version you get is whatever version the operator deployed. - Auth is an access token in the `Authorization` header (declared as `ApiKeyAuth` in the spec). Tokens come from `/api/access-token/` in the app, or from `POST /api-token-auth/` with a username and password. - Unauthenticated `/api/` calls are 302-REDIRECTED to `/accounts/login/`. A client that follows redirects sees an HTTP 200 HTML login page where it expected a 401. Do not follow redirects. - The contract declares NO error responses — no 4xx, no 5xx, no problem+json — across all 462 operations. Errors come back in the django-rest-framework shape: `{"field": ["message"]}` for validation, `{"detail": "message"}` for everything else. - There is NO idempotency key. Retrying a POST creates a second object. Dedupe client-side. - There is NO undo, no soft delete and no trash. DELETE is final. Back up with `POST /api/export/` first. ## Before you delete anything Tandoor ships a real pre-flight for destructive operations, and an agent should treat it as mandatory. Every resource with dependants exposes three read-only previews that return `{id, model, name}` lists: - `GET /api/{resource}/{id}/cascading/` — what gets DELETED along with it - `GET /api/{resource}/{id}/nulling/` — what survives but loses its reference to it - `GET /api/{resource}/{id}/protecting/` — what will make the DELETE FAIL Available on recipe, food, unit, keyword, recipe-book, shopping-list, supermarket and supermarket-category. For foods, units, keywords and supermarket categories, prefer `PUT /api/{resource}/{id}/merge/{target}/` over delete — it repoints every reference instead of destroying them. Merge itself cannot be undone. ## Core surface Recipes: apiRecipeList, apiRecipeRetrieve, apiRecipeCreate, apiRecipeUpdate, apiRecipePartialUpdate, apiRecipeDestroy, apiRecipeFlatList, apiRecipeBatchUpdateUpdate, apiRecipeImageUpdate, apiRecipeRelatedList, apiRecipeShoppingUpdate Steps and ingredients: apiStepList/Create/Update/Destroy, apiIngredientList/Create/Update/Destroy, apiIngredientParserPostCreate (parse a free-text ingredient line) Foods and units: apiFoodList, apiFoodCreate, apiFoodBatchUpdateUpdate, apiFoodMergeUpdate, apiFoodMoveUpdate, apiFoodShoppingUpdate, apiFoodFdcCreate, apiUnitList, apiUnitMergeUpdate, apiUnitConversionList Keywords: apiKeywordList, apiKeywordCreate, apiKeywordMergeUpdate, apiKeywordMoveUpdate Properties and nutrition: apiPropertyList, apiPropertyTypeList, apiRecipeAipropertiesCreate, apiFoodAipropertiesCreate, apiFdcSearchRetrieve Meal planning: apiMealPlanList, apiMealPlanCreate, apiMealTypeList, apiAutoPlanCreate, apiMealPlanIcalRetrieve (text/calendar, RFC 5545) Shopping: apiShoppingListEntryList, apiShoppingListEntryCreate, apiShoppingListEntryBulkCreate, apiShoppingListRecipeBulkCreateEntriesCreate, apiShoppingListList, apiSupermarketList, apiSupermarketCategoryList, apiSupermarketCategoryRelationList Pantry: apiInventoryEntryList, apiInventoryLocationList, apiInventoryLogList Books and collections: apiRecipeBookList, apiRecipeBookEntryList, apiCustomFilterList Import and export: apiRecipeFromSourceCreate (scrape a URL or pasted text), apiRecipeImportList, apiRecipeImportImportRecipeCreate, apiRecipeImportImportAllCreate, apiImportCreate, apiExportCreate, apiBookmarkletImportCreate, apiImportOpenDataCreate AI: apiAiImportCreate (image/PDF to structured recipe), apiAiStepSortCreate, apiAiProviderList, apiAiLogList Open Data reference database: apiOpenDataFoodList, apiOpenDataUnitList, apiOpenDataStoreList, apiOpenDataCategoryList, apiOpenDataPropertyList, apiOpenDataConversionList, apiOpenDataVersionList Spaces and users: apiSpaceList, apiHouseholdList, apiUserSpaceList, apiUserPreferenceList, apiSwitchActiveSpaceRetrieve, apiInviteLinkList, apiShareLinkRetrieve, apiAccessTokenList, apiServerSettingsCurrentRetrieve Sync and storage: apiStorageList, apiSyncList, apiSyncLogList, apiConnectorConfigList Automation: apiAutomationList ## Conventions - Pagination: `page` and `page_size`, envelope `{count, next, previous, results}`. 113 list operations. - Update: `PUT` for full replacement, `PATCH` for partial. Both idempotent by HTTP semantics. - Trailing slashes are required on every path. - Ids are plain database integers, unique only within one instance and one space. - A `space` is the tenant boundary. `GET /api/switch-active-space/{spaceId}/` changes which space you act in. - No expand/fields parameter; the serializer decides what is inlined. A recipe always arrives with its steps, each step with its ingredients, each ingredient with its food and unit. - No rate-limit headers. Recipe URL import and AI calls are throttled at an operator-set 60/hour by default; nothing signals it in the response. ## Documentation - Docs home: https://docs.tandoor.dev/ - Install (Docker): https://docs.tandoor.dev/install/docker/ - Configuration reference: https://docs.tandoor.dev/system/configuration/ - Authentication (allauth, OIDC, social providers): https://docs.tandoor.dev/features/authentication/ - AI features: https://docs.tandoor.dev/features/ai/ - Connectors (Home Assistant, beta): https://docs.tandoor.dev/features/connectors/ - Import/export formats: https://docs.tandoor.dev/features/import_export/ - Backup: https://docs.tandoor.dev/system/backup/ - Live OpenAPI: https://app.tandoor.dev/openapi/ - Redoc / Swagger UI (requires login): /docs/api/ and /docs/swagger/ on any instance ## Project - Source: https://github.com/TandoorRecipes/recipes (8,562 stars, 850 forks, default branch `develop`) - Container: https://hub.docker.com/r/vabene1111/recipes (13.2M pulls; 2.6.13 released 2026-07-05) - Releases / changelog: https://github.com/TandoorRecipes/recipes/releases - Security policy: https://github.com/TandoorRecipes/recipes/security/policy — report through GitHub Security Advisories. Support is LATEST VERSION ONLY, with no backports; 10 advisories were published between April and June 2026, most of them API authorization defects. Run the current release. - Status (hosted service only): https://status.tandoor.dev/status/tandoor - Pricing: https://tandoor.dev/#pricing — Free, Basic EUR 1.99/mo, Standard EUR 4.49/mo, Premium AI EUR 6.49/mo, or self-host for nothing. No plan meters API calls; only AI credits are metered. - Community: https://community.tandoor.dev/ and the project Discord - Vendor: Tandoor Recipes, Benedikt Sienz, Falkensee, Germany. GDPR-compliant, no tracking or analytics. ## What Tandoor does NOT publish - No MCP server (at least 11 community ones exist; none is first-party) - No A2A agent card (/.well-known/agent-card.json and /.well-known/agent.json probed on all three hosts) - No /.well-known/ surface of any kind, no security.txt, no api-catalog - No client SDK in any language. A complete generated TypeScript client lives in the repo at vue3/src/openapi/ but is never published to npm. - No AsyncAPI, no webhooks, no event stream - No GraphQL, no gRPC, no SOAP - No Postman collection - No documented error catalogue, no deprecation policy, no SLA