POST https://api.sonorancad.com/v2/general/bodycam-recordings/external
Rate limit: 30 requests per minute per API key, shared with bodycam uploads.
Register a hosted video URL under a community member’s bodycam recordings. The clip can then be selected in a custom record.
Sonoran CAD saves the URL, without downloading the video. External clip entries do not expire or use your daily recording allowance. The video must remain available at that URL; attaching it to a record does not preserve the file. Clips uploaded to Sonoran CAD still expire after 24 hours.
Request
Sendapplication/json with Authorization: Bearer YOUR_API_KEY. The API key determines the community.
| Field | Type | Required | Description |
|---|---|---|---|
fileUrl | string | Yes | Absolute HTTPS URL to a playable video file, not a webpage. Maximum 8,192 characters; embedded credentials are not allowed. |
accountUuid | string (UUID) | One target | Recording owner’s account UUID. |
communityUserId | string | One target | Recording owner’s community user ID. |
roblox | string | One target | Roblox user ID linked to the recording owner’s account. |
discord | string | One target | Discord user ID linked to the recording owner’s account. |
durationMs | integer | No | Nonnegative duration in milliseconds. Defaults to 0 (unknown). |
identId | integer | No | Nonnegative identifier ID owned by the target account. Defaults to its selected identifier, when available. |
unitNumber | string | No | Unit number; defaults to the resolved identifier’s unit number. Maximum 255 characters. |
unitLocation | string | No | Recording location. Maximum 2,000 characters. |
originalFileName | string | No | Filename saved with the clip; defaults to the URL’s filename. Maximum 255 characters. |
mimeType | string | No | Video MIME type, such as video/mp4. Inferred from recognized URL extensions when omitted. Maximum 100 characters. |
accountUuid, communityUserId, roblox, or discord. The target must already belong to the community. Use a stable URL that viewers can access without additional sign-in.
Example Request
The SDKs do not yet include a helper for this endpoint. These examples send JSON directly over HTTP.- Sonoran.lua
- Sonoran.js
- Sonoran.py
- Sonoran.Net
- OpenAPI
- cURL
-- Standalone Lua: luarocks install luasec; luarocks install lua-cjson
local https = require("ssl.https")
local ltn12 = require("ltn12")
local json = require("cjson")
local body = json.encode({
accountUuid = "USER_ACCOUNT_UUID",
fileUrl = "https://clips.example.com/chase.mp4",
durationMs = 90000
})
local response = {}
local _, status = https.request({
url = "https://api.sonorancad.com/v2/general/bodycam-recordings/external",
method = "POST",
headers = {
["Authorization"] = "Bearer YOUR_API_KEY",
["Content-Type"] = "application/json",
["Content-Length"] = tostring(#body)
},
source = ltn12.source.string(body),
sink = ltn12.sink.table(response)
})
print(status, table.concat(response))
// Node.js 18+; uses the built-in fetch API.
const response = await fetch(
'https://api.sonorancad.com/v2/general/bodycam-recordings/external',
{
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
accountUuid: 'USER_ACCOUNT_UUID',
fileUrl: 'https://clips.example.com/chase.mp4',
durationMs: 90000
})
}
);
console.log(response.status, await response.json());
import json
import urllib.request
request = urllib.request.Request(
"https://api.sonorancad.com/v2/general/bodycam-recordings/external",
method="POST",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
data=json.dumps({
"accountUuid": "USER_ACCOUNT_UUID",
"fileUrl": "https://clips.example.com/chase.mp4",
"durationMs": 90000,
}).encode("utf-8"),
)
with urllib.request.urlopen(request) as response:
print(response.status, json.load(response))
// .NET 6+; uses HttpClient.
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "YOUR_API_KEY");
using var response = await client.PostAsJsonAsync(
"https://api.sonorancad.com/v2/general/bodycam-recordings/external",
new
{
accountUuid = "USER_ACCOUNT_UUID",
fileUrl = "https://clips.example.com/chase.mp4",
durationMs = 90000
});
Console.WriteLine((int)response.StatusCode);
Console.WriteLine(await response.Content.ReadAsStringAsync());
Import this YAML into Postman with Import → Raw text.
openapi: 3.0.3
info:
title: Sonoran CAD v2 - Register External Bodycam Recording
version: 1.0.0
servers:
- url: https://api.sonorancad.com
paths:
/v2/general/bodycam-recordings/external:
post:
summary: Register External Bodycam Recording
operationId: registerExternalBodycamRecording
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [fileUrl]
oneOf:
- required: [accountUuid]
- required: [communityUserId]
- required: [roblox]
- required: [discord]
properties:
fileUrl:
type: string
format: uri
pattern: '^https://'
maxLength: 8192
accountUuid:
type: string
format: uuid
communityUserId:
type: string
roblox:
type: string
discord:
type: string
durationMs:
type: integer
format: int64
minimum: 0
default: 0
identId:
type: integer
minimum: 0
maximum: 2147483647
unitNumber:
type: string
maxLength: 255
unitLocation:
type: string
maxLength: 2000
originalFileName:
type: string
maxLength: 255
mimeType:
type: string
pattern: '^video/[a-zA-Z0-9.+-]+$'
maxLength: 100
example:
accountUuid: 00000000-0000-4000-8000-000000000001
fileUrl: https://clips.example.com/chase.mp4
durationMs: 90000
responses:
'201':
description: Recording metadata created; expiresAt is null.
content:
application/json:
schema:
type: object
properties:
id:
type: string
format: uuid
fileUrl:
type: string
format: uri
source:
type: string
enum: [external]
expiresAt:
type: string
format: date-time
nullable: true
'400':
description: Invalid URL, target identifiers, identifier ownership, or metadata.
'401':
description: Missing or invalid API key.
'404':
description: Target account not found or not a member of this community.
'429':
description: Rate limit exceeded.
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
curl --request POST \
--url 'https://api.sonorancad.com/v2/general/bodycam-recordings/external' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"accountUuid": "USER_ACCOUNT_UUID",
"fileUrl": "https://clips.example.com/chase.mp4",
"durationMs": 90000
}'
Response
Returns201 Created with the recording metadata:
{
"id": "00000000-0000-4000-8000-000000000002",
"communityUuid": "00000000-0000-4000-8000-000000000003",
"accountUuid": "00000000-0000-4000-8000-000000000001",
"username": "OfficerExample",
"identId": 123,
"unitNumber": "1A-12",
"unitLocation": "",
"originalFileName": "chase.mp4",
"mimeType": "video/mp4",
"fileSizeBytes": 0,
"durationMs": 90000,
"fileUrl": "https://clips.example.com/chase.mp4",
"s3Key": "",
"createdAt": "2026-10-30T12:00:00Z",
"expiresAt": null,
"source": "external"
}
Errors
| Status | Cause |
|---|---|
400 | Invalid HTTPS URL, missing or multiple target identifiers, invalid metadata, or an identifier belonging to another account. |
401 | Missing or invalid API key. |
404 | Target account not found or not a member of this community. |
429 | Rate limit exceeded. |

