Can UBO information be submitted separately from the business?

Follow-up probe to the MT failure-webhooks spike (RENTAL-594) · run 2026-07-07 against the shared Modern Treasury sandbox · raw REST, no SDK · scripts 07-ubo-probe.mjs / 08-ubo-attach-variants.mjs, wire captures under snapshots/07-ubo-probe/ and snapshots/08-ubo-attach-variants/ · card commerce#insane-dynamic-shield

Verdict: no. UBOs (beneficial owners / control persons) only take effect when embedded in the business create call. Every post-create path — PATCH with an embedded child, PATCH linking a pre-created individual by id, a standalone associations endpoint, a nested route — is either silently ignored or does not exist. Business + UBOs are one packet at create time.

Why we ran this

David asked (comment on commerce#retire-lawsuit-intact) whether UBO information can be submitted separately from the business — e.g. business first, owners later. The original spike never exercised associations, but its captures hinted "probably yes": MT models UBOs as separate legal entities linked via legal_entity_associations, the create-time completeness checklist has no beneficial-owner rule, and PATCH re-triggers verification. The probe was run to confirm before answering. The hint was wrong.

What was attempted

Every plausible API surface for attaching a UBO after the business exists:

#AttemptResultEvidence
1 POST /api/legal_entities with embedded legal_entity_associations (control) 201 — works 08/05-embedded-at-create.json
2 PATCH /api/legal_entities/:id, association with embedded child individual 200, silently dropped 07/03-patch-attach-ubo.json
3 PATCH /api/legal_entities/:id, association by child_legal_entity_id to a pre-created individual 200, silently dropped 08/03-patch-link-by-id.json
4 POST /api/legal_entity_associations (standalone resource) 404 — no such path 07/04-standalone-association.json
5 POST /api/legal_entities/:id/legal_entity_associations (nested route) 404 — no such path 08/04-nested-route.json
6 POST /api/legal_entities creating a standalone individual (a would-be UBO on its own) 201 — but unlinkable 08/01-individual-create.json

Evidence paths are relative to snapshots/; 07/ = 07-ubo-probe, 08/ = 08-ubo-attach-variants. Each file holds the exact request body sent and the raw response.

The two decisive wire captures

PATCH is a silent no-op, not a rejection

Business 912a0ee8 was created with no associations and auto-activated. A PATCH carrying a complete beneficial owner (name, DOB, address, SSN, 40% ownership) returned 200 OK — and the response body still shows "legal_entity_associations": []. No updated event was ever emitted (the events log stayed [activated, created] through 30s of polling), so MT didn't just decline the field — it never registered a change at all. The same happened when linking a pre-created individual by id (attempt 3).

PATCH /api/legal_entities/912a0ee8-5d48-46ba-b2ba-39ece2354082
{ "legal_entity_associations": [ { "relationship_types": ["beneficial_owner"],
    "ownership_percentage": 40, "child_legal_entity": { ...complete individual... } } ] }

→ HTTP 200
   "legal_entity_associations": []        ← field silently dropped
   events after 30s: [activated, created] ← no "updated" ever fired

Embedded at create is the one path that works

The identical association payload, embedded in a fresh business create, persists fully: the association gets an id, the child becomes a real legal entity with its own id and pending status, and ownership_percentage round-trips.

POST /api/legal_entities   (business + embedded legal_entity_associations)

→ HTTP 201, parent 89fb5992-5647-4424-acdd-57469b9d3ae4 (status: pending)
   association 30224e62-c5c1-47eb-9a34-5d05f11066b0
     relationship_types: ["beneficial_owner"], ownership_percentage: 40
     child_legal_entity: 7fe6fe37-f26d-4cbc-9b0e-b78cb80bde24
       (type: individual, status: pending)

Method notes

What this means for us

Caveats / for MT support: a 200 that silently drops a documented field smells like a versioned or unreleased API surface — worth asking whether a newer API version supports association updates post-create. And Persona doesn't run in sandbox, so whether production verification holds or fails a business with missing UBOs is invisible here; bundle with the existing profile-configurability question.

File inventory

FileContents
07-ubo-probe.mjsCreate association-less business → PATCH embedded UBO → standalone endpoint → event polling
08-ubo-attach-variants.mjsStandalone individual create → link-by-id PATCH → nested route → embedded-at-create control
snapshots/07-ubo-probe/7 request/response captures incl. the silent-drop PATCH and 404
snapshots/08-ubo-attach-variants/6 captures incl. the working embedded-at-create response
NOTES.mdParent spike writeup; UBO findings appended as a follow-up section