# API-only personal Data Vault integration

**Verified on mainnet, 20 October 2026:** the public APIs created five new synthetic owners, each with a separate personal Vault, normal MFA/protection and explicit app/file consent. All five original files were uploaded, retrieved and decrypted byte-for-byte, revoked, explicitly reapproved and retrieved again. Their new native proofs were independently verified on `hybrid-mainnet` at heights 122–126. No browser or MPC wallet was used. This client-neutral guide applies to any registered application using the documented flow. This validates the recorded platform flow; Every production client must register its own application and exact hostnames before use.

[Sanitized acceptance receipt](https://hybrid-id.com/integrations/data-vault-mainnet-acceptance-20261020.json) · [Standalone API example](https://hybrid-id.com/integrations/data-vault-api-example-20261020.tar.gz) · [Retrieved dummy files and checksums](https://hybrid-id.com/integrations/data-vault-example-files-20261020.zip)

The acceptance uses five new synthetic accounts and dummy files. No existing owner, customer Vault, wallet, MPC credential or live mailbox is reused. Each synthetic account gets its own native identity, MFA and protected personal Vault. Test email addresses remain unverified unless normal email verification actually occurs.

The historical acceptance receipts and dummy-file downloads are preserved byte-for-byte under neutral download aliases. Their original fixture labels identify the recorded test, not a client restriction. The new example bundle uses generic application names and a new private runtime namespace.

## 1. Separate the two API clients

| Runs where | Credential and key material | What it does |
| --- | --- | --- |
| Owner's device or trusted owner CLI | Native Hybrid-ID API session, authenticator and master password | Creates the account, enables MFA/protection, previews and explicitly authorizes a connection, and approves/revokes a selected file. Local cryptography never sends the master password, root or private key to either service. |
| Application backend | Its confidential application credential, a token scoped to that owner/application's file operations, and the application's own recipient private key | Uploads/downloads ciphertext; asks for file decryption; decrypts only a file whose wrapped key the owner separately approved. |

The native owner session never belongs on the application's backend. Native and application tokens are not interchangeable. The application receives no wallet, spending, general Identity-management or other-owner access. A file-read connection alone does not authorize plaintext processing.

There is no browser, redirect interaction, cookie automation, HTML form scraping or web-interface step in this guide. `platform: "web"` below selects Identity's existing `hcb_` credential class for the owner-device API; it does not require a browser.

## 2. Release and registration prerequisites

The platform operator first verifies and deploys the approved Core/provider/gateway sources together, enables only their reviewed Vault gates, and verifies the public/private ingress. The additional owner-device route has its own `partnerVault.ownerApiEnabled` switch, default off. Existing invitation-only V2 registration remains unchanged; the new Hybrid-ID owner API delegates to the already governed Hybrid-ID registration service.

Public endpoints after activation:

- Owner-device commands: `POST https://auth.hybrid-id.com/vault/owner`.
- Existing native authentication/security: `https://api.hybrid-chain.com/api/v2`.
- Application file transport: `POST https://api.hybrid-chain.com/api/v2/data-vault/files`.

For a production application registration, supply the exact application name and HTTPS application origin. The confidential application's current registration contract also requires an exact HTTPS sign-in callback, even though this headless flow does not use it. An optional post-logout callback must share that origin. Register staging separately. Each client supplies its actual hostnames; they must not be guessed.

The five-account driver deliberately uses `https://vault-acceptance.example.invalid/callback` for an isolated, unused callback. This is a synthetic test-app registration, **not** a production application registration or proof that any production application endpoint is deployed.

## 3. Install the reviewed SDK and examples

Use Node 24.18.0 for the recorded acceptance environment. The small standalone bundle contains the same SDKs and two example drivers, a pinned npm lockfile and source checksums. It contains no credentials or runtime state and requires no access to the website repository.

```sh
curl --fail --location --output data-vault-api-example-20261020.tar.gz \
  https://hybrid-id.com/integrations/data-vault-api-example-20261020.tar.gz
printf '%s  %s\n' \
  f83c339e718d10a20c3f4d11baf65fe0f53d99c07a5cc3e693865a29f75d9164 \
  data-vault-api-example-20261020.tar.gz | sha256sum --check -
tar -xzf data-vault-api-example-20261020.tar.gz
cd data-vault-api-example
sha256sum --check SHA256SUMS
npm ci --ignore-scripts --no-audit --no-fund
```

The SDK and driver paths below are relative to this extracted directory. To rebuild the source-only bundle from the platform repository, run `node scripts/build-partner-vault-sdk.mjs` then `python3 scripts/package-data-vault-api-example.py`. The build script copies an explicit allowlist; it never packages private acceptance runtime directories.

Runtime packages for an independent Node integration are `openid-client@6.8.8` if using OIDC, `@hpke/core@1.9.0`, `@hpke/dhkem-x25519@1.8.0` and `libsodium-wrappers-sumo@0.8.4`. The headless owner SDK does not use a browser/OIDC redirect. Keep the SDK's relative `vault-crypto/` modules together. `source-sha256.json` records their source hashes.

SDK entry points:

- `public/integrations/hybrid-id-vault-owner-node.mjs`: owner-device API only.
- `public/integrations/hybrid-id-vault-node.mjs`: backend file transport.
- `public/integrations/hybrid-id-vault-recipient-node.mjs`: backend recipient key generation and selected-file decryption.

## 4. Create a user through the owner API

The owner submits the actual current terms acceptance. Account creation is not email verification, identity verification, app consent or encryption readiness.

```json
{
  "operation": "register",
  "email": "<owner email>",
  "password": "<owner-selected password>",
  "first_name": "<optional>",
  "last_name": "<optional>",
  "terms_version": "2026-10-05",
  "terms_accepted": true
}
```

Send that JSON directly from the owner device to the owner endpoint using `Content-Type: application/json`. Registration has no bearer header. Unknown owner/role/verification/module fields are rejected. The actual Identity signup policy still controls availability, password checks and email delivery. Do not set `email_verified` yourself. Use the current published terms version if it changes.

The SDK equivalent, executed on the owner's device:

```js
import {HybridVaultOwnerClient} from './public/integrations/hybrid-id-vault-owner-node.mjs';
const owner = new HybridVaultOwnerClient();
await owner.register({
  email, password, firstName, lastName,
  termsVersion: '2026-10-05', termsAccepted: true
});
```

Do not place owner passwords in command-line arguments, shell history, URLs, source control or application logs. Supply them through a protected local input mechanism. The acceptance driver generates and stores only its own synthetic credentials in owner-only files.

## 5. Authenticate and enroll an authenticator

`POST /api/v2/auth/sessions` from the owner device:

```json
{
  "email": "<same owner email>",
  "password": "<owner password>",
  "platform": "web",
  "device_id": "<stable device identifier>",
  "device_name": "Data Vault owner API"
}
```

The response contains the native `hcb_` access token and its lifetime; retain it only on the owner device. After MFA enrollment, subsequent sign-ins also supply `two_factor_code` (or the supported recovery mechanism).

Before first authenticator enrollment, exchange the native source session for an owner-device Hybrid-ID management session. Generic API sign-in intentionally cannot manage authenticators. This uses the existing Identity SSO contract with the server-fixed canonical application; it does not require a browser or change the identity.

```json
{"operation":"authenticator-session","device_id":"<same stable device identifier>"}
```

Send this to the owner endpoint with the original native source bearer. The response contains an `hcb_` token bound by Identity to `hybrid-id-web`, plus `purpose: "FIRST_AUTHENTICATOR_ENROLLMENT"`. It stays on the owner device and is never sent to the application. The operation refuses an already-enabled authenticator or a caller-selected application.

```js
await owner.prepareAuthenticatorSession({deviceId});
const enrollment = await owner.enrollAuthenticator({label: "My Data Vault authenticator"});
await owner.confirmAuthenticator(enrollment.enrollment_id, currentEnrollmentCode);
```

Using `Authorization: Bearer <canonical management session token>` for these two enrollment calls only:

```text
POST /api/v2/me/authenticator-enrollments
{"issuer":"Hybrid-ID","label":"My Data Vault authenticator"}

POST /api/v2/me/authenticator-enrollments/<enrollment_id>/confirmations
{"code":"<current code from that enrollment>"}
```

Keep the original native source bearer for the owner API, protection and purpose-bound step-up calls. Step-up authorizations are bound to that source session; do not substitute the management session when approving application or file access.

The enrollment secret/URI and recovery codes belong in the owner's authenticator/recovery storage, never the application's backend. The SDK provides `signIn`, `enrollAuthenticator` and `confirmAuthenticator` for these same APIs. The dummy-account driver can generate fixture TOTP codes because it operates those test owners' authenticators; a real application must not silently enroll or operate an authenticator on behalf of a person.

## 6. Establish owner protection without MPC

Call the owner API using `Authorization: Bearer <native owner token>`:

```json
{"operation":"protection-status"}
```

If not configured, the owner SDK performs the existing protection protocol:

```js
await owner.configureProtection(masterPassword, currentAuthenticatorCode);
```

Its network calls are:

```text
POST /vault/owner
{"operation":"protection","command":{"operation":"context"}}

POST /vault/owner
{"operation":"protection","command":{"operation":"step-up","code":"<current code>"}}

POST /vault/owner
{"operation":"protection","command":{"operation":"begin","operation_id":"<stable 32-hex id>","revision":0,"package":{...encrypted package...},"step_up_token":"<one-use setup token>"}}

POST /vault/owner
{"operation":"protection","command":{"operation":"commit","challenge_id":"<returned id>","proofs":{"password":"<locally derived challenge proof>"}}}
```

The SDK creates the account package locally, wraps the root/private key with the owner master password, and proves possession using the returned HPKE challenge. Only the encrypted package and one-use proof leave the device. It uses the existing Data Vault branch of account protection; it does not call any wallet or MPC endpoint. If protection already exists, it does not replace it.

A lost commit response must be resolved by re-reading protection status. Preserve the original pending operation/package for uncertain setup retries; never reset an existing identity or key to make a test pass.

## 7. Register your application and recipient public key

Generate the application's own X25519 recipient key on its backend:

```js
import {createFileRecipient} from './public/integrations/hybrid-id-vault-recipient-node.mjs';
const {recipient, privateKey} = await createFileRecipient();
// Store privateKey in protected backend key storage. Register recipient only.
```

A current application owner can create the confidential application using the owner API and fresh MFA. The request is bound to a stable `request_id`, so exact retries cannot create multiple applications. Public-key registration does not itself grant access to any user file.

```js
const app = await owner.createApplication({
  name: '<your application name>',
  redirect_uris: [exactRegisteredCallback],
  post_logout_redirect_uris: [],
  vault_enabled: true,
  vault_recipient: recipient
}, currentAuthenticatorCode, {requestId: persistedApplicationRequestId});
// Keep app.client_secret server-side. Never send it to customer devices.
```

Developer eligibility and app limits remain enforced. A separate app key is not an owner key, and possession of it does not provide user consent. A rotated recipient key requires a new selected-file approval.

## 8. Preview and explicitly authorize this user's file connection

The owner-device API previews the registered application and requested scopes:

```json
{
  "operation":"connection-preview",
  "client_id":"<registered app id>",
  "scopes":["vault:files:upload","vault:files:read"]
}
```

Show the returned name, origin, scope and recipient information to the owner. On explicit agreement, submit:

```json
{
  "operation":"connection-authorize",
  "client_id":"<same app id>",
  "scopes":["vault:files:upload","vault:files:read"],
  "request_id":"<persisted 32-hex id>",
  "preview_digest":"<digest returned with these exact terms>",
  "step_up_token":"<fresh ACCOUNT_SECURITY_CHANGE token>",
  "acknowledgement":"AUTHORIZE_THIS_APPLICATION_FILE_ACCESS"
}
```

Create that step-up token through the existing API:

```text
POST /api/v2/security/step-up
Authorization: Bearer <native owner token>
{"purpose":"ACCOUNT_SECURITY_CHANGE","authenticator_code":"<current code>"}
```

The owner SDK wraps those calls:

```js
const preview = await owner.connectionPreview(app.client_id);
// Obtain the owner's agreement to preview.terms before this next call.
const connection = await owner.authorizeConnection(preview, {
  requestId: persistedConnectionRequestId,
  code: currentAuthenticatorCode,
  acknowledgement: 'AUTHORIZE_THIS_APPLICATION_FILE_ACCESS'
});
```

Only the app-scoped `connection.access_token` / `refresh_token`, its pairwise `subject` and expiry are handed to the intended application backend. This app-scoped token is separate from the native owner session. Backend calls also require the application's confidential app authentication. Current consent, native session, app status, protection context and expiration are checked on each request. The reported expiry is an upper bound; revocation or the native source session ending can stop access earlier. The backend must verify the authoritative pairwise `subject` from the file `context` response against its stored application account; do not trust a caller-supplied subject or link accounts by email.

The SDK can renew an expired short-lived token using only the application secret and the separate scoped renewal capability. `refresh-connection` accepts `{operation, refresh_token, request_id}` and has no native owner token in its body. It cannot extend the original eight-hour renewal window, restore withdrawn consent or outlive the native owner session. The SDK retries a 401 once with the exact file request after renewal; 403 is not silently retried. Persist updated app tokens through the `onTokens` callback in protected backend storage.

## 9. Allocate, encrypt and upload dummy data

Backend initialization and a stable allocation:

```js
import {HybridVaultClient} from './public/integrations/hybrid-id-vault-node.mjs';
import {encryptFile} from './public/integrations/vault-crypto/crypto.mjs';
const files = new HybridVaultClient({
  clientId: app.client_id, clientSecret: app.client_secret,
  accessToken: connection.access_token, refreshToken: connection.refresh_token,
  expectedSubject: storedApplicationAccountSubject
});
const context = await files.request('context');
// Bind context.subject to the application's existing account record.
const plan = await files.prepare(persistedUploadRequestId);
const encrypted = await encryptFile(dummyFile, plan.descriptor, {
  schema: 'HC_DATA_FILE_V1', owner: plan.descriptor.context,
  file_id: plan.object_id, version: 1
});
// Persist plan, manifest, envelope and exact encrypted bytes before sending.
await files.uploadPrepared(plan, encrypted);
```

`encryptFile` needs the public descriptor only. Filenames/content are encrypted before storage. The real data source decides where encryption happens; backend access to pre-upload plaintext is a separate product decision, not a privilege granted by this Vault API.

The transport SDK issues JSON POSTs to the file endpoint with HTTP Basic app authentication and the app-scoped user token in the body:

```text
{"operation":"prepare-upload","access_token":"<scoped token>","request_id":"<stable id>"}
{"operation":"register","access_token":"<scoped token>","object_id":"<allocated id>","registration":{"manifest":{...},"envelope":{...}}}
{"operation":"put-chunk","access_token":"<scoped token>","object_id":"<same id>","index":0,"ciphertext":"<base64url encrypted chunk>"}
{"operation":"commit","access_token":"<scoped token>","object_id":"<same id>"}
```

Retry the exact registration/chunks/commit after an uncertain response. Do not re-encrypt under the same object ID. Do not supply an owner, tenant, workspace or Vault selector. Current limits are in the machine contract; SDK transport uses one-MiB chunks. File placement is Data Vault-owned; the integration does not choose raw IPFS paths or bypass the primary mounted storage volume.

## 10. Request owner-approved backend decryption

A complete file can request a separate per-file approval:

```js
const request = await files.requestDecryption(plan.object_id, {
  requestId: persistedDecryptionRequestId,
  purpose: 'Read this selected Data Vault file for the agreed task.',
  expiresAt: Math.floor(Date.now()/1000) + 86400
});
```

The corresponding API payload is:

```json
{
  "operation":"request-decryption",
  "access_token":"<scoped token>",
  "object_id":"<allocated file id>",
  "request_id":"<stable retry id>",
  "purpose":"Read this selected Data Vault file for the agreed task.",
  "expires_at":0
}
```

Replace `expires_at: 0` with the actual future Unix time; it is deliberately invalid as a copy-paste default. The server accepts an expiry within the documented bound. The status starts `pending`, not approved. Pending requests also report `consent_changed`, `recipient_changed`, `application_disabled` or `expired` when those terms stop being current. After explicit app reauthorization, create a new request ID for a stale review; retrying its original ID never changes the old terms or restores access.

On the owner's device, using the owner API rather than any web interface:

```js
const prepared = await owner.prepareFileApproval(request.request_id, masterPassword);
// Show prepared.metadata.name and size plus prepared.request.binding's
// application, purpose, recipient key and expiry. Get explicit agreement.
await owner.approvePreparedFile(prepared, {
  code: currentAuthenticatorCode,
  acknowledgement: 'ALLOW_SELECTED_FILE_DECRYPTION'
});
```

This uses `file-review` commands `read` then `approve`. The approval contains the exact request ID, revision, terms digest, one-use step-up token and encrypted recipient envelope. The master password/root/private key is absent. The owner API does not accept a partner secret as owner authentication; the file API cannot submit an approval.

## 11. Retrieve and decrypt on the application's backend

```js
import {decryptApprovedFile} from './public/integrations/hybrid-id-vault-recipient-node.mjs';
const encryptedFile = await files.retrieve(plan.object_id);
const grant = await files.decryptionStatus(plan.object_id, request.request_id);
const restored = await decryptApprovedFile({
  ciphertext: encryptedFile.ciphertext,
  manifest: encryptedFile.manifest,
  grant, privateKey: applicationRecipientPrivateKey,
  expected: {
    clientId: app.client_id, subject: connection.subject,
    objectId: plan.object_id, recipient: registeredApplicationRecipient
  }
});
// restored.plaintext is a Blob; restored.metadata contains the verified name/size.
```

Verify the retrieved bytes against the dummy input's SHA-256. The parser also checks authenticated framing/final tag, encrypted byte digest, binding and metadata. A different owner/app/file/recipient key is rejected.

The actual download operations are `read`, then `read-chunk` for each index. `list` shows only files created through this owner/app connection; it cannot adopt arbitrary existing Vault objects. `decryption-status` releases a wrapped selected-file key only while approval is current.

## 12. Run the same procedure for five synthetic accounts

These commands operate only the driver's generated synthetic accounts. They automate those test owners' explicit consent for acceptance purposes; they are not permission to approve real customers' files automatically.

```sh
umask 077
mkdir -p "$PWD/.private-vault-acceptance"
chmod 700 "$PWD/.private-vault-acceptance"
# Prefer an absolute runtime directory outside the checkout in a real run.
export VAULT_ACCEPTANCE_RUNTIME="$PWD/.private-vault-acceptance"

node examples/data-vault/bootstrap-five.mjs \
  "$VAULT_ACCEPTANCE_RUNTIME" create --synthetic-accounts-only

node examples/data-vault/five-account-acceptance.mjs \
  "$VAULT_ACCEPTANCE_RUNTIME/application-backend/acceptance-config.json" upload

node examples/data-vault/bootstrap-five.mjs \
  "$VAULT_ACCEPTANCE_RUNTIME" approve-files --synthetic-accounts-only

node examples/data-vault/five-account-acceptance.mjs \
  "$VAULT_ACCEPTANCE_RUNTIME/application-backend/acceptance-config.json" retrieve
```

On retry, the driver reuses a still-valid source session, so an interrupted first enrollment does not silently replace its session binding. An expired or revoked source requires normal password/MFA authentication and a new explicit app authorization; current policy is still checked. It retains the same account, Vault and uploaded files. An unconfirmed enrollment tied to an expired session is restarted through the normal enrollment API, without replacing an already-enabled authenticator.

The driver generates five distinct `example.invalid` addresses and strong fixture passwords, enrolls/retains their authenticators, configures owner protection, creates an isolated application plus a separate peer app for the cross-app denial check, and authorizes each owner's file connection. It never changes email-verification state. It stops if actual policy prevents any step. Do not use the closed legacy `/api/v2/registrations` route as a workaround or create profiles by SQL.

The upload phase uses five distinct dummy files, including multi-chunk files, and repeats the full exact encrypted upload to test idempotence. The retrieval phase saves dummy plaintext as `application-backend/files/retrieved-owner-01.txt` through `05.txt`, reports their SHA-256 values, and collects each new proof. It also checks every owner against another owner's file and rejects caller-selected Vault IDs. A second confidential app, approved by the same first owner, must receive HTTP 404 for the primary app's file/proof and an empty app-scoped inventory.

| Runtime directory | Contains | May the application receive it? |
| --- | --- | --- |
| `owner-device/` | Synthetic passwords, native sessions, MFA/recovery data, master passwords | No; this represents owner custody. |
| `application-backend/` | App secret, application recipient key and app-scoped owner tokens | Only this side is the backend integration. Protect it as server credentials. |

Both directories are colocated on the test machine only to automate synthetic acceptance. Real deployments separate them. Do not commit, publish, attach or paste their contents into chat.

Short-lived scoped tokens renew in the background within the original approved native-session window. Re-running `create` reuses an existing approved connection and renews its short token instead of replaying an expired issuance receipt. A revoked connection still stops with 403; the driver does not silently restore consent. If that session or renewal window expires, use a fresh explicit owner authorization request. Preserve the existing upload request IDs and encrypted bytes. Do not replace an owner, Vault or file just to get a new token.

## 13. Verify newly generated mainnet evidence independently

`files.proof(objectId)` resolves this exact new file's event. A pending anchor is an expected intermediate state, not a finalized proof. A previously existing platform proof cannot pass this acceptance.

For each new event, record and independently verify:

1. Immutable file/event correspondence and commitment-only public payload.
2. Merkle inclusion against the reported batch root.
3. Actual native validator certificate and its trusted validator-set binding.
4. Network `hybrid-mainnet`, confirmed native height and finality.
5. No wallet creation, MPC enrollment or financial-signing request occurred.

The acceptance runner saves proof packets and labels certification only as reported status. It deliberately does **not** equate that response flag with independent verification; `independent_mainnet_acceptance_complete` remains false until the separate verifier evidence and final acceptance receipt are reviewed. The platform's native anchor verifier must be used, rather than treating HTTP 200 or an old proof as success.

## 14. Revoke and test the access boundary

```sh
node examples/data-vault/bootstrap-five.mjs \
  "$VAULT_ACCEPTANCE_RUNTIME" revoke-files --synthetic-accounts-only

node examples/data-vault/five-account-acceptance.mjs \
  "$VAULT_ACCEPTANCE_RUNTIME/application-backend/acceptance-config.json" revocation-check
```

For all five files this requires `revoked`, no returned recipient envelope, and HTTP 403 on `read`, `read-chunk` and `proof`. A fresh request alone cannot clear a revoked guard; it needs another explicit owner approval. Expiry, recipient rotation and a changed consent revision also stop future access. Information already decrypted or copied by the application cannot be recalled cryptographically.

After the negative test, restore the dummy samples through a **new explicit file approval** so the final samples remain retrievable within their approved session/window:

```sh
node examples/data-vault/five-account-acceptance.mjs \
  "$VAULT_ACCEPTANCE_RUNTIME/application-backend/acceptance-config.json" request-decryption
node examples/data-vault/bootstrap-five.mjs \
  "$VAULT_ACCEPTANCE_RUNTIME" approve-files --synthetic-accounts-only
node examples/data-vault/five-account-acceptance.mjs \
  "$VAULT_ACCEPTANCE_RUNTIME/application-backend/acceptance-config.json" retrieve
```

This retains all five original file IDs and encrypted bytes. The backend request alone leaves the revoked guard in force until the owner approves the new exact request.

The owner can separately revoke the whole app file connection through `owner.revokeConnection(clientId, currentAuthenticatorCode)`. A file approval does not replace app consent, and app consent does not replace a file approval.

A revoked or expired native source session stops file access and scoped renewal with HTTP 403. The application must request fresh owner sign-in/authorization; the backend cannot revive it by renewing an app token. A genuine Identity service/HMAC/replay outage remains HTTP 503 and must not be treated as evidence that the owner signed out.

An owner can revoke their own source through the existing API, using that source bearer:

```text
POST /api/v2/auth/sessions/<current_session_id>/revocations
{"session_id":"<same current_session_id>"}
```

Revoking another session requires the existing separately bound step-up; this example operates only the caller's own session. The same account and Vault survive revocation. Restore access through normal password/MFA sign-in and a new explicit app authorization, then request and approve the exact files again if their consent binding changed.

## 15. Recorded acceptance and remaining production setup

Publish a sanitized receipt with the reviewed source/deployment revisions, exact API commands and response states, five distinct personal Vaults, dummy input/retrieval hashes, duplicate/cross-owner denials, file/app/session revocation results, and a genuine newly verified mainnet proof for each acceptance object. Preserve immutable evidence; retire the synthetic application's credentials and sessions through normal owner APIs after the retention window.

Never include passwords, native/app tokens, recipient private keys, MFA secrets, recovery codes, master passwords or encrypted owner packages in that handoff.

The recorded run passed these checks:

| Check | Observed result |
| --- | --- |
| New API-only owners and separate personal Vaults | Five; email deliberately remains unverified |
| Dummy plaintext sizes | 97; 1,024; 1,048,640; 2,097,161; 8,192 bytes |
| Exact encrypted registration/chunks/commit retried | Original five objects retained, one completion event per object |
| Backend decryption | All five SHA-256 values and original bytes matched |
| Cross-owner read | HTTP 404 |
| Same-owner, different-app read and proof | HTTP 404, empty app inventory |
| Caller-selected Vault | HTTP 400 |
| File revocation | All five deny read, chunks and private proof with HTTP 403; no wrapped key |
| New requests after revocation | Stay pending; all five still deny retrieval until explicitly approved |
| App and native-source revocation | Context and renewal denied with HTTP 403; new explicit authorization restores the same owner/Vault |
| Expired short access tokens | 23 successful scoped renewals observed within original authorization windows |
| Final restoration | Same five original file IDs and encrypted bytes; byte-exact retrieval passed again |
| Independent proof verification | New mainnet heights 122–126; native signatures/quorum, Merkle inclusion and continuity to trusted checkpoint 121; tampered signature rejected |
| Browser or wallet/MPC operations | None |

The [receipt](https://hybrid-id.com/integrations/data-vault-mainnet-acceptance-20261020.json) records each original object/event, checksum, certificate, review source and remaining limitations. The [public certificate chain](https://hybrid-id.com/integrations/data-vault-native-certificate-chain-20261020.json) and [independent verification report](https://hybrid-id.com/integrations/data-vault-independent-proof-20261020.json) support the evidence. Example public proof queries for the first new file:

```sh
curl --fail https://api.hybrid-chain.com/api/v2/explorer/data-vault/proof/76ba66034b0f43ff9dbbfd2d3ca9e26b
curl --fail https://api.hybrid-chain.com/api/v2/explorer/data-vault/anchors/da51ee9eee03765ce1ee50001ef9b127607d459b1c3fa93520349d5934f04905
```


### View the upload evidence in Explorer

Open [Mainnet Data Vault evidence](https://hybrid-explorer.com/networks/hybrid-mainnet/explorer/data-vault) for public storage events and native anchor certificates. Mainnet links pin the network even when the browser previously selected TestNet. For example, inspect the [first acceptance upload](https://hybrid-explorer.com/networks/hybrid-mainnet/explorer/data-vault/evidence/76ba66034b0f43ff9dbbfd2d3ca9e26b) and follow **Inspect validator certificate**.

The directory shows protected byte counts, storage readiness, timestamps and commitments. Its summary covers loaded, network-scoped records, not all stored data. Proof pages attribute verification to Core; Explorer does not independently replay signatures. Filenames, user identities, private Vault identifiers and contents remain withheld. Data Vault mainnet availability does not activate MPC wallets, trading or unrelated Mainnet views.

These public endpoints return commitment evidence, not file contents or access credentials. This acceptance independently used the established native verifier, pinned validator set `ab26c580159a240fbd94e8041a9e3bb04ec1a3e0406b49299122923e9abf19ff` and checkpoint `22aef5c33d800e9c8b60ac9e52ad4768c3e60b28a4287c6bad5de6e9c262f079`. A verifier must not trust an arbitrary replacement validator list just because an HTTP response says “certified”.

The downloadable ZIP contains only the five deliberately synthetic, decrypted text files, a README and SHA256SUMS. Their protected originals remain in the five personal Vaults. No tokens are published: repeat API retrieval using a current app connection plus each exact owner approval. The original demonstration's short token and bounded renewal windows naturally expire; this does not delete the files. Normal owner sign-in, explicit connection authorization and fresh file approvals restore access without creating replacement identities or Vaults.

Before registering a production application, send the platform team its exact HTTPS origin, exact same-origin callback, and optional logout URL. Staging needs a separate registration. The application also chooses and implements its actual owner-device consent experience and protects its backend app/recipient credentials. The documented API transport removes any need for a Hybrid-ID web-interface step; it does not remove explicit user consent or permit a backend to impersonate its users.

This five-owner exercise establishes neither a load/scale SLA nor geographic redundancy. It does not establish unattended background access beyond the original eight-hour authorization window, or recall of plaintext already decrypted. Existing Messaging archival and MPC activation gates remain unchanged.
