[{"data":1,"prerenderedAt":1230},["ShallowReactive",2],{"/docs/base/jobs-base/media-providers":3,"/docs/base/jobs-base/media-providers-surround":1217,"/docs/base/jobs-base/media-providers-implemented-suggestions":1229},{"id":4,"title":5,"body":6,"description":1206,"extension":1207,"head":1208,"implementedSuggestions":1208,"meta":1209,"navigation":1210,"path":1212,"schemaOrg":1208,"seo":1213,"sitemap":1214,"stem":1215,"__hash__":1216},"docs/1.docs/base/2.jobs-base/3.media-providers.md","Media Providers",{"type":7,"value":8,"toc":1197},"minimark",[9,14,25,88,100,104,111,393,397,413,478,484,847,850,961,975,980,991,1054,1059,1068,1072,1075,1128,1136,1140,1190,1193],[10,11,13],"h2",{"id":12},"overview","Overview",[15,16,17,21,22,24],"p",{},[18,19,20],"code",{},"sky_jobs_base"," uses one shared media provider for tablet, gallery, camera, CCTV, speedcam, report, and bodycam uploads. FiveManage and Qbox CDN are included. A server resource can register another provider without modifying ",[18,23,20],{},".",[26,27,28,48],"table",{},[29,30,31],"thead",{},[32,33,34,38,42,45],"tr",{},[35,36,37],"th",{},"Provider",[35,39,41],{"align":40},"right","Browser upload URL",[35,43,44],{"align":40},"Server-side data URL upload",[35,46,47],{"align":40},"Delete remote file",[49,50,51,64,75],"tbody",{},[32,52,53,57,60,62],{},[54,55,56],"td",{},"FiveManage",[54,58,59],{"align":40},"Yes",[54,61,59],{"align":40},[54,63,59],{"align":40},[32,65,66,69,71,73],{},[54,67,68],{},"Qbox CDN",[54,70,59],{"align":40},[54,72,59],{"align":40},[54,74,59],{"align":40},[32,76,77,80,83,86],{},[54,78,79],{},"Custom adapter",[54,81,82],{"align":40},"Required for all NUI workflows",[54,84,85],{"align":40},"Required",[54,87,85],{"align":40},[89,90,93],"callout",{"color":91,"icon":92},"warning","i-lucide-shield-alert",[15,94,95,96,99],{},"API keys, webhook tokens, and other provider secrets must remain server-side. ",[18,97,98],{},"requestUploadUrl"," must return a temporary browser-safe URL that does not expose those secrets.",[10,101,103],{"id":102},"select-a-built-in-provider","Select a built-in provider",[15,105,106,107,110],{},"Configure the provider in ",[18,108,109],{},"sky_jobs_base/config/webhooks.lua",", then perform a full server restart.",[112,113,114,275],"tabs",{},[115,116,118,259],"tabs-item",{"icon":117,"label":56},"i-lucide-image-up",[119,120,125],"pre",{"className":121,"code":122,"filename":109,"language":123,"meta":124,"style":124},"language-lua shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","Webhooks = {\n    media = {\n        provider = \"fivemanage\",\n        providers = {}\n    },\n    fivemanage = {\n        apiKey = \"your_media_api_key_here\",\n        baseUrl = \"https://api.fivemanage.com/api/v3/file\",\n        timeoutMs = 10000\n    }\n}\n","lua","",[18,126,127,143,153,174,185,191,201,218,235,247,253],{"__ignoreMap":124},[128,129,132,136,140],"span",{"class":130,"line":131},"line",1,[128,133,135],{"class":134},"sTEyZ","Webhooks ",[128,137,139],{"class":138},"sMK4o","=",[128,141,142],{"class":134}," {\n",[128,144,146,149,151],{"class":130,"line":145},2,[128,147,148],{"class":134},"    media ",[128,150,139],{"class":138},[128,152,142],{"class":134},[128,154,156,159,161,164,168,171],{"class":130,"line":155},3,[128,157,158],{"class":134},"        provider ",[128,160,139],{"class":138},[128,162,163],{"class":138}," \"",[128,165,167],{"class":166},"sfazB","fivemanage",[128,169,170],{"class":138},"\"",[128,172,173],{"class":134},",\n",[128,175,177,180,182],{"class":130,"line":176},4,[128,178,179],{"class":134},"        providers ",[128,181,139],{"class":138},[128,183,184],{"class":134}," {}\n",[128,186,188],{"class":130,"line":187},5,[128,189,190],{"class":134},"    },\n",[128,192,194,197,199],{"class":130,"line":193},6,[128,195,196],{"class":134},"    fivemanage ",[128,198,139],{"class":138},[128,200,142],{"class":134},[128,202,204,207,209,211,214,216],{"class":130,"line":203},7,[128,205,206],{"class":134},"        apiKey ",[128,208,139],{"class":138},[128,210,163],{"class":138},[128,212,213],{"class":166},"your_media_api_key_here",[128,215,170],{"class":138},[128,217,173],{"class":134},[128,219,221,224,226,228,231,233],{"class":130,"line":220},8,[128,222,223],{"class":134},"        baseUrl ",[128,225,139],{"class":138},[128,227,163],{"class":138},[128,229,230],{"class":166},"https://api.fivemanage.com/api/v3/file",[128,232,170],{"class":138},[128,234,173],{"class":134},[128,236,238,241,243],{"class":130,"line":237},9,[128,239,240],{"class":134},"        timeoutMs ",[128,242,139],{"class":138},[128,244,246],{"class":245},"sbssI"," 10000\n",[128,248,250],{"class":130,"line":249},10,[128,251,252],{"class":134},"    }\n",[128,254,256],{"class":130,"line":255},11,[128,257,258],{"class":134},"}\n",[15,260,261,262,266,267,24],{},"Create a token with the ",[263,264,265],"strong",{},"Media"," permission. See the ",[268,269,274],"a",{"href":270,"rel":271,"target":273},"https://docs.fivemanage.com/guides/uploading-files/first-steps",[272],"nofollow","_blank","FiveManage upload guide",[115,276,278,381],{"icon":277,"label":68},"i-lucide-cloud",[119,279,281],{"className":121,"code":280,"filename":109,"language":123,"meta":124,"style":124},"Webhooks = {\n    media = {\n        provider = \"qbox\",\n        providers = {}\n    },\n    qbox = {\n        apiKey = \"qbox_live_abc123\",\n        baseUrl = \"https://api.qbox.re/v1/file\",\n        timeoutMs = 10000\n    }\n}\n",[18,282,283,291,299,314,322,326,335,350,365,373,377],{"__ignoreMap":124},[128,284,285,287,289],{"class":130,"line":131},[128,286,135],{"class":134},[128,288,139],{"class":138},[128,290,142],{"class":134},[128,292,293,295,297],{"class":130,"line":145},[128,294,148],{"class":134},[128,296,139],{"class":138},[128,298,142],{"class":134},[128,300,301,303,305,307,310,312],{"class":130,"line":155},[128,302,158],{"class":134},[128,304,139],{"class":138},[128,306,163],{"class":138},[128,308,309],{"class":166},"qbox",[128,311,170],{"class":138},[128,313,173],{"class":134},[128,315,316,318,320],{"class":130,"line":176},[128,317,179],{"class":134},[128,319,139],{"class":138},[128,321,184],{"class":134},[128,323,324],{"class":130,"line":187},[128,325,190],{"class":134},[128,327,328,331,333],{"class":130,"line":193},[128,329,330],{"class":134},"    qbox ",[128,332,139],{"class":138},[128,334,142],{"class":134},[128,336,337,339,341,343,346,348],{"class":130,"line":203},[128,338,206],{"class":134},[128,340,139],{"class":138},[128,342,163],{"class":138},[128,344,345],{"class":166},"qbox_live_abc123",[128,347,170],{"class":138},[128,349,173],{"class":134},[128,351,352,354,356,358,361,363],{"class":130,"line":220},[128,353,223],{"class":134},[128,355,139],{"class":138},[128,357,163],{"class":138},[128,359,360],{"class":166},"https://api.qbox.re/v1/file",[128,362,170],{"class":138},[128,364,173],{"class":134},[128,366,367,369,371],{"class":130,"line":237},[128,368,240],{"class":134},[128,370,139],{"class":138},[128,372,246],{"class":245},[128,374,375],{"class":130,"line":249},[128,376,252],{"class":134},[128,378,379],{"class":130,"line":255},[128,380,258],{"class":134},[15,382,383,384,387,388,24],{},"The Qbox key may be stored directly or with the ",[18,385,386],{},"Bearer "," prefix. See the ",[268,389,392],{"href":390,"rel":391,"target":273},"https://docs.qbox.re/dashboard/cdn",[272],"Qbox CDN documentation",[10,394,396],{"id":395},"register-a-custom-provider","Register a custom provider",[15,398,399,400,402,403,406,407,409,410,412],{},"Create a server resource for the adapter and make ",[18,401,20],{}," its dependency. Provider names must match ",[18,404,405],{},"^[a-z][a-z0-9_%-]*$",". The built-in names ",[18,408,167],{}," and ",[18,411,309],{}," are reserved.",[119,414,417],{"className":121,"code":415,"filename":416,"language":123,"meta":124,"style":124},"fx_version \"cerulean\"\ngame \"gta5\"\n\nserver_script \"server.lua\"\n\ndependency \"sky_jobs_base\"\n","fxmanifest.lua",[18,418,419,433,445,451,463,467],{"__ignoreMap":124},[128,420,421,425,427,430],{"class":130,"line":131},[128,422,424],{"class":423},"s2Zo4","fx_version",[128,426,163],{"class":138},[128,428,429],{"class":166},"cerulean",[128,431,432],{"class":138},"\"\n",[128,434,435,438,440,443],{"class":130,"line":145},[128,436,437],{"class":423},"game",[128,439,163],{"class":138},[128,441,442],{"class":166},"gta5",[128,444,432],{"class":138},[128,446,447],{"class":130,"line":155},[128,448,450],{"emptyLinePlaceholder":449},true,"\n",[128,452,453,456,458,461],{"class":130,"line":176},[128,454,455],{"class":423},"server_script",[128,457,163],{"class":138},[128,459,460],{"class":166},"server.lua",[128,462,432],{"class":138},[128,464,465],{"class":130,"line":187},[128,466,450],{"emptyLinePlaceholder":449},[128,468,469,472,474,476],{"class":130,"line":193},[128,470,471],{"class":423},"dependency",[128,473,163],{"class":138},[128,475,20],{"class":166},[128,477,432],{"class":138},[15,479,480,481,483],{},"Register the adapter from ",[18,482,460],{},":",[119,485,487],{"className":121,"code":486,"filename":460,"language":123,"meta":124,"style":124},"local function request_upload_url(config, options)\n    -- Authenticate against your provider on the server and create a\n    -- temporary browser-safe upload URL.\n    return true, {\n        presignedUrl = \"https://uploads.example.com/presigned-token\",\n        expiresIn = 300\n    }\nend\n\nlocal function upload_data_url(config, data_url, options)\n    -- Decode/upload the data URL through your provider's server API.\n    return true, {\n        url = \"https://cdn.example.com/example.png\",\n        id = \"provider-file-id\"\n    }\nend\n\nlocal function delete_file(config, file_id, options)\n    -- Delete the provider object identified by file_id.\n    return true\nend\n\nlocal registration = exports[\"sky_jobs_base\"]:registerMediaProvider(\"my_provider\", {\n    requestUploadUrl = request_upload_url,\n    uploadDataUrl = upload_data_url,\n    deleteFile = delete_file\n})\n\nif not registration.success then\n    error((\"Could not register media provider: %s\"):format(registration.error))\nend\n",[18,488,489,517,523,528,539,555,565,569,574,578,602,607,616,633,648,653,658,663,688,694,702,707,712,748,759,770,781,787,792,811,842],{"__ignoreMap":124},[128,490,491,494,498,501,504,508,511,514],{"class":130,"line":131},[128,492,493],{"class":138},"local",[128,495,497],{"class":496},"s7zQu"," function",[128,499,500],{"class":423}," request_upload_url",[128,502,503],{"class":138},"(",[128,505,507],{"class":506},"sHdIc","config",[128,509,510],{"class":138},",",[128,512,513],{"class":506}," options",[128,515,516],{"class":138},")\n",[128,518,519],{"class":130,"line":145},[128,520,522],{"class":521},"sHwdD","    -- Authenticate against your provider on the server and create a\n",[128,524,525],{"class":130,"line":155},[128,526,527],{"class":521},"    -- temporary browser-safe upload URL.\n",[128,529,530,533,536],{"class":130,"line":176},[128,531,532],{"class":496},"    return",[128,534,535],{"class":138}," true",[128,537,538],{"class":134},", {\n",[128,540,541,544,546,548,551,553],{"class":130,"line":187},[128,542,543],{"class":134},"        presignedUrl ",[128,545,139],{"class":138},[128,547,163],{"class":138},[128,549,550],{"class":166},"https://uploads.example.com/presigned-token",[128,552,170],{"class":138},[128,554,173],{"class":134},[128,556,557,560,562],{"class":130,"line":193},[128,558,559],{"class":134},"        expiresIn ",[128,561,139],{"class":138},[128,563,564],{"class":245}," 300\n",[128,566,567],{"class":130,"line":203},[128,568,252],{"class":134},[128,570,571],{"class":130,"line":220},[128,572,573],{"class":496},"end\n",[128,575,576],{"class":130,"line":237},[128,577,450],{"emptyLinePlaceholder":449},[128,579,580,582,584,587,589,591,593,596,598,600],{"class":130,"line":249},[128,581,493],{"class":138},[128,583,497],{"class":496},[128,585,586],{"class":423}," upload_data_url",[128,588,503],{"class":138},[128,590,507],{"class":506},[128,592,510],{"class":138},[128,594,595],{"class":506}," data_url",[128,597,510],{"class":138},[128,599,513],{"class":506},[128,601,516],{"class":138},[128,603,604],{"class":130,"line":255},[128,605,606],{"class":521},"    -- Decode/upload the data URL through your provider's server API.\n",[128,608,610,612,614],{"class":130,"line":609},12,[128,611,532],{"class":496},[128,613,535],{"class":138},[128,615,538],{"class":134},[128,617,619,622,624,626,629,631],{"class":130,"line":618},13,[128,620,621],{"class":134},"        url ",[128,623,139],{"class":138},[128,625,163],{"class":138},[128,627,628],{"class":166},"https://cdn.example.com/example.png",[128,630,170],{"class":138},[128,632,173],{"class":134},[128,634,636,639,641,643,646],{"class":130,"line":635},14,[128,637,638],{"class":134},"        id ",[128,640,139],{"class":138},[128,642,163],{"class":138},[128,644,645],{"class":166},"provider-file-id",[128,647,432],{"class":138},[128,649,651],{"class":130,"line":650},15,[128,652,252],{"class":134},[128,654,656],{"class":130,"line":655},16,[128,657,573],{"class":496},[128,659,661],{"class":130,"line":660},17,[128,662,450],{"emptyLinePlaceholder":449},[128,664,666,668,670,673,675,677,679,682,684,686],{"class":130,"line":665},18,[128,667,493],{"class":138},[128,669,497],{"class":496},[128,671,672],{"class":423}," delete_file",[128,674,503],{"class":138},[128,676,507],{"class":506},[128,678,510],{"class":138},[128,680,681],{"class":506}," file_id",[128,683,510],{"class":138},[128,685,513],{"class":506},[128,687,516],{"class":138},[128,689,691],{"class":130,"line":690},19,[128,692,693],{"class":521},"    -- Delete the provider object identified by file_id.\n",[128,695,697,699],{"class":130,"line":696},20,[128,698,532],{"class":496},[128,700,701],{"class":138}," true\n",[128,703,705],{"class":130,"line":704},21,[128,706,573],{"class":496},[128,708,710],{"class":130,"line":709},22,[128,711,450],{"emptyLinePlaceholder":449},[128,713,715,717,720,722,725,727,729,731,734,737,739,741,744,746],{"class":130,"line":714},23,[128,716,493],{"class":138},[128,718,719],{"class":134}," registration ",[128,721,139],{"class":138},[128,723,724],{"class":134}," exports[",[128,726,170],{"class":138},[128,728,20],{"class":166},[128,730,170],{"class":138},[128,732,733],{"class":134},"]:",[128,735,736],{"class":423},"registerMediaProvider",[128,738,503],{"class":134},[128,740,170],{"class":138},[128,742,743],{"class":166},"my_provider",[128,745,170],{"class":138},[128,747,538],{"class":134},[128,749,751,754,756],{"class":130,"line":750},24,[128,752,753],{"class":134},"    requestUploadUrl ",[128,755,139],{"class":138},[128,757,758],{"class":134}," request_upload_url,\n",[128,760,762,765,767],{"class":130,"line":761},25,[128,763,764],{"class":134},"    uploadDataUrl ",[128,766,139],{"class":138},[128,768,769],{"class":134}," upload_data_url,\n",[128,771,773,776,778],{"class":130,"line":772},26,[128,774,775],{"class":134},"    deleteFile ",[128,777,139],{"class":138},[128,779,780],{"class":134}," delete_file\n",[128,782,784],{"class":130,"line":783},27,[128,785,786],{"class":134},"})\n",[128,788,790],{"class":130,"line":789},28,[128,791,450],{"emptyLinePlaceholder":449},[128,793,795,798,801,804,808],{"class":130,"line":794},29,[128,796,797],{"class":496},"if",[128,799,800],{"class":138}," not",[128,802,803],{"class":134}," registration.",[128,805,807],{"class":806},"sBMFI","success",[128,809,810],{"class":496}," then\n",[128,812,814,817,820,822,825,827,830,833,836,839],{"class":130,"line":813},30,[128,815,816],{"class":423},"    error",[128,818,819],{"class":134},"((",[128,821,170],{"class":138},[128,823,824],{"class":166},"Could not register media provider: %s",[128,826,170],{"class":138},[128,828,829],{"class":134},"):",[128,831,832],{"class":423},"format",[128,834,835],{"class":134},"(registration.",[128,837,838],{"class":806},"error",[128,840,841],{"class":134},"))\n",[128,843,845],{"class":130,"line":844},31,[128,846,573],{"class":496},[15,848,849],{},"Add its private configuration and select it:",[119,851,853],{"className":121,"code":852,"filename":109,"language":123,"meta":124,"style":124},"Webhooks = {\n    media = {\n        provider = \"my_provider\",\n        providers = {\n            my_provider = {\n                apiKey = \"server-side-secret\",\n                baseUrl = \"https://api.example.com/files\",\n                timeoutMs = 10000\n            }\n        }\n    }\n}\n",[18,854,855,863,871,885,893,902,918,934,943,948,953,957],{"__ignoreMap":124},[128,856,857,859,861],{"class":130,"line":131},[128,858,135],{"class":134},[128,860,139],{"class":138},[128,862,142],{"class":134},[128,864,865,867,869],{"class":130,"line":145},[128,866,148],{"class":134},[128,868,139],{"class":138},[128,870,142],{"class":134},[128,872,873,875,877,879,881,883],{"class":130,"line":155},[128,874,158],{"class":134},[128,876,139],{"class":138},[128,878,163],{"class":138},[128,880,743],{"class":166},[128,882,170],{"class":138},[128,884,173],{"class":134},[128,886,887,889,891],{"class":130,"line":176},[128,888,179],{"class":134},[128,890,139],{"class":138},[128,892,142],{"class":134},[128,894,895,898,900],{"class":130,"line":187},[128,896,897],{"class":134},"            my_provider ",[128,899,139],{"class":138},[128,901,142],{"class":134},[128,903,904,907,909,911,914,916],{"class":130,"line":193},[128,905,906],{"class":134},"                apiKey ",[128,908,139],{"class":138},[128,910,163],{"class":138},[128,912,913],{"class":166},"server-side-secret",[128,915,170],{"class":138},[128,917,173],{"class":134},[128,919,920,923,925,927,930,932],{"class":130,"line":203},[128,921,922],{"class":134},"                baseUrl ",[128,924,139],{"class":138},[128,926,163],{"class":138},[128,928,929],{"class":166},"https://api.example.com/files",[128,931,170],{"class":138},[128,933,173],{"class":134},[128,935,936,939,941],{"class":130,"line":220},[128,937,938],{"class":134},"                timeoutMs ",[128,940,139],{"class":138},[128,942,246],{"class":245},[128,944,945],{"class":130,"line":237},[128,946,947],{"class":134},"            }\n",[128,949,950],{"class":130,"line":249},[128,951,952],{"class":134},"        }\n",[128,954,955],{"class":130,"line":255},[128,956,252],{"class":134},[128,958,959],{"class":130,"line":609},[128,960,258],{"class":134},[15,962,963,964,966,967,970,971,974],{},"The adapter receives the ",[18,965,743],{}," configuration as its first argument. The options table contains trusted server-side options such as ",[18,968,969],{},"filename",", ",[18,972,973],{},"path",", or an explicitly selected provider.",[976,977,979],"h3",{"id":978},"adapter-contract","Adapter contract",[15,981,982,983,986,987,990],{},"Every method returns ",[18,984,985],{},"true, data"," on success or ",[18,988,989],{},"false, errorCode"," on failure.",[26,992,993,1006],{},[29,994,995],{},[32,996,997,1000,1003],{},[35,998,999],{},"Method",[35,1001,1002],{},"Success data",[35,1004,1005],{},"Purpose",[49,1007,1008,1023,1038],{},[32,1009,1010,1015,1020],{},[54,1011,1012],{},[18,1013,1014],{},"requestUploadUrl(config, options)",[54,1016,1017],{},[18,1018,1019],{},"{ presignedUrl, expiresIn? }",[54,1021,1022],{},"Creates the browser-safe upload URL used by NUI uploads.",[32,1024,1025,1030,1035],{},[54,1026,1027],{},[18,1028,1029],{},"uploadDataUrl(config, dataUrl, options)",[54,1031,1032],{},[18,1033,1034],{},"{ url, id? }",[54,1036,1037],{},"Uploads base64 data from a trusted server workflow.",[32,1039,1040,1045,1048],{},[54,1041,1042],{},[18,1043,1044],{},"deleteFile(config, fileId, options)",[54,1046,1047],{},"No data required",[54,1049,1050,1051,24],{},"Deletes the provider object stored under ",[18,1052,1053],{},"fileId",[15,1055,1056,1058],{},[18,1057,20],{}," validates and normalizes successful results. The selected provider name and timeout are added automatically.",[89,1060,1062],{"color":91,"icon":1061},"i-lucide-triangle-alert",[15,1063,1064,1065,24],{},"A provider without a browser-safe upload URL is not compatible with all existing tablet and report workflows. Never return a Discord webhook URL, API endpoint containing credentials, or another reusable secret as ",[18,1066,1067],{},"presignedUrl",[10,1069,1071],{"id":1070},"server-exports","Server exports",[15,1073,1074],{},"The normalized media operations are also available to trusted server resources:",[26,1076,1077,1086],{},[29,1078,1079],{},[32,1080,1081,1084],{},[35,1082,1083],{},"Export",[35,1085,1005],{},[49,1087,1088,1098,1108,1118],{},[32,1089,1090,1095],{},[54,1091,1092],{},[18,1093,1094],{},"getMediaUploadUrl()",[54,1096,1097],{},"Requests an upload URL from the selected provider.",[32,1099,1100,1105],{},[54,1101,1102],{},[18,1103,1104],{},"uploadMediaDataUrl(dataUrl, options?)",[54,1106,1107],{},"Uploads a server-side base64 data URL.",[32,1109,1110,1115],{},[54,1111,1112],{},[18,1113,1114],{},"deleteMediaFile(fileId, options?)",[54,1116,1117],{},"Deletes a remote file.",[32,1119,1120,1125],{},[54,1121,1122],{},[18,1123,1124],{},"registerMediaProvider(name, adapter)",[54,1126,1127],{},"Registers or replaces a custom adapter.",[15,1129,1130,1131,1135],{},"See ",[268,1132,1134],{"href":1133},"/docs/base/jobs-base/server-exports#gallery","Server Exports"," for return values and examples.",[10,1137,1139],{"id":1138},"troubleshooting","Troubleshooting",[1141,1142,1143,1153,1164,1170,1181],"ul",{},[1144,1145,1146,1149,1150,1152],"li",{},[18,1147,1148],{},"media_provider_not_registered",": the adapter resource did not start, started before ",[18,1151,20],{},", or used a different provider name.",[1144,1154,1155,1158,1159,1161,1162,24],{},[18,1156,1157],{},"provider_name_reserved",": the adapter attempted to register as ",[18,1160,167],{}," or ",[18,1163,309],{},[1144,1165,1166,1169],{},[18,1167,1168],{},"missing_adapter_method_*",": one of the three required adapter methods is missing.",[1144,1171,1172,1175,1176,1178,1179,24],{},[18,1173,1174],{},"missing_presigned_url",": ",[18,1177,98],{}," did not return a non-empty ",[18,1180,1067],{},[1144,1182,1183,1175,1186,1189],{},[18,1184,1185],{},"missing_url",[18,1187,1188],{},"uploadDataUrl"," did not return the final public file URL.",[15,1191,1192],{},"After changing the provider, its configuration, or resource start order, perform a full server restart and test upload plus deletion before players connect.",[1194,1195,1196],"style",{},"html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}",{"title":124,"searchDepth":131,"depth":145,"links":1198},[1199,1200,1201,1204,1205],{"id":12,"depth":145,"text":13},{"id":102,"depth":145,"text":103},{"id":395,"depth":145,"text":396,"children":1202},[1203],{"id":978,"depth":155,"text":979},{"id":1070,"depth":145,"text":1071},{"id":1138,"depth":145,"text":1139},"Configure FiveManage, Qbox CDN, or register a custom media provider for tablet, gallery, camera, CCTV, speedcam, and bodycam uploads.","md",null,{},{"icon":1211},"i-lucide-cloud-upload","/docs/base/jobs-base/media-providers",{"title":5,"description":1206},{"loc":1212},"1.docs/base/2.jobs-base/3.media-providers","gz-wGBGnxHT0GeeCNUgI6sbQKv_MDH5NWnW-lVC7R_8",[1218,1224],{"title":1219,"path":1220,"stem":1221,"description":1222,"icon":1223,"children":-1},"Client Exports","/docs/base/jobs-base/client-exports","1.docs/base/2.jobs-base/2.client-exports","Client-side exports provided by sky_jobs_base for radial menu, dispatch, and storage interactions.","i-lucide-monitor",{"title":1134,"path":1225,"stem":1226,"description":1227,"icon":1228,"children":-1},"/docs/base/jobs-base/server-exports","1.docs/base/2.jobs-base/3.server-exports","Server-side exports provided by sky_jobs_base for dispatch, tablet app registration, and more.","i-lucide-server",[],1785795425694]