Auth API · apps

Open an embedded app

POST /api/auth/organizations/{organizationId}/installations/{appId}/launch

Open an embedded app: where its page is in this deployment, and an app session token for the page — the person, the organization and the person's own scopes, for five minutes, accepted by the app's own service alone.

The admin frames the page and hands it the token over the app bridge. onboarding: true is the setup walk framing the app's onboarding page: the token then carries the onboarding claim, the one thing that lets the app serve that page; 409 AppHasNoOnboarding for an app that declares none, 409 InstallationRetiring for a legacy platform draining or retired at go-live, 403 OnboardingLaunchNeedsSetup for a person who does not hold setup:write. The body is optional (400 InvalidInstall for one that is not JSON of that shape). 404 AppNotFound for an app with no page here, 409 AppNotInstalled until it is installed. Appends nothing: a token is not a fact, and nothing changes in the organization. No idempotency key: each call mints a fresh session token, and a second call simply opens the page again.

Access

Requires a signed-in session: Any active member of the organization, checked against its membership by the route

How scopes come from roles: Scopes and roles. Getting a token: Authentication and app tokens.

Retries

No idempotency key: each call mints a fresh session token, and a second call simply opens the page again.

Why every write carries a key: Idempotency and retries.

Facts appended

None. This call records nothing in a journal.

What a fact is: Facts and the journal.

AI agent tool

No agent tool. Opening an embedded app mints a session for its page in the admin's frame; an agent has no page to open and uses the app's own tools.

Connecting an agent: AI agents.

Example

curl
curl -X POST 'https://auth.getmanifold.io/api/auth/organizations/org_01a156d2-8680-7738-ab2e-ff985e454887/installations/app_85cedb60-f616-4fe5-b9ea-dcd3689b4bc6/launch' \
  -H "Authorization: Bearer $MANIFOLD_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
  "onboarding": true
}'
JavaScript (fetch)
const response = await fetch("https://auth.getmanifold.io/api/auth/organizations/org_01a156d2-8680-7738-ab2e-ff985e454887/installations/app_85cedb60-f616-4fe5-b9ea-dcd3689b4bc6/launch", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.MANIFOLD_TOKEN}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "onboarding": true
  }),
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
const answer = await response.json();
Request body · application/json
{
  "onboarding": true
}
Response · 200 · application/json
{
  "url": "https://xero.getmanifold.io/ui",
  "token": "eyJhbGciOiJFZERTQSIsImtpZCI6Imp3a18wMWExNSJ9.eyJzdWIiOiJ1c3JfMDFhMTU3MDkiLCJhdWQiOiJleGFtcGxlIn0.SGVsbG8tc2lnbmVkLWJ5LWF1dGgtc2VydmljZQ",
  "expiresAt": "2026-10-22T03:05:00.000Z"
}

The panel writes this call in other languages. It does not send it: Manifold's APIs do not take calls from a web page on another site, so run the call from your own code or terminal. The whole API as OpenAPI: auth-service.openapi.json. Base URL https://auth.getmanifold.io.

Errors

Every refusal is a status and a JSON body whose _tag names it. A refused call changes nothing.

400

RefusalWhat it meansWhat to do
InvalidInstall reason The install request is not in the shape this call takes.Fix the request body.

401

RefusalWhat it meansWhat to do
Unauthorized reason The token is missing, expired or not one Manifold issued.Get a fresh token and send the call again.
TokenAlreadyUsed tokenId A single-use app token was already spent.Mint a new token for this call.

402

RefusalWhat it meansWhat to do
SubscriptionRequired status The organization's subscription has lapsed, so writes are refused.An owner settles billing. Reads still work meanwhile.

403

RefusalWhat it meansWhat to do
NotAMember The person is not a member of this organization.Check the organization, or invite them first.
OnboardingLaunchNeedsSetup appId Opening an app from the setup walk needs setup:write.Ask an owner or admin for a role that sets up the organization.
TenantRequired userId The token names no organization.Choose the organization, then get a new token.
ScopeRequired required The token's roles do not grant the scope this call needs.Ask an owner or admin for a role that grants it.

404

RefusalWhat it meansWhat to do
AppNotFound appId No such record in this organization.Check the id in the path or the body.

409

RefusalWhat it meansWhat to do
AppNotInstalled appId The organization has not installed this app, or removed it.Install the app first.
AppHasNoOnboarding appId This app has no setup page to open.Open the app from its own page instead.
InstallationRetiring appId, status The app is being retired or was retired at go-live.Nothing to do: it will not be installed again.
MirroredFromSource source This area is fed by your source system until the organization goes live.Make the change in the source system, or go live first.

503

RefusalWhat it meansWhat to do
RequestLogUnavailable tokenId, reason The service could not record the request, so it did nothing.Send the same request again shortly.

How refusals work everywhere: Errors.