Discovery & Readiness
Discover accessible brands, publishing targets, platform capabilities, and content readiness.
Use these four read operations and one explicit provider-backed refresh to discover the caller's exact authority, choose a connected target, retrieve its live TikTok privacy choices when required, and inspect Wahlu's public platform rules. Follow the resolved links returned by the API instead of constructing brand routes yourself.
Get agent context
/v1/contextRequires a valid API key but no additional scope. It returns the actor, workspace, the key's exact scopes and brand restrictions, accessible brands, and resolved links. Credentials and provider secrets are never included.
curl https://api.wahlu.com/v1/context \
-H "Authorization: Bearer wahlu_live_your_api_key_here"{
"success": true,
"data": {
"actor": { "user_id": "user_01k0agent" },
"workspace": { "id": "workspace_01k0acme", "name": "Acme Social" },
"api_key": {
"id": "api_key_01k0agent",
"name": "Content agent",
"scopes": [
"brands:read",
"integrations:read",
"media:read",
"media:write",
"posts:read",
"posts:write",
"schedule:read",
"schedule:write"
],
"brand_access": "restricted",
"brand_ids": ["brand_01k0acme"]
},
"brands": [
{
"id": "brand_01k0acme",
"name": "Acme",
"links": {
"targets": {
"href": "/v1/brands/brand_01k0acme/targets",
"required_scopes": ["integrations:read"]
},
"media_imports": {
"href": "/v1/brands/brand_01k0acme/media/imports",
"method": "POST",
"required_scopes": ["media:write"]
},
"content_items": {
"href": "/v1/brands/brand_01k0acme/content-items",
"method": "POST",
"required_scopes": ["posts:write"]
}
}
}
],
"links": {
"platform_capabilities": {
"href": "/v1/platforms/capabilities",
"required_scopes": []
}
}
},
"meta": { "request_id": "req_context_01k0" }
}List brand targets
/v1/brands/:brand_id/targetsRequires integrations:read. Use the brand ID from context, or follow that brand's links.targets.href. Each target reports its connection state, schedulable readiness, capabilities, blockers, and bounded repair actions.
A connected target has an integration_id; carry that exact ID into draft preflight and Schedule creation. A disconnected discovery row can have a null integration ID. Provider tokens, provider account IDs, and complete provider profiles are not returned.
curl https://api.wahlu.com/v1/brands/brand_01k0acme/targets \
-H "Authorization: Bearer wahlu_live_your_api_key_here"const target = payload.data.targets.find(
(candidate) => candidate.schedulable && candidate.integration_id
);
if (!target) {
const guidance = payload.data.targets.flatMap(
(candidate) => candidate.repair_actions.map((action) => action.guidance)
);
throw new Error(guidance.join(" ") || "No schedulable target is available");
}
const integrationId = target.integration_id;Get target dynamic options
/v1/brands/:brand_id/targets/:integration_id/dynamic-optionsRequires integrations:read. Call this only after selecting an authorised TikTok target. Wahlu reads that exact connected account live and returns its currently supported creator_privacy_levels plus bounded comment, duet, and stitch constraints. This compatible read never refreshes credentials, acquires a provider-effect lease, or changes integration status. If the current credential cannot safely support the read, the request fails explicitly.
Never infer or default a privacy level. Present the returned options to the user and carry the selected canonical value into the precise draft privacy update. Reconnection, foreign-target, malformed-provider, and dependency failures return explicit errors instead of stale choices.
curl https://api.wahlu.com/v1/brands/brand_01k0acme/targets/integration_01k0tiktok/dynamic-options \
-H "Authorization: Bearer $WAHLU_API_KEY"{
"success": true,
"data": {
"brand_id": "brand_01k0acme",
"integration_id": "integration_01k0tiktok",
"platform": "tiktok",
"kind": "creator_privacy_levels",
"options": [
{ "value": "SELF_ONLY", "label": "Only you" },
{ "value": "MUTUAL_FOLLOW_FRIENDS", "label": "Friends" }
],
"constraints": {
"comments_disabled": false,
"duets_disabled": true,
"stitches_disabled": true
},
"retrieved_at": "2026-08-09T02:00:00.000Z",
"links": {
"self": {
"href": "/v1/brands/brand_01k0acme/targets/integration_01k0tiktok/dynamic-options",
"required_scopes": ["integrations:read"]
}
}
},
"meta": { "request_id": "req_dynamic_options_01k0" }
}Refresh target dynamic options
/v1/brands/:brand_id/targets/:integration_id/dynamic-optionsRequires integrations:write. Use this separate medium-risk action when the safe read reports that current credentials cannot proceed. Its strict body is{} and it accepts no idempotency key. The action may rotate stored credentials, update the provider-effect lease, or mark the integration for reauthorisation. It changes no content, creates no Schedule, submits no provider post, and returns no credential or raw provider payload.
curl -X POST https://api.wahlu.com/v1/brands/brand_01k0acme/targets/integration_01k0tiktok/dynamic-options \
-H "Authorization: Bearer $WAHLU_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'Get platform capabilities
/v1/platforms/capabilitiesThis public operation requires no API key. It returns the public platform registry: account modes, post types, media and text rules, settings fields, and agent guidance. Hidden and internal platform records are excluded.
Responses include an ETag and a five-minute public cache policy. Send the ETag in If-None-Match; an unchanged registry returns 304 with no body.
curl https://api.wahlu.com/v1/platforms/capabilities \
-H 'If-None-Match: "previous-etag"'