Browse docs

Media Providers

Configure FiveManage, Qbox CDN, or register a custom media provider for tablet, gallery, camera, CCTV, speedcam, and bodycam uploads.

Overview

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 sky_jobs_base.

ProviderBrowser upload URLServer-side data URL uploadDelete remote file
FiveManageYesYesYes
Qbox CDNYesYesYes
Custom adapterRequired for all NUI workflowsRequiredRequired
API keys, webhook tokens, and other provider secrets must remain server-side. requestUploadUrl must return a temporary browser-safe URL that does not expose those secrets.

Select a built-in provider

Configure the provider in sky_jobs_base/config/webhooks.lua, then perform a full server restart.

sky_jobs_base/config/webhooks.lua
Webhooks = {
    media = {
        provider = "fivemanage",
        providers = {}
    },
    fivemanage = {
        apiKey = "your_media_api_key_here",
        baseUrl = "https://api.fivemanage.com/api/v3/file",
        timeoutMs = 10000
    }
}

Create a token with the Media permission. See the FiveManage upload guide.

Register a custom provider

Create a server resource for the adapter and make sky_jobs_base its dependency. Provider names must match ^[a-z][a-z0-9_%-]*$. The built-in names fivemanage and qbox are reserved.

fxmanifest.lua
fx_version "cerulean"
game "gta5"

server_script "server.lua"

dependency "sky_jobs_base"

Register the adapter from server.lua:

server.lua
local function request_upload_url(config, options)
    -- Authenticate against your provider on the server and create a
    -- temporary browser-safe upload URL.
    return true, {
        presignedUrl = "https://uploads.example.com/presigned-token",
        expiresIn = 300
    }
end

local function upload_data_url(config, data_url, options)
    -- Decode/upload the data URL through your provider's server API.
    return true, {
        url = "https://cdn.example.com/example.png",
        id = "provider-file-id"
    }
end

local function delete_file(config, file_id, options)
    -- Delete the provider object identified by file_id.
    return true
end

local registration = exports["sky_jobs_base"]:registerMediaProvider("my_provider", {
    requestUploadUrl = request_upload_url,
    uploadDataUrl = upload_data_url,
    deleteFile = delete_file
})

if not registration.success then
    error(("Could not register media provider: %s"):format(registration.error))
end

Add its private configuration and select it:

sky_jobs_base/config/webhooks.lua
Webhooks = {
    media = {
        provider = "my_provider",
        providers = {
            my_provider = {
                apiKey = "server-side-secret",
                baseUrl = "https://api.example.com/files",
                timeoutMs = 10000
            }
        }
    }
}

The adapter receives the my_provider configuration as its first argument. The options table contains trusted server-side options such as filename, path, or an explicitly selected provider.

Adapter contract

Every method returns true, data on success or false, errorCode on failure.

MethodSuccess dataPurpose
requestUploadUrl(config, options){ presignedUrl, expiresIn? }Creates the browser-safe upload URL used by NUI uploads.
uploadDataUrl(config, dataUrl, options){ url, id? }Uploads base64 data from a trusted server workflow.
deleteFile(config, fileId, options)No data requiredDeletes the provider object stored under fileId.

sky_jobs_base validates and normalizes successful results. The selected provider name and timeout are added automatically.

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 presignedUrl.

Server exports

The normalized media operations are also available to trusted server resources:

ExportPurpose
getMediaUploadUrl()Requests an upload URL from the selected provider.
uploadMediaDataUrl(dataUrl, options?)Uploads a server-side base64 data URL.
deleteMediaFile(fileId, options?)Deletes a remote file.
registerMediaProvider(name, adapter)Registers or replaces a custom adapter.

See Server Exports for return values and examples.

Troubleshooting

  • media_provider_not_registered: the adapter resource did not start, started before sky_jobs_base, or used a different provider name.
  • provider_name_reserved: the adapter attempted to register as fivemanage or qbox.
  • missing_adapter_method_*: one of the three required adapter methods is missing.
  • missing_presigned_url: requestUploadUrl did not return a non-empty presignedUrl.
  • missing_url: uploadDataUrl did not return the final public file URL.

After changing the provider, its configuration, or resource start order, perform a full server restart and test upload plus deletion before players connect.