APISDK setup

Users and organizations

Map your application users to Openship and keep each operation inside an authorized organization.

An organization is the resource boundary. A scope selects the organization and carries a verified user identity. Supplying an organization ID does not grant access to it.

Remote scopes

remote-scopes.mts
import type { OpenshipClient } from "openship";

export async function listProjectsFor(client: OpenshipClient, organizationId: string) {
  return client.scope(organizationId).projects.list();
}

The API verifies the bearer credential and checks membership and grants. The client keeps the selected organization fixed across requests. Compatible server support is required.

Native identity adapter

The host supplies identity.resolve(assertion). Return a VerifiedIdentity only after authenticating the assertion; return null for an invalid or revoked session.

The SDK calls this adapter again for each operation. It also rereads persisted memberships and grants. Removing a membership or revoking a host session invalidates an existing scope.

ValueSupplied by
AssertionYour application, such as a session identifier.
Verified user and session IDYour trusted authentication adapter.
Organization IDYour application chooses from organizations the user may access.
Roles and resource grantsOpenship's persisted membership and permission model.

For verified PAT/OAuth identities, the adapter may supply tokenScope and credential restrictions. It must authenticate the credential before doing so. See permissions.

Provision a customer workspace

Enable administration: true for trusted host code. A namespace is a stable external key mapped to an Openship organization:

customer-workspace.mts
import type { OwnedShip } from "openship";

export async function provisionCustomer(
  ship: OwnedShip<string>,
  subject: string,
  email: string,
) {
  if (!ship.operator) throw new Error("Host administration is disabled");
  const person = await ship.operator.ensureIdentity({ issuer: "my-product", subject, email });
  const workspace = await ship.operator.ensureNamespace({
    issuer: "my-product",
    key: subject,
    name: "Customer workspace",
    ownerUserId: person.user.id,
  });
  return { person, organizationId: workspace.organizationId };
}

Both mappings persist. Email equality alone does not link existing accounts; explicit account linking uses userId. Use operator.setMembership() to add or remove members. The final owner cannot be removed.

After your adapter verifies the user's session, call ship.scope({ identity: assertion, organizationId }), then create or deploy projects through that scope. The scope contains no operator methods.

Background actions

Some saved actions continue after the initiating request. They use persisted authority and must still pass current membership and credential checks. An external host session cannot be revalidated after restart unless your integration synchronizes its revocation with persisted authority. See current background limits.

On this page