Skip to main content

Customer tenant API

The endpoints in Partner API reference manage your fleet: provisioning customers, minting leases, vouching workers, setting entitlements. This page covers the other half - driving what is inside a customer organization, so the people using your product never sign in to Yekar.AI.

Everything lives under /api/partner/v1/organizations/{orgId} and mirrors the product surface: agents and flows, connections and credentials, domains and members, triggers and schedules, sessions and runs, approvals, knowledge, apps, webhooks, events, evals, and organization settings.

How a request is authorized

Three things identify every call, and each is checked against the one before it:

POST /api/partner/v1/organizations/{orgId}/automations/{id}/publish
Authorization: Bearer ykp_00000000-0000-4000-8000-000000000001.AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
X-Yekar-Subject: your-user-id-42
PartWhat it proves
Authorization: Bearer ykp_…Which platform is calling.
{orgId} in the pathWhich customer - it must be an active follower of that platform.
X-Yekar-SubjectWhich provisioned person is acting.

The credential above is an obviously fake, structurally valid example.

Because the organization is addressed in the path rather than baked into a token, one long-lived key reaches your whole fleet. A nightly sweep across 500 customers is 500 calls on one key, not 500 leases.

Your key is an attestation, not an authority

This is the part worth internalizing, because it decides how you design your integration.

A ykp_ key proves who is asking. It confers no permission of its own. What a call may do is decided entirely by the org and domain roles of the person named in X-Yekar-Subject - evaluated by the same permission system that governs someone clicking in the Yekar.AI UI.

So the model is: when your platform needs to do something that requires a permission, provision a user who holds that permission, and act as them.

You provision that person with POST /organizations/{orgId}/workers:

{
"partnerSubject": "your-user-id-42",
"email": "[email protected]",
"orgRole": "admin",
"domains": [{ "domainId": "…", "domainRole": "editor" }]
}

domains is declarative when you send it: after the call that person holds exactly the roles listed, and any role you omit is removed. Omit the field entirely and their existing roles are left alone. That is what lets you narrow access as well as widen it.

orgRole is admin or member. Organization administration - settings, AI provider keys and inviting Members - requires admin. Creating domains may also be allowed for Members by organization policy. The organization owner's role cannot be changed by a vouch; that request is refused rather than silently ignored.

Which role for which job

Roles are the same everywhere, so you can reason about them once rather than per customer.

To do thisThe subject needs
Read domain agents, flows, ordinary sessions and knowledgeAny role in that domain (viewer or above)
Start a published agent/flow or participate in their own sessionAny role in that domain
Participate in a teammate's domain session; manage triggers and webhooksoperator, editor or owner in that domain
Decide a domain-routed approvalThe domain's approval policy and any Flow gate role floor; defaults to operator or above
Author agents, flows and knowledge; start evaluations or draft testseditor or owner in that domain
Decide OCR spending for scanned documentsOrganization admin
Manage domain shared connections and credentialsDomain owner
Manage domain members and assign any domain roleDomain owner, or organization admin across its domains
Organization settings, AI keys, invitations for MembersOrganization admin
Create domainsOrganization admin, or member when organization policy allows it

An organization Admin cannot read someone else's personal chat or bypass domain permissions. Linked Builder conversations require current edit permission on their subject agent. See Roles and permissions for the complete matrices, ownership rules and approval exceptions.

A subject provisioned in no domain can authenticate and will be refused everything domain-scoped - which is a useful default for a service identity that should only touch one area.

What this is not

Roles bound the blast radius of a call and make the audit trail name a real person. They are not a boundary against you: your platform may vouch anyone into any role in its own followers. What bounds you is the organization check - a key reaches only organizations its own platform provisioned.

Refusals

Every break in the chain answers the same 404: an unknown key, another platform's organization, a missing or unknown X-Yekar-Subject, a revoked mapping, a deactivated membership, a detached follower. They are deliberately indistinguishable, so a key cannot be used to discover which organizations exist or which of another platform's people are active.

Once the chain resolves, refusals are the ordinary product ones - 403 when the acting person lacks the permission, 404 for a record they cannot see.

Starting work

Three endpoints start an execution and accept an end user's own credential for the integrations it runs on:

  • POST /organizations/{orgId}/sessions - open a conversation
  • POST /organizations/{orgId}/sessions/{sessionId}/messages - continue one
  • POST /organizations/{orgId}/automations/{id}/sessions - fire one run

They take callerCredentials exactly as the caller credentials contract describes, and reconcile it against what the target binds at caller identity. A credential for an integration the target does not bind at caller identity is refused by name rather than accepted and ignored.

A credential is scoped to the single execution the request seeds and is never stored as a reusable connection. On POST /sessions, it must accompany a message: a session opened with nothing said has no execution to authorize, and sending one anyway is refused with CALLER_TOKENS_NO_ANCHOR.

POST /automations/{id}/test-runs and POST /automations/{id}/bulk-retry refuse callerCredentials by name. Both run on stored identity by construction, so a supplied token could only ever be silently ignored.

Not available through this API

WhyWhat to do instead
OAuth connectionsConnecting Google, Microsoft, Slack and the rest requires the end user's browser to reach the vendor's consent screen and return to a Yekar.AI URL. No server-to-server call can stand in for a screen a person must see and approve.Key-based integrations are fully API-driven. For OAuth ones, register your own client under OAuth apps so the consent screen carries your application name, then have the user complete the connect flow.

Everything else in the product is reachable, including document upload (single and streamed multi-file batches with per-document outcomes), OCR preflight and decisions, web crawl into knowledge, and session file transfer. Uploaded documents follow the same journey as in the product: first successful extraction publishes automatically as the acting subject, and a scanned document waits on an OCR decision - an org-admin subject's call to …/ocr-decision - unless the organization's standing OCR authorization is set.

Worked example: onboarding a customer end to end

1. POST /organizations → customer org
2. POST /organizations/{orgId}/workers → an admin subject
3. POST /organizations/{orgId}/domains → shape the org
4. POST /organizations/{orgId}/users → invite their people
(whitelabel: returns an activation link, sends no Yekar.AI-branded mail)
5. POST /organizations/{orgId}/domains/{id}/connections → their credentials
6. POST /organizations/{orgId}/domains/{id}/automations → author an agent
7. PATCH .../automations/{id}/setup → POST .../setup/publish
8. POST /organizations/{orgId}/automations/{id}/webhooks → completion callbacks
9. POST /organizations/{orgId}/sessions → talk to it

Steps 3–7 need a subject with the roles that step requires. Steps 5 and 6 are the ones people miss: connections need owner on the domain, authoring needs editor.