Skip to content

Seals

Concept: Seals & integrity.

Personal seal — /api/v1/seals (authenticated)

Section titled “Personal seal — /api/v1/seals (authenticated)”
Method · RoutePurposeSource
POST /Register a seal. OwnerId is always the authenticated user (client input ignored); OwnerType = User or Organization, with a security Tier.SealEndpoints.cs:28
DELETE /{credentialId}Revoke a seal (by owner + ownerType).:65
POST /checkPre-flight: a personal seal needs only email + first passkey (Owner default policy; KYC gating is org-level).:211

Seal registry — GET /api/org/{slug}/seals

Section titled “Seal registry — GET /api/org/{slug}/seals”

Returns the org’s seals (:90):

  • Master seal — one row if Organization.OrgSealKeyId is set ("{org} Master Seal", scope ALL (ROOT)).
  • Personal seals — each active member’s UserCredential(s) surfaced as personal seals (one row per passkey; the first is the semantic personal seal).

Bind personal → master (sole proprietorship)

Section titled “Bind personal → master (sole proprietorship)”

POST /api/org/{slug}/master-seal/bind-personal (:164) — for an independent sole proprietorship whose Owner had no passkey at org-creation time. After the Owner registers a passkey, this binds their first UserCredential as the org master seal. Owner-only; rejected if a master seal is already set (seals are immutable).

RegisterPersonalSealModal drives the member’s cryptographic personal-seal ritual: platform-authenticator check → KYC pre-flight (/api/v1/seals/check, skipped for device-only enrollment) → api/passkey/add/optionsnavigator.credentials.getapi/passkey/addPOST /api/v1/seals (RegisterSealCommandHandler). The first passkey is the semantic Personal Seal, and registering it also activates a Pending membershipActive (emits MemberActivatedEvent). Hybrid device-trust enrollment tokens ride the same flow. This modal is a required onboarding step and the member entry-gate (see Seals & integrity).

Distinct from the cryptographic seals above — these are the rendered SVG stamps drawn on approval documents. Full model: Seals & integrity → the visual seal designer.

Method · RoutePurposeSource
POST /api/org/{slug}/settings/sealUpload/replace the company seal image; stored on Organization.SealUrl (R2 logos/orgs/{id}/…). Owner/admin. Emits OrganizationSettingsUpdatedEvent (Category Seal).OrgLogoEndpoints.cs
DELETE /api/org/{slug}/settings/sealRemove the company seal.OrgLogoEndpoints.cs
PUT /api/org/{slug}/members/{connectedId}/signatureSet the caller’s own personal signature/seal{kind, spec} where kind = signature / seal / draw / image / none. Self-only; 8 KB cap; JSON-validated. Stored on User.SignatureSpec. Emits org.member.signature_changed (ORG025).OrgEndpoints.cs
POST /api/org/{slug}/members/{connectedId}/signature/imageUpload a raster/SVG personal seal image (R2 logos/users/{uid}/…). Self-only.OrgEndpoints.cs

The designed spec is exposed on /me (UserInfo.SignatureSpec) and rendered by the shared PersonalSignature component wherever a seal appears.