# Propose an exact owned-client registration policy POST /v1/projects/{project_id}/owned-clients Requires a controlled credential preparation and fresh private issuer custody readback. Stores the full immutable registration and versioned digest with exact accepted owner and catalog evidence for independent review. Approval does not install a client or authorize an assignment. Idempotency-Key replays the exact actor and body after current authority and fresh custody checks. Authentication: bearer access token with audience `taifa-management`. Endpoint roles and eligibility are reviewed separately from the OpenAPI bearer scheme. No operation-specific scopes are declared in the OpenAPI document. Bearer authentication and endpoint authorization requirements still apply. ## Parameters | Name | In | Type | Required | Description | | --- | --- | --- | --- | --- | | `project_id` | path | string | Yes | | | `idempotency-key` | header | string | Yes | | ## Request body ### application/json Required; ClientProposal | Field | Variant | Type | Required | Description | | --- | --- | --- | --- | --- | | `reason` | | string | Yes | Validation: min length 8; max length 500 | | `target_issuer` | | string | Yes | Validation: min length 1; max length 2048 | | `client_id` | | string | Yes | Validation: min length 1; max length 128 | | `client_version` | | integer | Yes | Validation: minimum 1; maximum 9223372036854775807 | | `display_name` | | string | Yes | Validation: min length 3; max length 120 | | `catalog_id` | | string | Yes | Validation: min length 1; max length 200 | | `credential_preparation_id` | | string | Yes | Canonical preparation UUID from controlled credential delivery. Management verifies fresh private issuer readback; browser proof is reference metadata only. Validation: min length 36; max length 36 | | `permission_ids` | | string[] | Yes | Validation: min items 1; max items 32 | | `registration` | | RegistrationProposal | Yes | | ## Responses ### 201 Successful Response | Field | Variant | Type | Required | Description | | --- | --- | --- | --- | --- | | `id` | | string | Yes | | | `project_id` | | string | Yes | | | `target_issuer` | | string | Yes | | | `client_id` | | string | Yes | | | `client_version` | | integer | Yes | | | `generation` | | integer | Yes | | | `display_name` | | string | Yes | | | `catalog_id` | | string | Yes | | | `catalog_digest` | | string | Yes | | | `permission_ids` | | string[] | Yes | | | `registration` | | RegistrationRead | Yes | | | `registration_digest` | | string | Yes | | | `policy_digest` | | string | Yes | | | `credential_preparation_id` | | string \| null | No | | | `custody_binding_digest` | | string \| null | No | | | `status` | | pending_review \| approved_pending_readback \| superseded \| revoked | Yes | | | `proposer` | | string | Yes | | | `approver` | | string \| null | Yes | | | `created_at` | | string | Yes | | | `expires_at` | | string | Yes | | | `actions` | | (approve \| revoke)[] | Yes | | | `revocation` | | RevocationRead \| null | No | | ### 403 Current project authority or independent review required No fields declared in the current specification. ### 409 Current exact proposal, catalog, version or idempotency conflict No fields declared in the current specification. ### 413 Exact JSON request exceeds 64 KiB No fields declared in the current specification. ### 422 Invalid exact reviewed policy or registration No fields declared in the current specification. ### 503 Configured owned issuer authority unavailable No fields declared in the current specification. ## Request examples Illustrative only. Replace placeholders and keep management tokens on the server. ### cURL ```sh curl -X POST 'https://YOUR_IDENTITY_HOST/v1/projects/REPLACE_WITH_PROJECT_ID/owned-clients' \ -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \ -H 'idempotency-key: REPLACE_WITH_IDEMPOTENCY_KEY' \ -H 'Content-Type: application/json' \ --data '{ "catalog_id": "00000000-0000-4000-8000-000000000001", "client_id": "case-app-test", "client_version": 1, "credential_preparation_id": "00000000-0000-4000-8000-000000000002", "display_name": "Case application test", "permission_ids": [ "case.read" ], "reason": "Review an owned case application registration", "registration": { "enabled": true, "management_access": false, "post_logout_redirect_uris": [ "https://case.example.test/signed-out" ], "redirect_uris": [ "https://case.example.test/callback" ], "refresh_allowed": false, "resource_audiences": [ "case-api-test" ], "secret_hash_fingerprint": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }, "target_issuer": "https://owned-issuer.example.test" }' ``` ### TypeScript (Node.js/server-side) ```typescript const response = await fetch('https://YOUR_IDENTITY_HOST/v1/projects/REPLACE_WITH_PROJECT_ID/owned-clients', { method: 'POST', headers: { Authorization: `Bearer ${process.env.TAIFA_MANAGEMENT_TOKEN}`, 'idempotency-key': 'REPLACE_WITH_IDEMPOTENCY_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ "catalog_id": "00000000-0000-4000-8000-000000000001", "client_id": "case-app-test", "client_version": 1, "credential_preparation_id": "00000000-0000-4000-8000-000000000002", "display_name": "Case application test", "permission_ids": [ "case.read" ], "reason": "Review an owned case application registration", "registration": { "enabled": true, "management_access": false, "post_logout_redirect_uris": [ "https://case.example.test/signed-out" ], "redirect_uris": [ "https://case.example.test/callback" ], "refresh_allowed": false, "resource_audiences": [ "case-api-test" ], "secret_hash_fingerprint": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }, "target_issuer": "https://owned-issuer.example.test" }) }); const result = await response.json(); ``` ### Python ```python import os import json import requests response = requests.request( 'POST', 'https://YOUR_IDENTITY_HOST/v1/projects/REPLACE_WITH_PROJECT_ID/owned-clients', headers={'Authorization': 'Bearer ' + os.environ['TAIFA_MANAGEMENT_TOKEN'], 'idempotency-key': 'REPLACE_WITH_IDEMPOTENCY_KEY'}, json=json.loads('{"catalog_id":"00000000-0000-4000-8000-000000000001","client_id":"case-app-test","client_version":1,"credential_preparation_id":"00000000-0000-4000-8000-000000000002","display_name":"Case application test","permission_ids":["case.read"],"reason":"Review an owned case application registration","registration":{"enabled":true,"management_access":false,"post_logout_redirect_uris":["https://case.example.test/signed-out"],"redirect_uris":["https://case.example.test/callback"],"refresh_allowed":false,"resource_audiences":["case-api-test"],"secret_hash_fingerprint":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},"target_issuer":"https://owned-issuer.example.test"}') ) response.raise_for_status() ``` ## Response example No response example in the current specification.