Organization invitations and applications

Native Management membership remains the authority for organization access. Relationship manages invitations, applications, bonds and delivery receipts. Acceptance grants ordinary member access and preserves existing membership, role and membership data.

On /members/settings/org, Invites & Applications beside New Organization opens received invitations, request updates, the caller's applications and an Apply form. Owners send invitations and review applications under Access in an organization. The tabs are Members | Invites & Apps | Policy. A single Add a principal form sits beneath the tabs, outside their panels, and appears on Members and Invites & Apps. Policy hides it. The form offers Send invitation by default or Direct add using the existing native access API. Direct add grants the chosen access level immediately; invitations grant Member access only after consent. Members shows current access; Invites & Apps shows pending requests for review. Switching tabs preserves the shared form's draft and expanded state. The owner modal uses its top alert for action results and errors, scrolling to the top when it updates. Member refreshes after a change preserve that result. Opening an invitation never accepts it.

Routes

All routes below are authenticated JSON POST requests under /api/v2. The normal authorization and response envelope apply. Nonexempt clients need org.relationships.<action> or a covering parent scope. Scopes do not replace native access checks.

Route suffix after /org/relationships/ Input Authority / effect
invite org, recipient, idempotency_key; optional type (default user) and message Current owner creates an invitation. Type user uses a native User UUID; type app uses a machine application's public Client ID.
apply org, idempotency_key, optional message Authenticated consumer user or machine application requests Member access for itself.
requests org, optional count, offset Current owner lists pending requests and incomplete accepted grants for this organization.
status command_id Recipient or current owner reads request status.
accept command_id, integer version Invitation recipient accepts; current owner approves an application. Applies a verified native grant.
decline command_id, integer version Invitation recipient declines; current owner declines an application.
cancel command_id, integer version Owner cancels an invitation; applicant withdraws its own application.
notifications optional count, offset Reads the authenticated caller's mailbox for this integration.
applications optional count, offset Reads only the authenticated caller's applications and current statuses.
delivered notification_id Acknowledges delivery for the authenticated caller; never grants consent.

Every route accepts an optional workspace_principal_id sentinel. Use the central principal UUID returned by an earlier response to reject actions after the authenticated actor changes. It cannot select another actor. Pagination uses integer count (1–50, default 25), nonnegative integer offset and next_offset (null at the end).

Creation requires a nonnil UUID idempotency_key. Retry identical input with the same key to recover the original command. Changing input needs a new key. Messages are UTF-8 text, limited to 2,000 bytes. Requests expire after seven days.

For example, a current owner can invite a consumer user:

curl --fail-with-body --silent --show-error \
  --request POST 'https://api.user.m7.org/api/v2/org/relationships/invite' \
  --header 'Authorization: Bearer ACCESS_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{"org":"ORGANIZATION_UUID","recipient":"USER_UUID","type":"user","idempotency_key":"FRESH_REQUEST_UUID"}'

Bound tokens require the matching sender proof. Successful operations use status: 1, comment: "OK", and data containing the result. Check the ordinary failure envelope for invalid fields, unavailable identities, missing current owner/recipient authority, actor-sentinel mismatch, expired requests, and stale decision versions. Read status again before retrying a decision with its current version; do not automatically accept a different request or widen the original consent.

Identities and authority

Native account/client IDs, central principal UUIDs and Management principal UUIDs are separate identifiers. The server resolves verified consumer users and machine applications by source kind and tenant, then maps accepted grants to native Management records. Invitation entry follows the native source conventions above; response principal_id uses the central registry. Tenant accounts and organization ownership references are not actors in this workflow. Machine owner proxies cannot inherit the owner's requests or consent.

Only current owners create invitations or review applications. An invitation's issuer must still be an eligible owner when it is accepted. Caller-supplied actors, remote project/space/subspace IDs, role overrides and arbitrary metadata are rejected.

Responses expose a request or an items list. Request fields include command_id, request_id, resource_id (native organization UUID), organization_name, principal_id, principal_name, issuer_name, kind, message, state, version, expires_at, grant_applied and access_active. Status responses also include can_respond. Remote protocol payloads and credentials remain server-side.

Incomplete accepted applications appear in the owner's queue for retry; recipients can retry incomplete invitation acceptance. A completed receipt records the exact native membership UUID. Replaying it cannot recreate removed access. Existing removal and leave operations synchronize remote bonds while preserving native last-owner, metadata and tag cleanup checks.