{"openapi":"3.1.0","info":{"title":"PAIC Public API","version":"0.1.0","description":"Build websites and automations on top of PAIC.\n\n## Start here\n\nThe API is served below the `/api` base path. Read the [PAIC Public API Guide](/api/PAIC-PUBLIC-API-GUIDE.md)\nfor complete integration examples, response envelopes, roles, configuration, and the WebRTC\nlifecycle. The documentation and health check are public; account data and processing are not.\n\n## Authentication\n\n- **Browser applications:** use the secure session cookie returned by `POST /auth/login`.\n- **Server-side automation:** use `Authorization: Bearer <token>` with the scopes listed by each operation.\n\n## Cross-origin websites\n\nUse a backend-for-frontend (BFF) for a website on another domain. Do not try to call PAIC directly\nfrom browser JavaScript. The Node backend should keep a separate PAIC cookie jar/session for each\nwebsite user and issue its own HttpOnly website session cookie. Cookie-authenticated PAIC mutations\nrequire a matching `Origin` header.\n\n## Intended browser flow\n\n```text\nLogin\n  ↓\nLoad user/config/presets/reference image\n  ↓\nChoose processing mode\n  ↓\nGet /streams/routes\n  ↓\nBook GPU time if routes say it is required\n  ↓\nStart local camera\n  ↓\nWHIP → publish camera\n  ↓\nPAIC processing starts\n  ↓\nWHEP → processed preview\n  ↓\nStop → DELETE WHIP/WHEP sessions + camera tracks\n```\n\n## Streaming\n\nThe streaming sequence matters: publish the camera using WHIP first, then connect to the processed\noutput using WHEP. The processed output may not exist immediately. The processing pipeline supports\nH.264, AV1, and H.265. The web client prefers **AV1**, then **H.265**, then **H.264**.\n\n## Processing modes\n\nEach account has a `processing-mode` configuration value. `gpu` is the default and can require an\nactive booking. `passthrough` does not use a GPU or require a booking: it decodes H.264, H.265/HEVC,\nor AV1 input, optionally adds deployment text, and publishes H.264 output. Set the mode with\n`POST /config`, then fetch `/streams/routes`. Use `active_stream.processing_mode`,\n`active_stream.passthrough_available`, and `active_stream.booking_required` from that response to\ndecide whether to publish or book. A mode change applies to the next publishing session.\n\n## Booking availability\n\nUse the limits returned by booking availability. Do not hard-code slot duration, booking windows, or\ndaily limits. A slot can disappear between reading availability and creating the booking, so handle\n`409 Conflict` by refreshing availability and asking the user to choose an available slot.\n\n## First request\n\n```bash\ncurl https://YOUR_PAIC_HOST/api/health\n```\n\nSuccessful requests and errors use JSON unless an operation documents a binary or WebRTC media type.\nNever expose bearer tokens, session cookies, or one-time SRT credential URLs in client-side code or logs.\n"},"paths":{"/health":{"get":{"summary":"Health","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Health Health Get"}}}}},"tags":["Service status"]}},"/auth/me":{"get":{"summary":"Me","operationId":"me_auth_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserEnvelope"}}}}},"security":[{"SessionCookie":[]}],"tags":["Account"]}},"/auth/login":{"post":{"summary":"Login","operationId":"login_auth_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"tags":["Account"]}},"/auth/logout":{"post":{"summary":"Logout","operationId":"logout_auth_logout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"SessionCookie":[]}],"tags":["Account"]}},"/auth/password":{"post":{"summary":"Change Password","operationId":"change_password_auth_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasswordChangeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"SessionCookie":[]}],"tags":["Account"]}},"/bookings/availability":{"get":{"summary":"Booking Availability","operationId":"booking_availability_bookings_availability_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Bookings"],"description":"Requires a user session or a bearer token with bookings:read. Account role and resource access rules also apply. See the integration guide for response fields and examples.","x-required-bearer-scopes":["bookings:read"],"parameters":[{"name":"from","in":"query","required":false,"description":"RFC 3339 timestamp with a timezone. Omit to use the default window.","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","required":false,"description":"RFC 3339 timestamp with a timezone. Omit to use the default window.","schema":{"type":"string","format":"date-time"}}]}},"/bookings":{"get":{"summary":"Get Bookings","operationId":"get_bookings_bookings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Bookings"],"description":"Requires a user session or a bearer token with bookings:read. Account role and resource access rules also apply. See the integration guide for response fields and examples.","x-required-bearer-scopes":["bookings:read"]},"post":{"summary":"Post Booking","operationId":"post_booking_bookings_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingCreateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Bookings"],"description":"Requires a user session or a bearer token with bookings:write. Account role and resource access rules also apply. See the integration guide for response fields and examples.","x-required-bearer-scopes":["bookings:write"]}},"/bookings/{booking_id}":{"delete":{"summary":"Delete Booking","operationId":"delete_booking_bookings__booking_id__delete","parameters":[{"name":"booking_id","in":"path","required":true,"schema":{"type":"string","title":"Booking Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Bookings"],"description":"Requires a user session or a bearer token with bookings:write. Account role and resource access rules also apply. See the integration guide for response fields and examples.","x-required-bearer-scopes":["bookings:write"]}},"/recordings":{"get":{"summary":"Get Recordings","operationId":"get_recordings_recordings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Recordings"],"description":"Requires a user session or a bearer token with recordings:read. Account role and resource access rules also apply. See the integration guide for response fields and examples.","x-required-bearer-scopes":["recordings:read"]}},"/recordings/{recording_id}/download":{"get":{"summary":"Download Recording","operationId":"download_recording_recordings__recording_id__download_get","parameters":[{"name":"recording_id","in":"path","required":true,"schema":{"type":"string","title":"Recording Id"}}],"responses":{"200":{"description":"Owned file bytes, not JSON.","content":{"video/mp4":{"schema":{"type":"string","format":"binary"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Recordings"],"description":"Requires a user session or a bearer token with recordings:read. Account role and resource access rules also apply. See the integration guide for response fields and examples.","x-required-bearer-scopes":["recordings:read"]}},"/config":{"get":{"summary":"Get Config","operationId":"get_config_config_get","responses":{"200":{"description":"The current account's flat configuration.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"properties":{"processing-mode":{"type":"string","enum":["gpu","passthrough"],"default":"gpu","description":"Per-account processing choice. gpu uses the configured GPU pipeline and may require a booking. passthrough uses the CPU relay without a booking and publishes H.264 output. A change applies to the next publishing session."}}},"example":{"processing-mode":"gpu","prompt":"a watercolor portrait"}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Configuration"],"description":"Requires a user session or a bearer token with config:read. Account role and resource access rules also apply. See the integration guide for response fields and examples. The processing-mode field is gpu (the default, with booking rules) or passthrough (CPU relay without a booking).","x-required-bearer-scopes":["config:read"]},"post":{"summary":"Post Config","operationId":"post_config_config_post","responses":{"200":{"description":"The saved configuration; inspect config for the accepted mode.","content":{"application/json":{"schema":{"type":"object","required":["message","config"],"properties":{"message":{"type":"string"},"config":{"type":"object","additionalProperties":true,"properties":{"processing-mode":{"type":"string","enum":["gpu","passthrough"],"default":"gpu","description":"Per-account processing choice. gpu uses the configured GPU pipeline and may require a booking. passthrough uses the CPU relay without a booking and publishes H.264 output. A change applies to the next publishing session."}}}}},"example":{"message":"User config saved.","config":{"processing-mode":"passthrough"}}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Configuration"],"description":"Requires a user session or a bearer token with config:write. Account role and resource access rules also apply. See the integration guide for response fields and examples.","x-required-bearer-scopes":["config:write"],"requestBody":{"required":true,"description":"Partial configuration object, without a value/config wrapper. Recognized non-null fields are merged. Set processing-mode to gpu or passthrough, stop any current publishing session, then fetch /streams/routes before publishing again. Read the returned config for accepted values.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"properties":{"processing-mode":{"type":"string","enum":["gpu","passthrough"],"default":"gpu","description":"Per-account processing choice. gpu uses the configured GPU pipeline and may require a booking. passthrough uses the CPU relay without a booking and publishes H.264 output. A change applies to the next publishing session."}}},"examples":{"passthrough":{"summary":"Use the CPU relay without a booking","value":{"processing-mode":"passthrough"}},"gpu":{"summary":"Use booked GPU processing","value":{"processing-mode":"gpu"}}}}}}}},"/config/loras":{"get":{"summary":"Get Klein Loras","operationId":"get_klein_loras_config_loras_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Configuration"],"description":"Requires a user session or a bearer token with config:read. Account role and resource access rules also apply. See the integration guide for response fields and examples. Returns {loras: [{name, path}]}; use an allowed path verbatim as lora-weights. Treat path as an opaque selection value, not a browser URL.","x-required-bearer-scopes":["config:read"]}},"/streams/routes":{"get":{"summary":"Get Stream Routes","operationId":"get_stream_routes_streams_routes_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StreamRoutesResponse"}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Streams"],"description":"Requires a session or a token with stream:read or stream:publish. Returns only routes permitted by the role and scopes; optional URLs may be absent. active_stream reports processing_mode, passthrough_available, booking_required, and booking. Check those fields after changing processing-mode. Passthrough accepts H.264, H.265/HEVC, or AV1 input and publishes H.264 output. Use returned WHIP/WHEP URLs verbatim; they already include the API prefix."}},"/auth/tokens":{"get":{"summary":"Get Tokens","operationId":"get_tokens_auth_tokens_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"SessionCookie":[]}],"tags":["Account"]},"post":{"summary":"Create Token","operationId":"create_token_auth_tokens_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenCreateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"SessionCookie":[]}],"tags":["Account"]}},"/auth/tokens/{token_id}":{"delete":{"summary":"Delete Token","operationId":"delete_token_auth_tokens__token_id__delete","parameters":[{"name":"token_id","in":"path","required":true,"schema":{"type":"string","title":"Token Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"SessionCookie":[]}],"tags":["Account"]}},"/streams/srt-credentials":{"get":{"summary":"List Srt Credentials","operationId":"list_srt_credentials_streams_srt_credentials_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SrtCredentialListResponse"}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Streams"],"description":"Requires a session or stream:read/stream:publish token. Creation requires the scope matching action; publishing also requires a write-capable role. List results are scope-filtered metadata. The credential.url secret is returned only on creation; never log it or embed it in public pages."},"post":{"summary":"Create Srt Credential","operationId":"create_srt_credential_streams_srt_credentials_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SrtCredentialCreateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SrtCredentialCreateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Streams"],"description":"Requires a session or stream:read/stream:publish token. Creation requires the scope matching action; publishing also requires a write-capable role. List results are scope-filtered metadata. The credential.url secret is returned only on creation; never log it or embed it in public pages."}},"/streams/srt-credentials/{credential_id}":{"delete":{"summary":"Revoke Srt Credential","operationId":"revoke_srt_credential_streams_srt_credentials__credential_id__delete","parameters":[{"name":"credential_id","in":"path","required":true,"schema":{"type":"string","title":"Credential Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Streams"]}},"/webrtc/{proxied_path}":{"delete":{"summary":"Webrtc Proxy","operationId":"webrtc_proxy_webrtc__proxied_path__delete","parameters":[{"name":"proxied_path","in":"path","required":true,"schema":{"type":"string","title":"Proxied Path"}}],"responses":{"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"204":{"description":"Success; no response body."}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Streams"],"description":"Authenticated WHIP/WHEP signaling. Use URLs returned by /streams/routes. WHIP requires stream:publish and a write-capable role; WHEP requires stream:read. POST to the protocol URL; PATCH/DELETE to the session Location returned by POST. Cookie-authenticated mutations need a matching Origin. Errors may be plain text; see the guide for ICE and cleanup."},"patch":{"summary":"Webrtc Proxy","operationId":"webrtc_proxy_webrtc__proxied_path__patch","parameters":[{"name":"proxied_path","in":"path","required":true,"schema":{"type":"string","title":"Proxied Path"}},{"name":"If-Match","in":"header","schema":{"type":"string"}}],"responses":{"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"204":{"description":"Success; no response body."}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Streams"],"description":"Authenticated WHIP/WHEP signaling. Use URLs returned by /streams/routes. WHIP requires stream:publish and a write-capable role; WHEP requires stream:read. POST to the protocol URL; PATCH/DELETE to the session Location returned by POST. Cookie-authenticated mutations need a matching Origin. Errors may be plain text; see the guide for ICE and cleanup.","requestBody":{"required":true,"content":{"application/trickle-ice-sdpfrag":{"schema":{"type":"string"}}}}},"post":{"summary":"Webrtc Proxy","operationId":"webrtc_proxy_webrtc__proxied_path__post","parameters":[{"name":"proxied_path","in":"path","required":true,"schema":{"type":"string","title":"Proxied Path"}}],"responses":{"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"201":{"description":"Session created; SDP answer in the body.","headers":{"Location":{"schema":{"type":"string"},"description":"Session URL for subsequent PATCH/DELETE."},"ETag":{"schema":{"type":"string"},"description":"Session entity tag; retain for If-Match when using trickle ICE."},"Link":{"schema":{"type":"string"},"description":"Optional ICE server configuration."},"Accept-Patch":{"schema":{"type":"string"},"description":"Supported PATCH media type."}},"content":{"application/sdp":{"schema":{"type":"string"}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Streams"],"description":"Authenticated WHIP/WHEP signaling. Use URLs returned by /streams/routes. WHIP requires stream:publish and a write-capable role; WHEP requires stream:read. POST to the protocol URL; PATCH/DELETE to the session Location returned by POST. Cookie-authenticated mutations need a matching Origin. Errors may be plain text; see the guide for ICE and cleanup.","requestBody":{"required":true,"content":{"application/sdp":{"schema":{"type":"string"}}}}},"options":{"summary":"Webrtc Proxy","operationId":"webrtc_proxy_webrtc__proxied_path__options","parameters":[{"name":"proxied_path","in":"path","required":true,"schema":{"type":"string","title":"Proxied Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Streams"],"description":"Authenticated WHIP/WHEP signaling. Use URLs returned by /streams/routes. WHIP requires stream:publish and a write-capable role; WHEP requires stream:read. POST to the protocol URL; PATCH/DELETE to the session Location returned by POST. Cookie-authenticated mutations need a matching Origin. Errors may be plain text; see the guide for ICE and cleanup."}},"/assets/image":{"get":{"summary":"Get Source Face","operationId":"get_source_face_assets_image_get","responses":{"200":{"description":"Owned file bytes, not JSON.","content":{"image/png":{"schema":{"type":"string","format":"binary"}},"image/jpeg":{"schema":{"type":"string","format":"binary"}},"image/webp":{"schema":{"type":"string","format":"binary"}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Assets"],"description":"Requires a user session or a bearer token with assets:read. Account role and resource access rules also apply. See the integration guide for response fields and examples.","x-required-bearer-scopes":["assets:read"]},"delete":{"summary":"Delete Source Face","operationId":"delete_source_face_assets_image_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Assets"],"description":"Requires a user session or a bearer token with assets:write. Account role and resource access rules also apply. See the integration guide for response fields and examples.","x-required-bearer-scopes":["assets:write"]}},"/config/presets":{"get":{"summary":"Get Presets","operationId":"get_presets_config_presets_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Configuration"],"description":"Requires a user session or a bearer token with presets:read. Account role and resource access rules also apply. See the integration guide for response fields and examples.","x-required-bearer-scopes":["presets:read"]},"post":{"summary":"Post Preset","operationId":"post_preset_config_presets_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresetCreateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Configuration"],"description":"Requires a user session or a bearer token with presets:write. Account role and resource access rules also apply. See the integration guide for response fields and examples.","x-required-bearer-scopes":["presets:write"]}},"/config/presets/{preset_id}":{"patch":{"summary":"Patch Preset","operationId":"patch_preset_config_presets__preset_id__patch","parameters":[{"name":"preset_id","in":"path","required":true,"schema":{"type":"string","title":"Preset Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresetUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Configuration"],"description":"Requires a user session or a bearer token with presets:write. Account role and resource access rules also apply. See the integration guide for response fields and examples.","x-required-bearer-scopes":["presets:write"]},"delete":{"summary":"Delete Preset","operationId":"delete_preset_config_presets__preset_id__delete","parameters":[{"name":"preset_id","in":"path","required":true,"schema":{"type":"string","title":"Preset Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Configuration"],"description":"Requires a user session or a bearer token with presets:write. Account role and resource access rules also apply. See the integration guide for response fields and examples.","x-required-bearer-scopes":["presets:write"]}},"/config/presets/{preset_id}/apply":{"post":{"summary":"Apply Preset","operationId":"apply_preset_config_presets__preset_id__apply_post","parameters":[{"name":"preset_id","in":"path","required":true,"schema":{"type":"string","title":"Preset Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Configuration"],"description":"Requires a user session or a bearer token with presets:write. Account role and resource access rules also apply. See the integration guide for response fields and examples.","x-required-bearer-scopes":["presets:write"]}},"/uploadImage":{"post":{"summary":"Upload Source Face","operationId":"upload_source_face_uploadImage_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_source_face_uploadImage_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"SessionCookie":[]},{"BearerToken":[]}],"tags":["Assets"],"description":"Requires a user session or a bearer token with assets:write. Account role and resource access rules also apply. See the integration guide for response fields and examples.","x-required-bearer-scopes":["assets:write"]}},"/auth/invitations/accept":{"post":{"summary":"Accept Account Invitation","operationId":"accept_account_invitation_auth_invitations_accept_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvitationAcceptRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"tags":["Account"],"description":"Redeem an invitation using token, username and password. No session is required. This does not log in; call /auth/login after successful redemption."}},"/videos":{"get":{"summary":"List Videos","operationId":"list_videos_videos_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"SessionCookie":[]}],"tags":["videos"],"description":"Requires a user session or a bearer token with stream:read. Account role and resource access rules also apply. See the integration guide for response fields and examples.","x-required-bearer-scopes":["stream:read"]},"post":{"summary":"Create Video","operationId":"create_video_videos_post","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Payload"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"SessionCookie":[]}],"tags":["videos"],"description":"Requires a user session or a bearer token with stream:publish. Account role and resource access rules also apply. See the integration guide for response fields and examples.","x-required-bearer-scopes":["stream:publish"]}},"/videos/{job_id}/source":{"post":{"summary":"Upload Video Chunk","operationId":"upload_video_chunk_videos__job_id__source_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"SessionCookie":[]}],"tags":["videos"],"description":"Requires a user session or a bearer token with stream:publish. Account role and resource access rules also apply. See the integration guide for response fields and examples.","x-required-bearer-scopes":["stream:publish"]}},"/videos/{job_id}/start":{"post":{"summary":"Start Video","operationId":"start_video_videos__job_id__start_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"SessionCookie":[]}],"tags":["videos"],"description":"Requires a user session or a bearer token with stream:publish. Account role and resource access rules also apply. See the integration guide for response fields and examples.","x-required-bearer-scopes":["stream:publish"]}},"/videos/{job_id}":{"get":{"summary":"Video Status","operationId":"video_status_videos__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"SessionCookie":[]}],"tags":["videos"],"description":"Requires a user session or a bearer token with stream:read. Account role and resource access rules also apply. See the integration guide for response fields and examples.","x-required-bearer-scopes":["stream:read"]},"delete":{"summary":"Delete Video","operationId":"delete_video_videos__job_id__delete","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"SessionCookie":[]}],"tags":["videos"],"description":"Requires a user session or a bearer token with stream:publish. Account role and resource access rules also apply. See the integration guide for response fields and examples.","x-required-bearer-scopes":["stream:publish"]}}},"components":{"schemas":{"Body_upload_source_face_uploadImage_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_source_face_uploadImage_post"},"BookingCreateRequest":{"properties":{"start_at":{"type":"string","format":"date-time","title":"Start At"},"end_at":{"type":"string","format":"date-time","title":"End At"}},"additionalProperties":false,"type":"object","required":["start_at","end_at"],"title":"BookingCreateRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"InvitationAcceptRequest":{"properties":{"username":{"type":"string","maxLength":100,"minLength":1,"title":"Username"},"password":{"type":"string","maxLength":128,"minLength":15,"title":"Password"},"token":{"type":"string","maxLength":128,"minLength":1,"title":"Token"}},"additionalProperties":false,"type":"object","required":["username","password","token"],"title":"InvitationAcceptRequest"},"LoginRequest":{"properties":{"username":{"type":"string","maxLength":100,"minLength":1,"title":"Username"},"password":{"type":"string","maxLength":128,"minLength":1,"title":"Password"}},"additionalProperties":false,"type":"object","required":["username","password"],"title":"LoginRequest"},"PasswordChangeRequest":{"properties":{"current_password":{"type":"string","maxLength":128,"minLength":1,"title":"Current Password"},"new_password":{"type":"string","maxLength":128,"minLength":15,"title":"New Password"}},"additionalProperties":false,"type":"object","required":["current_password","new_password"],"title":"PasswordChangeRequest"},"PresetCreateRequest":{"properties":{"name":{"type":"string","title":"Name"},"value":{"additionalProperties":true,"type":"object","title":"Value"},"is_shared":{"type":"boolean","title":"Is Shared","default":false}},"additionalProperties":false,"type":"object","required":["name","value"],"title":"PresetCreateRequest"},"PresetUpdateRequest":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"value":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Value"},"is_shared":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Shared"}},"additionalProperties":false,"type":"object","title":"PresetUpdateRequest"},"RevokeResponse":{"properties":{"ok":{"type":"boolean","title":"Ok"},"kicked":{"type":"integer","title":"Kicked"}},"additionalProperties":false,"type":"object","required":["ok","kicked"],"title":"RevokeResponse"},"SrtCredentialCreateRequest":{"properties":{"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name"},"action":{"type":"string","enum":["read","publish"],"title":"Action"}},"additionalProperties":false,"type":"object","required":["name","action"],"title":"SrtCredentialCreateRequest"},"SrtCredentialCreateResponse":{"properties":{"credential":{"$ref":"#/components/schemas/SrtCredentialCreated"}},"additionalProperties":false,"type":"object","required":["credential"],"title":"SrtCredentialCreateResponse"},"SrtCredentialCreated":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"action":{"type":"string","enum":["read","publish"],"title":"Action"},"created_at":{"type":"string","title":"Created At"},"expires_at":{"type":"string","title":"Expires At"},"revoked_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Revoked At"},"url":{"type":"string","title":"Url"}},"additionalProperties":false,"type":"object","required":["id","name","action","created_at","expires_at","url"],"title":"SrtCredentialCreated"},"SrtCredentialListResponse":{"properties":{"credentials":{"items":{"$ref":"#/components/schemas/SrtCredentialMetadata"},"type":"array","title":"Credentials"}},"additionalProperties":false,"type":"object","required":["credentials"],"title":"SrtCredentialListResponse"},"SrtCredentialMetadata":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"action":{"type":"string","enum":["read","publish"],"title":"Action"},"created_at":{"type":"string","title":"Created At"},"expires_at":{"type":"string","title":"Expires At"},"revoked_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Revoked At"}},"additionalProperties":false,"type":"object","required":["id","name","action","created_at","expires_at"],"title":"SrtCredentialMetadata"},"StreamRoutesResponse":{"properties":{"tenant_id":{"type":"string","title":"Tenant Id"},"input_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Input Path"},"output_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Output Path"},"whip_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Whip Url"},"whep_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Whep Url"},"webrtc_proxy_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Webrtc Proxy Url"},"capture_defaults":{"additionalProperties":true,"type":"object","title":"Capture Defaults"},"active_stream":{"additionalProperties":true,"type":"object","title":"Active Stream"}},"additionalProperties":false,"type":"object","required":["tenant_id","capture_defaults","active_stream"],"title":"StreamRoutesResponse"},"TokenCreateRequest":{"properties":{"name":{"type":"string","title":"Name"},"scopes":{"items":{"type":"string"},"type":"array","title":"Scopes"},"expires_in_days":{"type":"integer","maximum":365.0,"minimum":1.0,"title":"Expires In Days","default":90}},"additionalProperties":false,"type":"object","required":["name","scopes"],"title":"TokenCreateRequest"},"UserEnvelope":{"properties":{"user":{"$ref":"#/components/schemas/UserResponse"}},"additionalProperties":false,"type":"object","required":["user"],"title":"UserEnvelope"},"UserResponse":{"properties":{"id":{"type":"string","title":"Id"},"username":{"type":"string","title":"Username"},"role":{"type":"string","enum":["owner","admin","operator","viewer"],"title":"Role"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updated At"}},"additionalProperties":false,"type":"object","required":["id","username","role"],"title":"UserResponse"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"SessionCookie":{"type":"apiKey","in":"cookie","name":"paic_admin_session"},"BearerToken":{"type":"http","scheme":"bearer"}}},"servers":[{"url":"/api"}],"externalDocs":{"description":"PAIC Public API Guide — website integration and examples","url":"/api/PAIC-PUBLIC-API-GUIDE.md"},"tags":[{"name":"Service status","description":"Public service availability check; no authentication required."},{"name":"Account","description":"Sign in, inspect the current account, and manage session credentials."},{"name":"Bookings","description":"Check processing availability and manage scheduled GPU bookings."},{"name":"Configuration","description":"Read and update generation settings, presets, and available LoRA adapters."},{"name":"Streams","description":"Discover permitted routes, create SRT credentials, and exchange WHIP/WHEP signaling."},{"name":"Assets","description":"Upload, inspect, and remove the source image used for processing."},{"name":"Recordings","description":"List recording metadata and download owned recording files."}]}