Third-party business API: 27 integration endpoints
These 27 endpoints are for backend-to-AKStream.Next integration using the contract matching the deployment version. A frontend receives only a short-lived playback/download address for an authorized resource. Send an independent, least-privilege Authorization: Bearer ak_pat_... token from your backend. Call GET /api/v2/third-party/capabilities first. Use UTC times or parse response offsets. For an asynchronous task, follow its terminal state; HTTP 200 does not prove a camera is online or a file exists.
POST /api/v2/third-party/channels/{channelId}/playback
Authorization: Bearer <backend API token>
Content-Type: application/json
{"protocols":["hls","http-flv"],"lifetimeSeconds":120}
The response sources[] contains short-lived URLs and expiresAt gives their deadline. Only an existing Online channel qualifies; the call does not silently start an offline source. Your backend checks the business user's channel rights before returning a URL to a player.
Connection, channels, live streams
| Endpoint | Grant | Input | Return and edge case |
|---|---|---|---|
GET /api/v2/third-party/capabilities |
Valid API token | None | Capability groups and support; verify the actual deployed version. |
GET /api/v2/third-party/media-servers |
nodes.view |
Optional clusterId |
Visible media nodes; node health is not channel state. |
GET /api/v2/third-party/channels |
channels.view |
page/pageSize, keyword, protocol, device/node/media node, desired/effective state filters |
{page,pageSize,total,rows[]}. Reuse stable channelId in later calls. |
GET /api/v2/third-party/channels/{channelId} |
channels.view |
Route ID | Channel state, protocol, media ownership; do not return a source URL with camera credentials to a frontend. |
POST /api/v2/third-party/channels/{channelId}/start |
channels.manage |
Route ID | {channel,command}. Accepted command is not Online; keep querying. |
POST /api/v2/third-party/channels/{channelId}/stop |
channels.manage |
Route ID | streamCommandId/nodeCommandId/state. Stopping can affect other viewers. |
GET /api/v2/third-party/streams |
streams.view |
mediaServerId, streamId, state |
Active stream sessions. A configured channel can have no live media. |
POST /api/v2/third-party/channels/{channelId}/playback |
streams.play |
ThirdPartyLivePlaybackRequest |
channelId/mediaServerId/vhost/app/streamId/streamState/expiresAt/sources[]; online only. |
POST /api/v2/third-party/channels/{channelId}/playback-lease |
streams.play |
ThirdPartyPlaybackLeaseRequest |
Stable sources[], leaseId, renewal times for longer playback without changing the player URL. |
Channel filters include mediaServerId/nodeId/deviceId/deviceChannelId/vhost/app/stream/streamId/enabled/autoVideo/autoRecord/noPlayerBreak/hasAudio/hasPtz/isShareChannel/desiredState/actualState/sourceUrl/keyword. sourceUrl is a filter, not a frontend playback URL. Use this version's OpenAPI for full types and nullable fields.
Recording files, links, deletion
| Endpoint | Grant | Input | Return and edge case |
|---|---|---|---|
GET /api/v2/third-party/recordings |
recordings.view |
Paging, channelId, node/media node, app/stream, state, time range |
{page,pageSize,total,rows[]} of authorized files; no physical server paths. |
POST /api/v2/third-party/recordings/{fileId}/playback-link |
recordings.play |
File ID, ThirdPartyMediaLinkRequest |
url/expiresAt/supportsRange for a short playback. |
POST /api/v2/third-party/recordings/{fileId}/download-link |
recordings.download |
Same | Short download address; play is not download permission. |
POST /api/v2/third-party/recordings/{fileId}/playback-lease |
recordings.play |
ThirdPartyPlaybackLeaseRequest |
Stable renewable URL. Deletion/revocation still ends access. |
POST /api/v2/third-party/recordings/soft-delete |
recordings.delete |
RecordFileBatchRequest.fileIds[] |
succeeded[]/failed[] per file. Soft-deleted files may be restored. |
POST /api/v2/third-party/recordings/restore |
recordings.manage |
Same | Restore index state; cannot recreate already removed bytes. |
POST /api/v2/third-party/recordings/hard-delete |
recordings.delete |
Same | Irreversible eligible-file deletion. Confirm scope and show per-item failures. |
Recording time filters locate files intersecting a range. To produce one result across several files or gaps, use cut/merge instead of joining server paths yourself.
Cut/merge tasks
| Endpoint | Grant | Input | Return and edge case |
|---|---|---|---|
GET /api/v2/third-party/cut-merge/tasks |
recordings.view |
Paging, mediaServerId/taskStatus/mainId |
Paged tasks and runtime status. |
POST /api/v2/third-party/cut-merge/tasks |
recordings.manage |
CutMergeRequest time range and stable channelId or stream locator; optional callbackUrl |
taskId/taskStatus/processPercentage; query until terminal. Gaps with no recording may be skipped. |
GET /api/v2/third-party/cut-merge/tasks/{taskId} |
recordings.view |
Task ID | Progress, size, actual duration, error, completion time. Link only after success. |
DELETE /api/v2/third-party/cut-merge/tasks/{taskId} |
recordings.delete |
Task ID, optional deleteOutputFile |
Delete task; output-file removal follows the option. |
POST /api/v2/third-party/cut-merge/tasks/{taskId}/playback-link |
recordings.play |
Task ID and ThirdPartyMediaLinkRequest |
Short play URL; unavailable before completion. |
POST /api/v2/third-party/cut-merge/tasks/{taskId}/download-link |
recordings.download |
Task ID and ThirdPartyMediaLinkRequest |
Short download URL; play grant is insufficient. |
POST /api/v2/third-party/cut-merge/tasks/{taskId}/playback-lease |
recordings.play |
ThirdPartyPlaybackLeaseRequest |
Renewable stable result address. |
CutMergeRequest.startTime/endTime must form a valid range. channelId is preferred for cross-media-node ownership; mediaServerId is only a compatibility fallback when matched files do not identify an execution node. Omit callbackUrl to poll; if supplied it must be a valid URL, and the task query remains the authoritative terminal result.
Playback leases and GB28181 replay
| Endpoint | Grant | Input | Return and edge case |
|---|---|---|---|
GET /api/v2/third-party/playback-leases/{leaseId} |
Same API token and original resource grant | Lease ID | state/expiresAt/renewAfter/absoluteExpiresAt/renewCount; another token cannot take it over. |
POST /api/v2/third-party/playback-leases/{leaseId}/renew |
Same | Optional new leaseSeconds |
URL stays fixed; sliding expiry moves but cannot exceed absolute expiry. |
DELETE /api/v2/third-party/playback-leases/{leaseId} |
Same | Lease ID, optional reason |
Revoke and invalidate old URL. |
POST /api/v2/third-party/gb28181/playback-sessions/{sessionId}/playback-lease |
streams.play |
Online GB playback session ID and lease request | Stable URL for that session. Establish Playback INVITE first. |
Use leaseId to query, renew, and revoke. resourceKind is live/recording-file/cut-merge-output; sources[] is the stable address returned at creation. renewAfter recommends when the backend should renew; expiresAt is current sliding expiry, absoluteExpiresAt the hard limit. Revocation of resource access cannot be bypassed by renewal.
Common request and response fields
| Model/field | Type and purpose | Default/constraint |
|---|---|---|
ThirdPartyLivePlaybackRequest.protocols |
string[]: http-flv/http-fmp4/hls |
Omit for all three; target must be online. |
ThirdPartyLivePlaybackRequest.lifetimeSeconds |
Short URL lifetime | Default 120; minimum 30, maximum from server configuration. |
ThirdPartyPlaybackLeaseRequest.leaseSeconds |
Sliding lease seconds | 60–600, default 120. |
ThirdPartyPlaybackLeaseRequest.absoluteLifetimeSeconds |
Maximum total lifetime | At least sliding lease, at most 43200 (12 hours). |
ThirdPartyMediaLinkRequest.lifetimeSeconds |
One-shot play/download URL seconds | Default 120. |
RenewThirdPartyPlaybackLeaseRequest.leaseSeconds |
New sliding interval | 60–600; omitted retains initial choice. |
RecordFileBatchRequest.fileIds |
File ID array | Per-item success or failure. |
ThirdPartyMediaLink |
resourceKind/resourceId/action/url/expiresAt/supportsRange |
Controlled HTTP URL, not file:// or a server directory. |
Typical failures: 401 invalid/revoked token, 403 insufficient grant/scope, 404 missing or invisible channel/file/task, 409 offline or conflicting state, 429 rate limit. Do not retry 403/404 without a state or grant change. If a task submission result is unknown, query by task ID before creating a duplicate. See RTC integration and archive integration for meeting-specific APIs.