Files
momentry_core/docs_v1.0/doc/07_identity.html

516 lines
23 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>07 Identity - Momentry API Docs</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f5f5f5; color: #333; padding: 40px; }
.container { max-width: 960px; margin: 0 auto; background: white; border-radius: 12px; box-shadow: 0 2px 12px rgba(0,0,0,0.08); padding: 40px; }
h1 { font-size: 24px; margin: 24px 0 12px; }
h2 { font-size: 20px; margin: 20px 0 10px; color: #222; }
h3 { font-size: 16px; margin: 16px 0 8px; color: #444; }
p { line-height: 1.6; margin: 8px 0; }
table { border-collapse: collapse; width: 100%; margin: 12px 0; font-size: 14px; }
th, td { border: 1px solid #ddd; padding: 8px 12px; text-align: left; }
th { background: #f0f0f0; font-weight: 600; }
code { background: #f0f0f0; padding: 2px 6px; border-radius: 3px; font-size: 13px; }
pre { background: #f8f8f8; border: 1px solid #ddd; border-radius: 6px; padding: 12px; overflow-x: auto; margin: 12px 0; }
pre code { background: none; padding: 0; }
a { color: #0066cc; }
.back { display: inline-block; margin-bottom: 20px; color: #666; }
.back:hover { color: #333; }
.topbar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; }
.logout-btn { font-size: 13px; color: #999; text-decoration: none; }
.logout-btn:hover { color: #cc0000; }
</style>
</head>
<body>
<div class="container">
<div class="topbar">
<a class="back" href="index.html">&larr; Back to index</a>
<a class="logout-btn" href="#" onclick="fetch('/api/v1/auth/logout',{method:'POST'}).then(()=>window.location.reload());return false">Logout</a>
</div>
<!-- module: identity -->
<!-- description: Global identities — CRUD, detail, files, faces, bind, unbind, search -->
<!-- depends: 01_auth -->
<h2>Global Identities</h2>
<h3><code>GET /api/v1/identities</code></h3>
<p><strong>Auth</strong>: Required
<strong>Scope</strong>: identity-level</p>
<p>List all registered identities with pagination.</p>
<h4>Example</h4>
<div class="codehilite"><pre><span></span><code>curl<span class="w"> </span>-s<span class="w"> </span><span class="s2">&quot;</span><span class="nv">$API</span><span class="s2">/api/v1/identities?page=1&amp;page_size=20&quot;</span><span class="w"> </span>-H<span class="w"> </span><span class="s2">&quot;X-API-Key: </span><span class="nv">$KEY</span><span class="s2">&quot;</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>jq<span class="w"> </span><span class="s1">&#39;{count, identities: [.identities[] | {name}]}&#39;</span>
</code></pre></div>
<hr />
<h3><code>GET /api/v1/identity/:identity_uuid</code></h3>
<p><strong>Auth</strong>: Required
<strong>Scope</strong>: identity-level</p>
<p>Get detailed information for a specific identity, including metadata and TMDb references.</p>
<h4>Example</h4>
<div class="codehilite"><pre><span></span><code>curl<span class="w"> </span>-s<span class="w"> </span><span class="s2">&quot;</span><span class="nv">$API</span><span class="s2">/api/v1/identity/</span><span class="nv">$IDENTITY_UUID</span><span class="s2">&quot;</span><span class="w"> </span>-H<span class="w"> </span><span class="s2">&quot;X-API-Key: </span><span class="nv">$KEY</span><span class="s2">&quot;</span>
</code></pre></div>
<h4>Response (200)</h4>
<div class="codehilite"><pre><span></span><code><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;success&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;identity_uuid&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;a9a901056d6b46ff92da0c3c1a57dff4&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Cary Grant&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;identity_type&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;people&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;source&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;tmdb&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;status&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;confirmed&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;tmdb_id&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">112</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;tmdb_profile&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;{output}/identities/{identity_uuid}/profile.jpg&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;metadata&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{},</span>
<span class="w"> </span><span class="nt">&quot;reference_data&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{},</span>
<span class="w"> </span><span class="nt">&quot;created_at&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;2026-05-16T12:00:00Z&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;updated_at&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span>
<span class="p">}</span>
</code></pre></div>
<table class="table">
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>identity_uuid</code></td>
<td>string</td>
<td>Identity identifier</td>
</tr>
<tr>
<td><code>name</code></td>
<td>string</td>
<td>Identity name</td>
</tr>
<tr>
<td><code>identity_type</code></td>
<td>string</td>
<td><code>"people"</code> or null</td>
</tr>
<tr>
<td><code>source</code></td>
<td>string</td>
<td><code>.json</code>, <code>auto</code>, <code>tmdb</code>, <code>user_defined</code>, or <code>merged</code></td>
</tr>
<tr>
<td><code>status</code></td>
<td>string</td>
<td><code>"confirmed"</code>, <code>"pending"</code>, or <code>"inactive"</code></td>
</tr>
<tr>
<td><code>tmdb_id</code></td>
<td>integer</td>
<td>TMDb person ID (only if source = tmdb)</td>
</tr>
<tr>
<td><code>tmdb_profile</code></td>
<td>string</td>
<td>Local profile image path (<code>{output}/identities/{uuid}/profile.jpg</code>)</td>
</tr>
<tr>
<td><code>metadata</code></td>
<td>object</td>
<td>Metadata JSON (tmdb_character, cast_order, etc.)</td>
</tr>
<tr>
<td><code>created_at</code></td>
<td>string</td>
<td>Creation timestamp</td>
</tr>
</tbody>
</table>
<hr />
<h3><code>DELETE /api/v1/identity/:identity_uuid</code></h3>
<p><strong>Auth</strong>: Required
<strong>Scope</strong>: identity-level</p>
<p>Delete an identity permanently.</p>
<hr />
<h3><code>GET /api/v1/identity/:identity_uuid/files</code></h3>
<p><strong>Auth</strong>: Required
<strong>Scope</strong>: identity-level</p>
<p>Get all files where this identity appears. Returns per-file summary including face count, confidence, and appearance time range.</p>
<h4>Example</h4>
<div class="codehilite"><pre><span></span><code>curl<span class="w"> </span>-s<span class="w"> </span><span class="s2">&quot;</span><span class="nv">$API</span><span class="s2">/api/v1/identity/</span><span class="nv">$IDENTITY_UUID</span><span class="s2">/files&quot;</span><span class="w"> </span>-H<span class="w"> </span><span class="s2">&quot;X-API-Key: </span><span class="nv">$KEY</span><span class="s2">&quot;</span>
</code></pre></div>
<hr />
<h3><code>GET /api/v1/identity/:identity_uuid/faces</code></h3>
<p><strong>Auth</strong>: Required
<strong>Scope</strong>: identity-level</p>
<p>Get all face detection records associated with this identity.</p>
<h4>Example</h4>
<div class="codehilite"><pre><span></span><code>curl<span class="w"> </span>-s<span class="w"> </span><span class="s2">&quot;</span><span class="nv">$API</span><span class="s2">/api/v1/identity/</span><span class="nv">$IDENTITY_UUID</span><span class="s2">/faces&quot;</span><span class="w"> </span>-H<span class="w"> </span><span class="s2">&quot;X-API-Key: </span><span class="nv">$KEY</span><span class="s2">&quot;</span>
</code></pre></div>
<table class="table">
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>file_uuid</code></td>
<td>string</td>
<td>File where face was detected</td>
</tr>
<tr>
<td><code>frame_number</code></td>
<td>integer</td>
<td>Frame number of detection</td>
</tr>
<tr>
<td><code>face_id</code></td>
<td>string</td>
<td>Face ID (format: <code>face_{frame_number}</code>)</td>
</tr>
<tr>
<td><code>confidence</code></td>
<td>float</td>
<td>Detection confidence</td>
</tr>
</tbody>
</table>
<hr />
<h3><code>GET /api/v1/identity/:identity_uuid/chunks</code></h3>
<p><strong>Auth</strong>: Required
<strong>Scope</strong>: identity-level</p>
<p>Get all text chunks (sentences) spoken while this identity's face was on screen. Useful for finding what a person said.</p>
<h4>Example</h4>
<div class="codehilite"><pre><span></span><code>curl<span class="w"> </span>-s<span class="w"> </span><span class="s2">&quot;</span><span class="nv">$API</span><span class="s2">/api/v1/identity/</span><span class="nv">$IDENTITY_UUID</span><span class="s2">/chunks&quot;</span><span class="w"> </span>-H<span class="w"> </span><span class="s2">&quot;X-API-Key: </span><span class="nv">$KEY</span><span class="s2">&quot;</span>
</code></pre></div>
<h4>Response (200)</h4>
<div class="codehilite"><pre><span></span><code><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;success&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;identity_uuid&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;a9a901056d6b46ff92da0c3c1a57dff4&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;data&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;file_uuid&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;bd80fec92b0b6963d177a2c55bf713e2&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;chunk_id&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;bd80fec92b0b6963d177a2c55bf713e2_2&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;chunk_type&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;sentence&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;start_frame&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">5103</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;end_frame&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">5127</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;fps&quot;</span><span class="p">:</span><span class="w"> </span><span class="mf">24.0</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;start_time&quot;</span><span class="p">:</span><span class="w"> </span><span class="mf">212.64</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;end_time&quot;</span><span class="p">:</span><span class="w"> </span><span class="mf">213.64</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;text_content&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;[213s-214s] Cary Grant: \&quot;Olá!\&quot;&quot;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">]</span>
<span class="p">}</span>
</code></pre></div>
<table class="table">
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>file_uuid</code></td>
<td>string</td>
<td>File identifier</td>
</tr>
<tr>
<td><code>chunk_id</code></td>
<td>string</td>
<td>Sentence chunk identifier</td>
</tr>
<tr>
<td><code>start_frame</code></td>
<td>integer</td>
<td>Frame-accurate start position</td>
</tr>
<tr>
<td><code>end_frame</code></td>
<td>integer</td>
<td>Frame-accurate end position</td>
</tr>
<tr>
<td><code>fps</code></td>
<td>float</td>
<td>Frames per second</td>
</tr>
<tr>
<td><code>start_time</code></td>
<td>float</td>
<td>Start time in seconds</td>
</tr>
<tr>
<td><code>end_time</code></td>
<td>float</td>
<td>End time in seconds</td>
</tr>
<tr>
<td><code>text_content</code></td>
<td>string</td>
<td>Spoken text content</td>
</tr>
</tbody>
</table>
<hr />
<h3><code>POST /api/v1/identity/:identity_uuid/bind</code></h3>
<p><strong>Auth</strong>: Required
<strong>Scope</strong>: identity-level</p>
<p>Bind a face detection to an identity. Associates the face trace with the identity for future search and recognition.</p>
<h4>Request Parameters</h4>
<table class="table">
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Required</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>file_uuid</code></td>
<td>string</td>
<td>Yes</td>
<td>File where face is detected</td>
</tr>
<tr>
<td><code>face_id</code></td>
<td>string</td>
<td>Yes</td>
<td>Face ID (format: <code>{frame}_{idx}</code>)</td>
</tr>
</tbody>
</table>
<h4>Example</h4>
<div class="codehilite"><pre><span></span><code>curl<span class="w"> </span>-s<span class="w"> </span>-X<span class="w"> </span>POST<span class="w"> </span><span class="s2">&quot;</span><span class="nv">$API</span><span class="s2">/api/v1/identity/</span><span class="nv">$IDENTITY_UUID</span><span class="s2">/bind&quot;</span><span class="w"> </span><span class="se">\</span>
<span class="w"> </span>-H<span class="w"> </span><span class="s2">&quot;X-API-Key: </span><span class="nv">$KEY</span><span class="s2">&quot;</span><span class="w"> </span><span class="se">\</span>
<span class="w"> </span>-H<span class="w"> </span><span class="s2">&quot;Content-Type: application/json&quot;</span><span class="w"> </span><span class="se">\</span>
<span class="w"> </span>-d<span class="w"> </span><span class="s1">&#39;{&quot;file_uuid&quot;: &quot;&#39;</span><span class="s2">&quot;</span><span class="nv">$FILE_UUID</span><span class="s2">&quot;</span><span class="s1">&#39;&quot;, &quot;face_id&quot;: &quot;1_5&quot;}&#39;</span>
</code></pre></div>
<hr />
<h3><code>POST /api/v1/identity/:identity_uuid/unbind</code></h3>
<p><strong>Auth</strong>: Required
<strong>Scope</strong>: identity-level</p>
<p>Unbind a face detection from an identity. Removes the identity association from the face record.</p>
<hr />
<h3><code>GET /api/v1/identities/search</code></h3>
<p><strong>Auth</strong>: Required
<strong>Scope</strong>: identity-level</p>
<p>Search identities by name (ILIKE search). Returns matching identity records.</p>
<h4>Example</h4>
<div class="codehilite"><pre><span></span><code>curl<span class="w"> </span>-s<span class="w"> </span><span class="s2">&quot;</span><span class="nv">$API</span><span class="s2">/api/v1/identities/search?q=Cary&quot;</span><span class="w"> </span>-H<span class="w"> </span><span class="s2">&quot;X-API-Key: </span><span class="nv">$KEY</span><span class="s2">&quot;</span>
</code></pre></div>
<table class="table">
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>name</code></td>
<td>string</td>
<td>Identity name</td>
</tr>
<tr>
<td><code>source</code></td>
<td>string</td>
<td>Identity source</td>
</tr>
<tr>
<td><code>tmdb_id</code></td>
<td>integer</td>
<td>TMDb ID (if source = tmdb)</td>
</tr>
<tr>
<td><code>file_uuid</code></td>
<td>string</td>
<td>Associated file</td>
</tr>
</tbody>
</table>
<hr />
<hr />
<h3><code>POST /api/v1/identity/upload</code></h3>
<p><strong>Auth</strong>: Required
<strong>Scope</strong>: identity-level</p>
<p>Upload an identity.json file to create or update an identity. Accepts the same format as the identity.json files stored on disk.</p>
<p>If an identity with the same <code>name</code> already exists, it will be updated with the new values.</p>
<h4>Request</h4>
<p>The request body is an <code>IdentityFile</code> object:</p>
<table class="table">
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Required</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>identity_uuid</code></td>
<td>string</td>
<td>Yes</td>
<td>Identity identifier</td>
</tr>
<tr>
<td><code>name</code></td>
<td>string</td>
<td>Yes</td>
<td>Identity display name</td>
</tr>
<tr>
<td><code>identity_type</code></td>
<td>string</td>
<td>No</td>
<td><code>"people"</code> or null</td>
</tr>
<tr>
<td><code>source</code></td>
<td>string</td>
<td>No</td>
<td><code>.json</code>, <code>auto</code>, <code>tmdb</code>, <code>user_defined</code>, or <code>merged</code></td>
</tr>
<tr>
<td><code>status</code></td>
<td>string</td>
<td>No</td>
<td><code>"confirmed"</code>, <code>"pending"</code>, or <code>"inactive"</code></td>
</tr>
<tr>
<td><code>tmdb_id</code></td>
<td>integer</td>
<td>No</td>
<td>TMDb person ID</td>
</tr>
<tr>
<td><code>tmdb_profile</code></td>
<td>string</td>
<td>No</td>
<td>TMDb profile image URL</td>
</tr>
<tr>
<td><code>metadata</code></td>
<td>object</td>
<td>No</td>
<td>Arbitrary metadata JSON</td>
</tr>
<tr>
<td><code>file_bindings</code></td>
<td>array</td>
<td>No</td>
<td>Array of <code>{ file_uuid, trace_ids, face_count }</code> (informational)</td>
</tr>
</tbody>
</table>
<h4>Example</h4>
<div class="codehilite"><pre><span></span><code>curl<span class="w"> </span>-s<span class="w"> </span>-X<span class="w"> </span>POST<span class="w"> </span><span class="s2">&quot;</span><span class="nv">$API</span><span class="s2">/api/v1/identity/upload&quot;</span><span class="w"> </span><span class="se">\</span>
<span class="w"> </span>-H<span class="w"> </span><span class="s2">&quot;X-API-Key: </span><span class="nv">$KEY</span><span class="s2">&quot;</span><span class="w"> </span><span class="se">\</span>
<span class="w"> </span>-H<span class="w"> </span><span class="s2">&quot;Content-Type: application/json&quot;</span><span class="w"> </span><span class="se">\</span>
<span class="w"> </span>-d<span class="w"> </span><span class="s1">&#39;{</span>
<span class="s1"> &quot;version&quot;: 1,</span>
<span class="s1"> &quot;identity_uuid&quot;: &quot;a9a901056d6b46ff92da0c3c1a57dff4&quot;,</span>
<span class="s1"> &quot;name&quot;: &quot;Cary Grant&quot;,</span>
<span class="s1"> &quot;identity_type&quot;: &quot;people&quot;,</span>
<span class="s1"> &quot;source&quot;: &quot;.json&quot;,</span>
<span class="s1"> &quot;status&quot;: &quot;confirmed&quot;,</span>
<span class="s1"> &quot;metadata&quot;: {},</span>
<span class="s1"> &quot;file_bindings&quot;: []</span>
<span class="s1"> }&#39;</span>
</code></pre></div>
<h4>Response (200)</h4>
<div class="codehilite"><pre><span></span><code><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;success&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;identity_uuid&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;a9a901056d6b46ff92da0c3c1a57dff4&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Cary Grant&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;message&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Identity uploaded successfully&quot;</span>
<span class="p">}</span>
</code></pre></div>
<hr />
<hr />
<h3><code>POST /api/v1/identity/:identity_uuid/profile-image</code></h3>
<p><strong>Auth</strong>: Required
<strong>Scope</strong>: identity-level</p>
<p>Upload a profile image (JPEG or PNG) for an identity. The image is saved to <code>{output}/identities/{uuid}/profile.{ext}</code>.</p>
<p>Uses <code>multipart/form-data</code> with field name <code>image</code>.</p>
<h4>Example</h4>
<div class="codehilite"><pre><span></span><code>curl<span class="w"> </span>-s<span class="w"> </span>-X<span class="w"> </span>POST<span class="w"> </span><span class="s2">&quot;</span><span class="nv">$API</span><span class="s2">/api/v1/identity/</span><span class="nv">$IDENTITY_UUID</span><span class="s2">/profile-image&quot;</span><span class="w"> </span><span class="se">\</span>
<span class="w"> </span>-H<span class="w"> </span><span class="s2">&quot;X-API-Key: </span><span class="nv">$KEY</span><span class="s2">&quot;</span><span class="w"> </span><span class="se">\</span>
<span class="w"> </span>-F<span class="w"> </span><span class="s2">&quot;image=@/path/to/photo.jpg&quot;</span>
</code></pre></div>
<h4>Response (200)</h4>
<div class="codehilite"><pre><span></span><code><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;success&quot;</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;identity_uuid&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;a9a901056d6b46ff92da0c3c1a57dff4&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;path&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;/path/to/output/identities/.../profile.jpg&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;message&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Profile image saved: profile.jpg&quot;</span>
<span class="p">}</span>
</code></pre></div>
<h4>Error Responses</h4>
<table class="table">
<thead>
<tr>
<th>HTTP</th>
<th>When</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>400</code></td>
<td>Missing image field or unsupported format</td>
</tr>
<tr>
<td><code>404</code></td>
<td>Identity not found</td>
</tr>
<tr>
<td><code>415</code></td>
<td>Unsupported image type (use JPEG or PNG)</td>
</tr>
</tbody>
</table>
<hr />
<h3><code>GET /api/v1/identity/:identity_uuid/profile-image</code></h3>
<p><strong>Auth</strong>: Required
<strong>Scope</strong>: identity-level</p>
<p>Retrieve the profile image for an identity. Returns the raw image data with appropriate Content-Type header.</p>
<div class="codehilite"><pre><span></span><code>curl<span class="w"> </span>-s<span class="w"> </span><span class="s2">&quot;</span><span class="nv">$API</span><span class="s2">/api/v1/identity/</span><span class="nv">$IDENTITY_UUID</span><span class="s2">/profile-image&quot;</span><span class="w"> </span><span class="se">\</span>
<span class="w"> </span>-H<span class="w"> </span><span class="s2">&quot;X-API-Key: </span><span class="nv">$KEY</span><span class="s2">&quot;</span><span class="w"> </span>-o<span class="w"> </span>profile.jpg
</code></pre></div>
<table class="table">
<thead>
<tr>
<th>Response Header</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>content-type</code></td>
<td><code>image/jpeg</code> or <code>image/png</code></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>