API Tester and Postman
Audience: System Admin, Developer, Support Related: Api · Database Administration · Regression Testing
API Tester exposes registered Blackcap endpoints with role-aware execution, sanitized examples, option resolution, authentication context, and Postman export. It covers API-token and session-authenticated endpoints, including feature-specific administrative surfaces.
The registry is the canonical API inventory. Documentation should describe endpoint purpose and safety boundaries without publishing live tokens, cookies, private organization identifiers, or credentials.
API Tester details
Blackcap includes a standalone, logged-in API explorer/tester at:
/api-tester
This is intentionally not an Admin UI page and is not mounted below /admin. It has its own blueprint, templates, static assets, layout shell, endpoint registry, and guarded execution service.
Why Blackcap-native instead of Swagger UI?
The first implementation uses a Blackcap-native tester instead of bundling Swagger UI.
Reasons:
- Blackcap self-hosted Raspberry Pi installs should not depend on external CDNs at runtime.
- The tester needs mixed authentication behavior: normal logged-in browser session for web endpoints and manually pasted API tokens for Chrome Extension endpoints.
- The endpoint list should be curated, not discovered automatically from every Flask route.
- Sensitive values need Blackcap-specific masking rules.
- The UI can stay lightweight and quick on a Pi.
The registry is still OpenAPI-style and exposed as JSON through /api-tester/spec, so a Swagger UI wrapper could be added later if it becomes useful.
Access Control
The tester requires a normal logged-in Blackcap browser session.
Routes:
GET /api-testerGET /api-tester/contextPOST /api-tester/context/switchGET /api-tester/specGET /api-tester/options/<source>GET /api-tester/postman-collectionGET /api-tester/postman-environmentPOST /api-tester/postman-tokenPOST /api-tester/execute
Access is controlled by the permission:
api_tester.view
Mutating tester execution additionally requires:
api_tester.execute_mutating
The initial role mapping grants both permissions to System Admin and Org Admin. Lower roles do not receive access by default.
System Admins can switch the API Tester organization context to any non-deleted organization. Users with access to multiple organizations can switch among their own active memberships. The switcher uses Blackcap's existing session organization context, then reloads the curated spec so visible endpoints and permissions match the selected context.
The API Tester does not replace existing route permissions. The execution service validates the curated registry first, then executes the existing Flask route so the normal route/service permissions, organization scoping, CSRF behavior, API token checks, and endpoint-specific validation remain authoritative.
Authentication Models
Session-authenticated endpoints
Session endpoints run with the current logged-in browser session. They use the current organization context and include the CSRF token for state-changing requests.
Examples:
- recipe search/list
- recipe details
- display assignment options
- display state
- job status rows
- live performance resource snapshot
API-token endpoints
Token endpoints behave like the Chrome Extension. The user manually pastes a Blackcap API token into the tester UI.
Rules:
- The token is not persisted server-side.
- The token is not inserted into curl examples.
- The token is not included in audit metadata.
- The token is masked in the browser input unless the user explicitly shows it.
- The browser input is intentionally marked to discourage password-manager autofill, and the masked token control is a text input with CSS masking rather than a normal password field.
- The token can optionally be remembered in browser
sessionStoragefor the current browser session only. It is cleared by the Clear button, by disabling the checkbox, or when the browser session ends. - If the Blackcap Chrome Extension content script is installed for the current Blackcap host, the tester can ask the extension for the active token. This is a browser-side handoff only; Blackcap does not retrieve or expose stored token plaintext from server-side token records.
- The API token organization determines scope for token-scoped endpoints.
- Invalid, revoked, inactive-user, or disabled-organization token behavior remains controlled by the existing authentication/security services.
Examples:
/api/recipes/ping/api/recipes/defaults/api/extension/context/api/recipes/add/api/extension/recipes/capture/api/extension/household-list/browser-bridge/context
Endpoint Registry
The curated endpoint registry lives in:
inky_admin/services/api_tester_registry_service.py
Each endpoint definition includes:
- category
- display name
- HTTP method
- path
- description
- authentication mode
- required permission
- organization scope behavior
- path parameters
- query parameters
- request body schema/example
- example response
- success/error status codes
- read-only vs mutating
- notes and safety flags
Do not auto-expose every Flask route. Add endpoints to the registry only when they are useful, safe, and documented.
Postman Collection Export
The API Tester can download a curated Postman collection through:
GET /api-tester/postman-collection
The route requires the same logged-in api_tester.view permission as the rest of the tester, but the downloaded collection does not contain any live secrets. It uses collection variables such as base_url, blackcap_api_token, blackcap_postman_token, client_token, pairing_token, recipe_share_public_id, and recipe_share_token.
The Postman collection is broader than the first pass but still filtered. It includes external/API-token endpoints plus useful session-authenticated action endpoints that can reasonably be called from Postman with an 8-hour API Tester-issued Postman token. This includes areas such as recipe search/details/cache status, Recipe Library add/manual add flows, Meal Planner, Shopping Lists, Displays, Kiosk controls, Let’s Cook, Kitchen Inventory, Settings utilities, Job Status actions, Backups, and Support Requests. It excludes documented-only endpoints, destructive endpoints, user/org lifecycle management, Database Admin, Data Purge, auth challenge flows, OAuth callbacks, webhooks, static/media routes, and normal page shell routes.
The API Tester sidebar includes a Postman button that opens a dedicated setup dialog. The dialog contains the Postman collection download button, the environment download button, and a helper to copy blackcap_postman_token. The token helper calls POST /api-tester/postman-token, requires the same logged-in API Tester permission and a valid CSRF token, returns a signed 8-hour bearer token scoped to the current user and organization context, and never logs the raw token. Treat the copied token like a password until it expires.
The generator lives in:
inky_admin/services/api_tester_postman_service.py
When adding a new endpoint, include it in the Postman collection only if it is useful outside the API Tester itself. API-token endpoints, tokenized public/client endpoints, and practical session-authenticated action endpoints can qualify; destructive lifecycle/admin/database operations should remain documented-only or in the browser-based tester only.
Display render settings and timed Meal Planner behavior
The Display Administration category includes Update Display Render Settings for POST /admin/displays/{display_id}/render-settings. This is a form-backed Admin route, so API Tester sends the structured body as form fields. In addition to width, height, and orientation, the endpoint now documents the timed Meal Planner fields:
{
"timed_meal_plan_behavior": "recipe",
"restore_default_after_slot": true,
"auto_show_lead_minutes": 0,
"auto_show_behavior": "first_recipe",
"voice_lets_cook_display_mode": "full_recipe",
"show_setup_step_in_full_lets_cook": false
}
Use timed_meal_plan_behavior=recipe for passive timed recipe display. Use timed_meal_plan_behavior=lets_cook for any display type. Kiosk displays and touch-enabled hosted web receivers show the interactive Let’s Cook UI, while local e-ink, non-touch hosted receivers, mock displays, and remote clients render the display-only Let’s Cook preview. voice_lets_cook_display_mode controls whether the display render surface uses full-recipe, voice-only current-step, or all-session current-step Let’s Cook. show_setup_step_in_full_lets_cook controls only whether full-recipe Let’s Cook includes generated Setup/Step 0. Database Admin exposes these raw displays fields for troubleshooting.
Organization cooking preferences
The Organization Management category documents both current-org and System Admin organization update routes. Their request body schemas now include the cooking-preference fields that appear near Preferred Recipe Units on the Organization page:
{
"recipe_preferred_units": "as_written",
"show_full_recipe_review_before_current_step_present": "1",
"show_full_recipe_review_before_current_step": true
}
show_full_recipe_review_before_current_step is org-scoped, defaults to true, and affects current-step Let’s Cook render surfaces. It is not a display setting and does not change saved recipes.
Shopping List checked-state endpoint
The Organization Management category includes current-org and by-id profile update endpoints with preferred_time_format (12h / 24h) in the generated form schema. The Create Organization endpoint uses the same System Admin form field names as the UI: preferred_time_zone, preferred_time_format, preferred_locale, admin_email, admin_display_name, and invite_message.
Meal Planner slot create/update endpoints expose start_time and end_time as native time controls. The request value is canonical HH:mm; the visible picker UI can follow the tester PC/browser clock preference, matching the production Meal Planner setting page.
The Shopping Lists category includes Update Checked Shopping Items for POST /shopping-list/{list_id}/toggle. This entry documents both the legacy single-item shape and the rapid Shop a List multi-item shape. Use the updates array when testing rapid checkoffs so the server receives the shopper's desired final state for each row. Prefer item_id in each update because display indexes can change after checked items are sorted. section/index remain a legacy fallback.
A useful API Tester check is to create a manual list, add several rows, then send a compact payload like:
{
"compact": true,
"updates": [
{"section": "unparsed_or_unquantified", "index": 0, "item_id": "sli_example_1", "checked": true},
{"section": "unparsed_or_unquantified", "index": 1, "item_id": "sli_example_2", "checked": true},
{"section": "unparsed_or_unquantified", "index": 2, "item_id": "sli_example_3", "checked": true}
]
}
The response should include verified: true, updated_count, updated_ref_count, and current counts when the request targets a single list. If verified is missing or false, treat that as a regression because the UI relies on this endpoint to avoid rapid-checkoff state loss.
Social Recipe Extension Workflow
The Chrome Extension category now documents the complete deterministic-first social recipe workflow:
- preview captured evidence without persistence
- submit/poll an organization-scoped social import
- run AI preflight only after deterministic extraction
- inspect anonymous exact-post reusable conversions
- load AI profile/cost options
- create and poll a social AI job
- review/import partial or complete candidates
- cancel an active review
- inspect the bounded multipart media contract
Use social_recipe_imports and social_recipe_ai_jobs option sources for import/job ID fields. The multipart media endpoint is documented-only because the API Tester does not attach files yet. The preview examples keep provider content IDs as strings; this is essential for 19-digit TikTok IDs, which exceed JavaScript's safe integer range. Pinterest examples include pinterest_current_pin_matched so stale single-page navigation data can be rejected explicitly.
The API Tester remains a diagnostic surface, not a replacement for the extension's browser capture. It cannot reproduce DOM isolation, active-player geometry, or thumbnail pixels, but it can verify server identity enforcement, deterministic completeness decisions, persisted import state, AI review state, and safe failure diagnostics.
Execution Flow
The API Tester uses:
POST /api-tester/execute
Execution flow:
- Confirm the user has
api_tester.view. - Look up the endpoint in the curated registry.
- Confirm the endpoint is visible to the current user role/permissions.
- For mutating calls, require
api_tester.execute_mutatingand explicit checkbox confirmation. - Build the target path from declared path/query parameters only.
- Parse and validate JSON body text if present.
- Add either session authentication/CSRF headers or an API token authorization header.
- Execute the existing Flask route in-process.
- Sanitize response headers/body before returning them to the tester UI.
- Audit the tester execution without storing secrets.
The execution service lives in:
inky_admin/services/api_tester_execution_service.py
Response and header secret masking lives in:
inky_admin/services/api_response_sanitizer_service.py
Initial Endpoint Coverage
Current curated categories include:
- API Tester
- Current User
- Status / Runtime
- Recipes
- Recipe Discovery
- Displays
- Emoji
- Meal Planner
- Shopping Lists
- Jobs
- Performance
- Let’s Cook
- Backups
- Chrome Extension
- Kiosk Display
The second pass added more typed path/query inputs, including select lists, booleans, numbers, dates, URLs, and request-schema display where a JSON body is expected.
The third pass separated examples/placeholders from actual defaults. Regular path/query inputs now start blank, while context-derived fields such as org_id use the selected API Tester organization context. When multiple organizations are available, organization fields use a browser typeahead/datalist containing the allowed organization IDs. This avoids fake defaults like org_... while still making valid context IDs easy to use.
The third pass added response-body search. The fourth pass made that search toolbar always visible whenever the response card is visible. Clicking inside the response area and pressing Ctrl+F/Cmd+F now focuses the in-response search box instead of showing the browser-level page search. Use Enter/Shift+Enter or the arrow buttons to move between matches.
Current curated coverage now also includes Recipe Sharing status/summary endpoints, Support Request status, Emoji cache status/rebuild, additional Meal Planner actions, and additional Chrome Extension Shop With review endpoints.
The fifth pass adds a documented API Tester options endpoint, more kiosk display endpoints, additional Let’s Cook control/timer endpoints, context-aware kiosk display typeahead values, Shop With provider/store-mode option sources, safer token session storage, and an optional Chrome Extension token handoff.
The sixth pass expands curated coverage again, including more Recipe Discovery, Meal Planner slot/move/settings, Recipe Sharing, Shopping List item/cart, Emoji registry, backup-provider test, and Noun Project test endpoints. Endpoint category groups in the sidebar are now collapsible and start expanded by default, so larger groups such as Backups and Chrome Extension stay easier to navigate as the registry grows.
The seventh pass fixes the public spec description builder and keeps endpoint descriptions focused on what each endpoint is for. Authentication requirements are shown in their own metadata area, so descriptions should explain the use case, workflow, or troubleshooting value instead of repeating the auth model.
The eighth pass fills in the remaining known /api and /kiosk Flask routes from the static route inventory. New coverage includes more Recipe Sharing lifecycle/import/export endpoints, scheduled display-assignment cancellation, the kiosk page route, and Remote Display Client pair/state/heartbeat/preview routes. Routes that require multipart file upload or return binary image data are documented in the tester but marked Documented only until the UI has a safe file/binary execution flow.
Remote Display Client coverage now documents the full lifecycle:
Generate pairing code → Pair → Read state → Download preview
→ Heartbeat with physical-panel acknowledgement → Unlink
Deployed clients authenticate to state, preview, heartbeat, and unlink with Authorization: Bearer <client token>. The client_token query field remains only as an API Tester convenience. Heartbeat examples include the last physically displayed preview, physical update time, successful poll time, Waveshare panel type, grayscale mode, and four gray levels. The binary preview route remains Documented only.
The attached-local display Link/Relink and Unlink Admin routes are also documented but not executable from the tester. They change encrypted live client state and should be used through Display Details, where atomic relinking and waiting/error states are handled safely.
The ninth pass improves discoverability for the existing add-recipe API at /api/recipes/add. It is listed as Add Recipe API under Chrome Extension because it uses the same API-token flow as the extension, and endpoint search now matches individual words instead of requiring the whole typed phrase to appear contiguously.
The tenth pass adds the Recipe Library's session-authenticated add flows that do not live under /api: /add-recipe, /manual-recipe, and /select-recipe. It also documents the editable-content prepare/save routes and shows the archive route as Documented only because archiving is destructive and should stay behind stronger safeguards before tester execution is enabled. These routes remain separate from the Chrome Extension add-recipe API; no route cleanup or aliasing is required just to make them available in the tester.
The eleventh pass adds explicit request encoding metadata and broader coverage for older session routes outside /api. Endpoints can now declare request_encoding as json, form, multipart, query, or none; the execution service sends form-backed routes as form data while keeping the tester body editor as a structured JSON object of fields. New coverage includes legacy display actions, Job Status actions, Shopping List UI actions, Mobile UI actions, Kitchen Inventory mobile/admin flows, and a broader Settings category for scoped configuration, GeoIP/flag utilities, Noun Project rules, auth provider settings, organization login providers, MFA policy, and related configuration helpers.
The twelfth pass improves navigation for the much larger registry. Endpoint groups are now sorted alphabetically, endpoints inside each group are sorted alphabetically by display name, and group headers stick to the top of the sidebar while scrolling until the next group takes over. This pass also rounds out the remaining useful non-page action routes from the static route inventory, including Display Administration, Connections, Organization Management, User Management, Data Purge, Database Admin, additional Meal Planner routes, shopping department actions, and legacy compatibility routes. The curated registry now accounts for the remaining non-page action routes that are useful to document or test; login/auth challenge flows, OAuth callbacks, webhooks, public share callbacks, static/media routes, and normal HTML page shells remain intentionally excluded.
The thirteenth pass adds Postman collection export for externally useful API surfaces. The fourteenth pass expands that export to include practical session-authenticated action endpoints as well, including recipe search/details, Recipe Library add/manual add, Meal Planner, Shopping Lists, Displays, Kiosk controls, Let’s Cook, Kitchen Inventory, Settings utilities, Job Status, Backups, and Support Requests. Postman requests use blackcap_postman_token for session-authenticated routes, while API-token routes continue to use blackcap_api_token. The fifteenth pass added explicit Postman setup helpers. The twentieth pass replaces cookie-plus-CSRF Postman usage with a signed 8-hour Postman bearer token issued from the API Tester and audited with source api_tester_postman. Documented-only endpoints, destructive endpoints, user/org lifecycle operations, Database Admin, Data Purge, auth challenge flows, OAuth callbacks, webhooks, static/media routes, and normal page shell routes remain excluded.
The first pass intentionally avoids highly destructive endpoints such as disable, purge, restore, ownership transfer, and broad deletes. Some normal item-level editing and lifecycle endpoints are included because they are useful for API testing, but they still require the API Tester mutating permission and explicit confirmation.
Postman Collection and Environment
The API Tester Postman dialog exports two files:
- Download Collection exports the curated Blackcap API and session-action Postman collection.
- Download Environment exports a companion environment containing every variable used by the collection.
The collection includes generated request bodies, path/query variables, request-description notes, and example successful responses where registry metadata allows a useful sample. The environment initializes base_url from the current browser-visible API Tester URL and leaves secrets as placeholders. When Blackcap is behind stunnel or another TLS terminator, the export prefers the configured external base URL or same-host browser referrer/origin so the value stays https:// instead of the local backend http:// scheme. Use the dialog's Copy Postman Token button to fill blackcap_postman_token when testing session-authenticated Admin/Mobile/UI action routes.
For detailed setup instructions, see:
api-tester.md
Dynamic Typeahead Options
The API Tester exposes read-only option lookups through:
GET /api-tester/options/<source>
These routes require the same logged-in api_tester.view permission and return only values the current session/context is allowed to see. The option service lives in:
inky_admin/services/api_tester_option_service.py
Supported option sources include recipes, displays, kiosk displays, scheduled display assignments, shopping lists, recent jobs, active Let’s Cook sessions, Meal Planner slots, Meal Planner entries, recipe shares, recipe share notifications, recipe share recipient targets, connections, Shop With providers, Shop With store modes, and safe API-token metadata. These are used for fields such as recipe_id, display_id, list_id, entry_id, slot_id, public_id, provider, store_mode, and similar identifiers. Token option metadata includes labels/prefixes only and never returns raw token values. Do not query tables directly from API Tester UI code; add new read-only option sources to the service layer when more typeahead controls are needed.
Structured Request Body Builder
For JSON POST endpoints with a curated request schema, the UI now renders guided body inputs above the raw JSON textarea. Supported schema hints include:
enumfor dropdownsoptions_sourcefor typeahead-backed IDsformatfor date/time/url controlstype: boolean,number, andintegercontrols- nested
objectgroups - expandable
arraycollections with add/remove rows
Collections render as collapsible sections. Each row is also collapsible, which helps navigate payloads such as display assignments, meal-plan selections, external household-list imports, and Shop With completion results. The raw JSON textarea remains visible and is synchronized from the structured fields, so advanced testers can still review or edit the exact outgoing body.
Structured fields auto-sync into the JSON body as they change. The Rebuild JSON from fields button manually regenerates the JSON from the guided controls if the body looks stale. The Load JSON into fields button parses manually edited JSON and repopulates matching structured controls.
Request Encoding
Each endpoint definition can declare how the tester should submit the request body:
jsonsendsapplication/jsonthrough the existing route.formconverts the structured body object into form fields, including repeated form values for arrays.multipartis reserved for routes that need multipart form structure; file inputs remain documented-only until the tester has a safe upload control.queryornoneindicates that the route does not need a request body.
The UI shows the selected request encoding next to the endpoint metadata. Curl examples now mirror the declared encoding with --data, --data-urlencode, or -F placeholders as appropriate.
Shop With store_mode
store_mode is a provider-specific hint used by the Chrome Extension Shop With flow.
- For Shipt, it represents the Shipt storefront/slug, such as
stores,target,costco, or another configured/free-form Shipt store value. - For Amazon, it selects the Amazon shopping surface, such as
amazon,amazon_fresh,whole_foods, oramazon_grocery. - Providers such as Target, Walmart, and Instacart usually ignore
store_modeunless their provider configuration is later enabled for multiple store modes.
The API Tester exposes store_mode as a typeahead backed by configured provider/store-mode metadata. Leaving it blank lets the Chrome Extension endpoint use the provider default or infer the mode from the active provider URL when applicable.
The API Tester registry also includes newer Household List and Recipe Library maintenance actions. Use Pin or Unpin Household Item (POST /shopping-list/{list_id}/manual-item/anchor) to test recurring Household staples without completing the persistent Household List row. Use Bulk Change Recipe Type (POST /api/recipes/bulk-recipe-type) to validate Recipe Library mass type changes and the expected no-cache-rebuild behavior for recipe-type-only metadata edits.
Security Notes
The API Tester is powerful. Keep these rules intact:
- Do not mount it under
/admin. - Do not expose it without a logged-in session.
- Do not allow display tokens or Chrome Extension tokens alone to access
/api-tester. - Do not store pasted API tokens.
- Do not persist API Tester tokens server-side. Browser session storage is opt-in and local to the browser session.
- Do not log raw API tokens, Postman bearer tokens, session cookies, session IDs, OAuth secrets, SMTP passwords, display tokens, or provider secrets. The API Tester can issue a signed 8-hour Postman bearer token to the current logged-in browser for clipboard use, but it must not log or persist the raw token.
- Keep response display scoped to the selected endpoint. The browser stores each endpoint's last response only in
sessionStorage; switching organizations clears that response cache. - Keep examples as examples only. Do not use sample values as hidden defaults for request controls unless a field is explicitly context-derived, such as the selected organization id.
- Do not add arbitrary query parameter forwarding.
- Do not include destructive endpoints by default.
- Keep backend route/service permission checks authoritative.
- Keep all database access in existing service/repository layers.
Adding a New Endpoint
- Confirm the route is safe and useful to test.
- Add an
EndpointDefinitioninapi_tester_registry_service.py. - Set
required_permissionto match the underlying feature permission. - Set
authtosession,api_token, oreither. - Mark
read_only=Falsefor any endpoint that changes data. - Add path/query parameters explicitly.
- Use
examplefor helper text/placeholders, not for auto-filled default values. Usedefault_valueonly when a true default should be submitted. Usevalue_source="current_org_id"andoptions_source="organizations"for organization-context fields. - Set
request_encodingto match the underlying route:jsonfor JSON APIs,formfor form-backed UI routes,multipartonly when the route needs multipart data, andnone/querywhen no body is expected. - For request bodies, add
enum,options_source,format, nestedproperties, and arrayitemsmetadata when available so the structured request builder can render useful controls. - Use
options_source="kiosk_displays"for kiosk-only display IDs,options_source="displays"for general display IDs,options_source="recipes"for recipe IDs,options_source="meal_plan_slots"for Meal Planner slots, andoptions_source="meal_plan_entries"for Meal Planner entries. - Write descriptions as two short sentences when possible. Keep them focused on what the endpoint is for, what workflow it supports, or what it helps troubleshoot. Do not repeat authentication requirements in the description because the UI renders that separately. If a description is short, the registry service adds a second purpose/context sentence in the public spec.
- Test as System Admin and, if applicable, Org Admin.
- If the endpoint should be callable externally, confirm it qualifies for the Postman generator. API-token, remote-display-client, and public/tokenized share endpoints usually qualify; session-only Admin/Mobile UI routes usually do not.
- Confirm no secrets appear in the response viewer, Postman collection, or audit log.
Restart
After deploying these files, restart the Admin service:
sudo systemctl restart inky_admin.service
sudo systemctl status inky_admin.service --no-pager
Testing Checklist
/api-testerloads for authorized logged-in users./api-testeris not under/admin./api-tester/specrequires login andapi_tester.view./api-tester/executerequires login,api_tester.view, and CSRF.- Lower roles cannot access the tester by default.
- Spec output is filtered by current permissions.
- Read-only session endpoints run successfully.
- Current organization context is respected.
- System Admin can switch organization context from
/api-tester. - Multi-organization Org Admin users can switch among their allowed organizations.
- Switching context reloads
/api-tester/specand clears endpoint response cache. - Optional
org_idfields show the selected real organization id, notorg_.... - System Admin/multi-org users get typeahead organization choices where an endpoint accepts
org_id. - Recipe, display, shopping list, job, and similar identifier fields use context-aware typeahead options where available.
- Kiosk endpoints use kiosk-display typeahead values only.
- Shop With provider and store-mode fields use configured provider/store-mode typeahead options.
/api-tester/options/<source>returns safe option values and does not expose raw token values./api-tester/postman-collectiondownloads a valid Postman v2.1 collection./api-tester/postman-environmentdownloads a valid companion Postman environment with the current browser-visiblebase_urlfilled in and secret values left as placeholders.- The Postman collection and environment use variables/placeholders and do not include real API tokens, Postman bearer tokens, client tokens, or share tokens.
- The Postman collection includes API-token endpoints and useful session-authenticated action endpoints while using placeholder variables for
blackcap_api_tokenandblackcap_postman_token. - The API Tester Postman button opens a setup dialog instead of showing Postman setup controls in the main sidebar.
- The setup dialog offers both Download Collection and Download Environment actions.
- The setup dialog can issue and copy an 8-hour Postman bearer token for the
blackcap_postman_tokenPostman variable after an explicit button click. - Postman token audit events use source
api_tester_postman. - The Postman collection excludes documented-only, destructive, user/org lifecycle, Database Admin, Data Purge, OAuth callback, webhook, static/media, and page-shell routes.
- Searching for
add recipe api,create recipe, or/api/recipes/addfinds the Chrome Extension Add Recipe API endpoint. - Searching for
recipe library add,manual recipe,/add-recipe, or/manual-recipefinds the session-authenticated Recipe Library add flows. - Endpoint groups are sorted alphabetically and endpoints within each group are sorted by display name.
- Long endpoint groups keep their group header visible while scrolling until the next group header takes over.
- POST endpoints with curated schemas show guided inputs, dropdowns, typeaheads, and expandable collection rows.
- Form-backed endpoints show request encoding as form and submit through form data rather than JSON.
- Settings endpoints are visible only to users with the matching settings/configuration permissions.
- Rebuild JSON from fields and Load JSON into fields behave as expected after manual JSON edits.
- Non-context request controls start blank while still showing helper examples.
- Response search is visible whenever a response is shown.
- Click inside a response body and press Ctrl+F/Cmd+F to focus the response search box.
- API-token endpoints require a pasted token.
- API-token endpoints can optionally reuse a token remembered in browser session storage.
- The Chrome Extension token handoff works only when the extension is installed, configured for the current Blackcap host, and reloaded with the supporting content-script version.
- Chrome does not autofill the endpoint search box with login data.
- Chrome does not autofill the API token box with the account password.
- Invalid/revoked tokens show clean errors.
- Curl examples use
<API_TOKEN>, never the real token. - Mutating endpoints require the confirmation checkbox.
- Mutating endpoints require
api_tester.execute_mutating. - Documented-only endpoints show in the registry but cannot be executed directly from the tester.
- Multipart file upload and binary preview endpoints are documented-only until a safe UI execution flow is added.
- No highly destructive endpoints are exposed by default.
- Admin UI, Mobile UI, Kiosk, and Chrome Extension behavior remain unchanged.
- No new direct SQL calls were introduced by the API Tester implementation.
API Tester button styling
API Tester action buttons should follow the Blackcap style of using concise emoji cues where they improve scanability. Endpoint list buttons still prioritize method/path readability, while action buttons such as Postman, Reload, Try It, Load Example, Copy Postman Token, Clear, and structured-body helpers include visible emoji labels.
Voice Assistant testing
The API Tester exposes Voice Assistant Test → Alexa Integration Status and Voice Assistant Test → Google Home Integration Status so platform OAuth/client status, HTTPS posture, and provider URLs can be copied into the provider consoles. Configure credentials first in Platform → Voice Assistant Providers. Alexa uses the generated Alexa OAuth Client ID/Secret for both the ask Blackcap custom skill and the Alexa Smart Home skill. Google Home uses its own generated OAuth Client ID/Secret for Cloud-to-cloud account linking.
Provider-facing fulfillment endpoints are not general API Tester endpoints:
/voice/alexa/skillexpects signed Alexa Custom Skill requests./voice/alexa/smarthomeis normally called by the AWS Lambda relay for Alexa Smart Home directives./voice/google-home/fulfillmentexpects Google Home Cloud-to-cloud OAuth bearer tokens and intent payloads.
Use Voice Assistant Test → Internal Voice Command Test for safe service-layer command coverage. It exercises the provider-neutral command service used by all three surfaces: ask Blackcap, Alexa Smart Home, and Google Home. The endpoint now covers the full current command set: start/end cooking, next/previous step, start/pause/resume/stop/cancel timer, add/subtract one or five minutes, and timer status.
Recommended quick API Tester checks after voice-assistant changes:
- Run
START_LETS_COOKagainst a known display. - Run
NEXT_STEPandPREVIOUS_STEPagainst the same display. - Run
START_TIMER,PAUSE_TIMER, andRESUME_TIMER. - Run
ADD_TIMER_MINUTESwithminutes=1andSUBTRACT_TIMER_MINUTESwithminutes=1. - Run
END_LETS_COOK. - Verify the command log in Database Admin records the provider, skill type, endpoint id when provided, display resolution source, status, and response summary without raw provider payloads.
Let’s Cook voice takeover endpoint
The API Tester includes Show Entire Recipe for Voice Session under Let’s Cook. It posts to /api/lets-cook/sessions/{session_id}/show-entire-recipe and exercises the same per-session render override used by Admin/Mobile/Kiosk/touch receiver takeover controls. The action preserves the active session, step/ingredient completion state, timers, and display default settings.
Database Admin / SQL Console coverage
The Database Admin category now documents the in-page tab endpoints used by the Database page shell:
GET /admin/database/api/tabs/resourcesGET /admin/database/api/resource-countsGET /admin/database/api/tabs/maintenancePOST /admin/database/api/tabs/maintenance/{action_key}GET /admin/database/api/tabs/sqlPOST /admin/database/api/tabs/sql
These fragment endpoints should be used when testing tab behavior because switching Resources, Maintenance, and SQL Console from the UI should not reload the full Database page. Resource counts and overview metrics are loaded separately after the shell renders. The resource-count example includes counts_complete, failed_resources, per-resource exists/error fields, and the aggregate header metrics so a partial count failure can be diagnosed without treating every resource as failed.
Maintenance action inputs use the dynamic database_maintenance_actions option source. It returns only actions supported by the active database provider and permitted for the current user. SQLite testers therefore see integrity, quick-check, WAL, vacuum, and analyze actions as applicable; PostgreSQL testers see connectivity and analyze actions rather than SQLite file operations.
The SQL Console entries document the current guardrails:
- SQL execution is System Admin only.
- Submit exactly one read-only statement using the active SQLite or PostgreSQL provider's supported syntax.
WITH/ CTE statements are blocked; use joins or derived subqueries instead.limitis the rows-per-page value when the SQL statement does not include its ownLIMIT.- Organization-scoped tables are allowed, but raw SQL is not automatically scoped to the current organization.
- Tables with protected fields can be queried and joined, but protected fields cannot be selected; avoid
SELECT *andalias.*for those tables.
The schema helper endpoints are also documented:
GET /admin/database/api/sql-console/schemareturns the active provider object plus table and safe-column metadata for autocomplete.GET /admin/database/api/sql-console/schema/{table_name}/sampleslazy-loads org-scoped example values for one table at a time.GET /admin/database/sql/schema-exportdownloads the Markdown schema brief for LLM or AI-assisted query drafting.
The schema metadata example includes provider_name, backend_name, sql_dialect, dialect guidance, and the provider-specific export filename. This makes it possible to confirm that the tester and SQL editor are using the same active backend before running a query.
The schema export endpoint is safe to download, but the tester marks it as a file/diagnostic endpoint because it returns Markdown rather than JSON. The downloaded filename and opening guidance identify the active SQLite or PostgreSQL provider and SQL dialect so an LLM does not generate syntax for the wrong backend. PostgreSQL exports also use the live physical column types as the source of truth: integer-backed flags use 1/0, native booleans use TRUE/FALSE, text-backed timestamps and JSON require safe casts, matching join types should not be cast unnecessarily, and UNION/UNION ALL output types must align. The export also includes production-query guidance that excludes regression test and diagnostic clone organizations with regression_test_organizations and regression_diagnostic_clones, plus display-assignment guidance that uses display_content_assignments instead of app_state JSON.
Meal-plan, Recipe Sharing, and display-deletion additions
The curated registry includes these workflow-specific entries:
- Recipe Add to Meal Plan Options —
GET /api/meal-planner/recipe-add-options/{recipe_id}with optionaldateandslot_idquery parameters. The response exposes active slots, slot-specific people served, the selected multiplier, and the ordered recipe-specific multiplier choices used by the Recipe Library popup. - Add Home Recipe to Other Date —
POST /api/meal-planner/home-future-entry.plan_datemust be after tomorrow in the organization time zone. This is a mutating, CSRF-protected entry and requires API Tester mutation permission. - Outbound Recipe Share Links —
GET /api/recipe-shares/outbound/activewithstatus=active|expired|completed. The registry name reflects that the endpoint now serves history filters rather than only active links. - Delete Display —
POST /admin/displays/{display_id}/delete, documented as destructive and not safe to run from the tester. The optionalreplacement_default_display_idis required when deleting the current default. The production route still enforces organization scope, only-display protection, active Let’s Cook protection, assignment cleanup, and replacement-default validation.
Mass Refresh Cache and Delete on Recipe Library intentionally reuse the existing single-recipe endpoints and therefore do not add separate bulk API Tester definitions:
POST /refresh-recipe/{recipe_id}POST /delete-recipe/{recipe_id}
MFA setup/challenge routes remain excluded because they operate on incomplete-login session state and authentication secrets. Existing policy/reset administration entries provide the appropriate tester coverage.
Home dashboard and display assignment coverage
The Displays category now documents the shared assignment routes used by Home, the Displays page, and Display Details:
- Assign Display Content (
POST /api/displays/assign-content) supports recipe, menu, meal-plan, and attached local e-ink Client assignment. Client is valid only for the one attached local e-ink display, only as immediate current content, and cannot be scheduled or made default. For meal plans,settings.viewcan beday,today_tomorrow,week, ormonth. - Return Displays to Default (
POST /api/displays/return-default) returns one or more displays to their configured default content. - Start Let’s Cook Session (
POST /api/lets-cook/sessions) is the tester entry point for Assign Content Let’s Cook behavior. Usedisplay_id: "here"to create a local/Admin-console cooking session, or pass a display id to start Let’s Cook for a display. A remote Raspberry Pi client session is allowed even when its fast preview watcher is disabled or stopped; the response then includeswarningandwarningsfields explaining that later step, ingredient, and timer updates may be delayed.
Example Today & Tomorrow meal-plan assignment:
{
"display_ids": ["disp_..."],
"content_mode": "current_meal_plan",
"action": "show_now",
"settings": {
"view": "today_tomorrow",
"anchor_policy": "current_day"
}
}
Example Return to Default request:
{
"display_ids": ["disp_..."]
}
Example Here Let’s Cook request:
{
"recipe_id": "recipe_...",
"display_id": "here",
"source": "api_tester",
"multiplier": 1,
"restore_display_content": true
}
System audit background actions
The API Tester registry includes the System-page background actions for Direct SQL Audit, Database Parity Audit, safe parity repair, and compact audit-job status polling. The parity audit target remains read-only; the repair endpoint requires the explicit repair-safe-database-gaps confirmation value and is not marked safe to run automatically.
Attached e-ink Client API coverage
The Remote Display Client category documents the full pull-client lifecycle:
POST /api/display-client/pairexchanges a short-lived code for a durable client token.GET /api/display-client/statereturns the remote display state without embedding the token in the preview URL. It also returnsnormal_pull_interval_secondsand advertises a 5-secondpull_interval_secondswhileactive_lets_cook=true; normal content returns to the configured interval, 30 seconds by default.GET /api/display-client/previewis documented-only because it returns binary image data.POST /api/display-client/heartbeataccepts physical-display acknowledgement metadata such as the last preview displayed, panel update time, grayscale mode, and four-level panel capability.POST /api/display-client/unlinkrevokes the presented durable client token. It is destructive and requires API Tester mutation permission.
The attached Pi display’s Link/Relink/Unlink Admin forms are intentionally not separate executable API Tester endpoints; they manage an encrypted local token and incomplete pairing state through the Display Details workflow.
Kitchen Inventory archive and restore
The curated registry documents Admin and Mobile Kitchen Inventory archive/restore routes. Archive/delete entries require inventory.delete, current-organization scope, and CSRF; they are marked documented-only/destructive so the API Tester cannot accidentally delete a real item. The archive examples show that deleting an on-hand item returns status=archived and is_on_hand=false, while preserving its pre-delete on-hand state internally. Restore entries reuse the same public inventory ID and return an item that was previously on hand to status=active and is_on_hand=true.
The generic Update Database Resource Row entry also documents the Database Admin lifecycle safe edit. For inventory_items, status may transition only between active and archived; the request additionally requires inventory.delete, is organization-scoped, and is routed through the Kitchen Inventory service rather than written directly. The route remains documented-only because arbitrary resource editing requires resource-specific safeguards.
AI Usage and AI Seed administration
The curated AI Usage category exposes authenticated read APIs for the completed AI administration experience:
- AI Usage Report —
GET /api/admin/ai/usage - Download AI Provider Billing Reconciliation CSV —
GET /admin/ai/usage/reconciliation.csv(System Admin only) - Organization AI Seed Balance —
GET /admin/ai/organizations/{organization_id}/drupeletes - Organization AI Seed Recent Adjustments —
GET /admin/ai/organizations/{organization_id}/drupeletes/adjustments - Personal AI Seed Balance —
GET /admin/ai/users/{user_id}/drupeletes
The JSON usage report uses the same authorization, filters, server-side paging, summary totals, and organization/user scope as the AI Usage page. Org Admin responses omit provider request identifiers, provider input/output/image tokens, provider usage payloads, and provider response metadata. System Admin responses may include those billing diagnostics. Provider credentials and raw prompts are never returned.
The reconciliation endpoint is intentionally visible only to System Admins and returns CSV. Balance adjustment writes are not marked as safe API Tester operations because they create audited financial-style ledger changes. Use Organizations or Users for normal adjustments.
Useful report query parameters include organization_id, date_from, date_to, provider_type, provider_connection_id, use_case_key, profile_key, user_id, outcome, selected_source, sort, page, and per_page. organization_id=all means All Organizations for System Admin or All My Organizations for an authorized multi-organization Org Admin.
Postman usage
Blackcap can export a Postman collection and companion environment from the logged-in API Tester at /api-tester. The collection is generated from the curated API Tester registry, so it avoids documented-only routes, destructive routes, callback/webhook flows, static assets, normal page shells, and other routes that do not make sense to call directly from Postman.
Download from the API Tester
- Log in to Blackcap.
- Open
/api-tester. - Click the Postman button in the sidebar.
- Download the collection with Download Collection.
- Download the environment with Download Environment.
- Import both files into Postman.
- Select the imported Blackcap API and Session Actions Environment environment before running requests.
The collection contains request bodies, path/query variables, request descriptions, and example responses where the API Tester registry has enough metadata to generate them safely.
Environment variables
The environment file defines all variables used by the collection. The base_url value is filled in from the browser-visible API Tester URL at download time; secret values remain placeholders until you paste the values you need. When Blackcap is behind stunnel or another TLS terminator, the export prefers the configured external base URL or same-host browser referrer/origin so the value stays https:// instead of the local backend http:// scheme.
Common variables:
| Variable | Purpose |
|---|---|
base_url |
Base Blackcap URL, such as https://blackcap.example.com |
blackcap_api_token |
Chrome Extension/API-token value for API-token endpoints |
blackcap_postman_token |
8-hour bearer token copied from the API Tester for session-authenticated endpoints |
recipe_id |
Recipe ID or slug to use in recipe endpoints |
display_id |
Display ID to use in display endpoints |
list_id |
Shopping list ID to use in shopping-list endpoints |
provider |
External shopping provider key, such as Google Keep, Amazon/Alexa, Target, Walmart, or Instacart provider values |
store_mode |
Optional provider-specific mode; leave blank unless testing a provider that needs it |
client_token / pairing_token |
Remote Display Client token values |
recipe_share_public_id / recipe_share_token |
Recipe share import/export token values |
API-token authentication
Chrome Extension and external API-token endpoints use:
Authorization: Bearer {{blackcap_api_token}}
Use an existing Blackcap API token from the Admin UI or Chrome Extension configuration. Do not paste this token into request descriptions or committed files.
API Tester session-token authentication
Many Admin, Mobile, Recipe Library, Meal Planner, Shopping List, and Settings routes require a logged-in Blackcap user context. In Postman, these routes use an API Tester-issued bearer token instead of copying the browser session cookie and CSRF token:
Authorization: Bearer {{blackcap_postman_token}}
To copy the Postman token:
- Open
/api-testerwhile logged in. - Select the organization context you want the token to use.
- Click Postman.
- Click Copy Postman Token and paste it into the
blackcap_postman_tokenenvironment variable.
The token lasts for 8 hours, is scoped to the current user and organization context, and should completely replace the environment variable value. Treat it like a password and clear it when you finish testing.
AI Usage collection folder
For users who can see the corresponding API Tester entries, the generated Postman collection includes an AI Usage folder with the safe read-only reporting and balance-inspection endpoints:
GET /api/admin/ai/usageGET /admin/ai/usage/reconciliation.csvfor System AdminsGET /admin/ai/organizations/{organization_id}/drupeletesGET /admin/ai/organizations/{organization_id}/drupeletes/adjustmentsGET /admin/ai/users/{user_id}/drupeletes
The copied Postman token preserves the signed-in user's permissions and organization context. Provider request IDs and provider-reported token counts remain System Admin-only. The collection intentionally omits AI Seed adjustment writes because those operations change audited balances.
Request examples
The generated collection includes request examples in the actual Postman request definitions:
- path variables are converted to Postman variables such as
{{recipe_id}}and{{display_id}} - useful query parameters are included but optional ones may be disabled by default
- JSON endpoints include sample JSON bodies when the registry has a request schema or example payload
- form-backed routes include
x-www-form-urlencodedfields - multipart routes include non-file field metadata and file placeholders where applicable
- saved example responses are included to show the expected shape of successful responses
If a request body is too broad for a safe generic example, use the API Tester structured request builder first, then copy the resulting JSON/form values into Postman.
Why Basic Auth is not used
Blackcap's session-authenticated routes rely on the normal login session for user identity, effective role, organization context, MFA/trusted-browser state, session timeout behavior, CSRF protection, and permission checks. Basic Auth would require a separate authentication layer and could accidentally bypass or duplicate important behavior.
Use Chrome Extension API tokens for Chrome Extension/external routes and the copied blackcap_postman_token for session-authenticated Admin/Mobile/UI action routes.
API Tester Postman token
The API Tester-issued Postman token is a Blackcap-specific token type. It is not Basic Auth and it is not the same as the Chrome Extension API token. It is signed with the app secret, valid for 8 hours, scoped to the current logged-in user and selected organization context, and audited with source api_tester_postman.
A Postman token is intended for support/developer testing of session-authenticated routes from Postman. It should not be used by the Chrome Extension, display clients, or long-running external integrations.
Safe usage notes
- Do not commit exported environments after filling in secrets.
- Clear
blackcap_postman_tokenandblackcap_api_tokenwhen finished. - Prefer test recipes, displays, and shopping lists when running mutating requests.
- Avoid running collection requests in bulk against a production organization unless you have reviewed the request bodies and variables.
- Use the in-browser API Tester first for complex mutating requests because it has stronger guided inputs, context-aware typeaheads, and explicit mutation confirmation.