Configure Azure Blob Storage
curl --request POST \
--url https://api.tornadoapi.io/user/blob \
--header 'Content-Type: application/json' \
--header 'x-api-key: <x-api-key>' \
--data '
{
"account_name": "<string>",
"container": "<string>",
"account_key": "<string>",
"sas_token": "<string>",
"folder_prefix": "<string>",
"base_folder": "<string>"
}
'import requests
url = "https://api.tornadoapi.io/user/blob"
payload = {
"account_name": "<string>",
"container": "<string>",
"account_key": "<string>",
"sas_token": "<string>",
"folder_prefix": "<string>",
"base_folder": "<string>"
}
headers = {
"x-api-key": "<x-api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<x-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
account_name: '<string>',
container: '<string>',
account_key: '<string>',
sas_token: '<string>',
folder_prefix: '<string>',
base_folder: '<string>'
})
};
fetch('https://api.tornadoapi.io/user/blob', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.tornadoapi.io/user/blob",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'account_name' => '<string>',
'container' => '<string>',
'account_key' => '<string>',
'sas_token' => '<string>',
'folder_prefix' => '<string>',
'base_folder' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <x-api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.tornadoapi.io/user/blob"
payload := strings.NewReader("{\n \"account_name\": \"<string>\",\n \"container\": \"<string>\",\n \"account_key\": \"<string>\",\n \"sas_token\": \"<string>\",\n \"folder_prefix\": \"<string>\",\n \"base_folder\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<x-api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.tornadoapi.io/user/blob")
.header("x-api-key", "<x-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"account_name\": \"<string>\",\n \"container\": \"<string>\",\n \"account_key\": \"<string>\",\n \"sas_token\": \"<string>\",\n \"folder_prefix\": \"<string>\",\n \"base_folder\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tornadoapi.io/user/blob")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<x-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"account_name\": \"<string>\",\n \"container\": \"<string>\",\n \"account_key\": \"<string>\",\n \"sas_token\": \"<string>\",\n \"folder_prefix\": \"<string>\",\n \"base_folder\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"message": "Azure Blob storage configured successfully",
"provider": "blob",
"container_or_bucket": "tornado-downloads"
}
User
Configure Azure Blob Storage
Configure Azure Blob Storage for your downloads
POST
/
user
/
blob
Configure Azure Blob Storage
curl --request POST \
--url https://api.tornadoapi.io/user/blob \
--header 'Content-Type: application/json' \
--header 'x-api-key: <x-api-key>' \
--data '
{
"account_name": "<string>",
"container": "<string>",
"account_key": "<string>",
"sas_token": "<string>",
"folder_prefix": "<string>",
"base_folder": "<string>"
}
'import requests
url = "https://api.tornadoapi.io/user/blob"
payload = {
"account_name": "<string>",
"container": "<string>",
"account_key": "<string>",
"sas_token": "<string>",
"folder_prefix": "<string>",
"base_folder": "<string>"
}
headers = {
"x-api-key": "<x-api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<x-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
account_name: '<string>',
container: '<string>',
account_key: '<string>',
sas_token: '<string>',
folder_prefix: '<string>',
base_folder: '<string>'
})
};
fetch('https://api.tornadoapi.io/user/blob', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.tornadoapi.io/user/blob",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'account_name' => '<string>',
'container' => '<string>',
'account_key' => '<string>',
'sas_token' => '<string>',
'folder_prefix' => '<string>',
'base_folder' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <x-api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.tornadoapi.io/user/blob"
payload := strings.NewReader("{\n \"account_name\": \"<string>\",\n \"container\": \"<string>\",\n \"account_key\": \"<string>\",\n \"sas_token\": \"<string>\",\n \"folder_prefix\": \"<string>\",\n \"base_folder\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<x-api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.tornadoapi.io/user/blob")
.header("x-api-key", "<x-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"account_name\": \"<string>\",\n \"container\": \"<string>\",\n \"account_key\": \"<string>\",\n \"sas_token\": \"<string>\",\n \"folder_prefix\": \"<string>\",\n \"base_folder\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.tornadoapi.io/user/blob")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<x-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"account_name\": \"<string>\",\n \"container\": \"<string>\",\n \"account_key\": \"<string>\",\n \"sas_token\": \"<string>\",\n \"folder_prefix\": \"<string>\",\n \"base_folder\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"message": "Azure Blob storage configured successfully",
"provider": "blob",
"container_or_bucket": "tornado-downloads"
}
Overview
Set up Azure Blob Storage for uploaded videos. Authenticate with either an account key or a SAS token. Credentials are verified before saving.Header Parameters
string
required
Your API key for authentication
Request Body
string
required
Azure Storage Account name
string
required
Blob container name
string
Storage Account access key (Base64 encoded). Required if
sas_token is not provided.string
SAS token for authentication. Required if
account_key is not provided.string
Optional folder prefix for organizing uploads (e.g.,
downloads/2024/)string
default:"videos"
Base folder name for uploaded files. Defaults to
videos if not specified. Set to a custom value to change the top-level folder where files are stored (e.g., downloads, media).Provide either
account_key OR sas_token, not both. At least one must be provided.Response
string
Success confirmation message
string
Storage provider type:
blobstring
The configured container name
string
The configured folder prefix (if provided)
Examples
curl -X POST "https://api.tornadoapi.io/user/blob" \
-H "x-api-key: sk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"account_name": "mystorageaccount",
"container": "tornado-downloads",
"account_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxx=="
}'
curl -X POST "https://api.tornadoapi.io/user/blob" \
-H "x-api-key: sk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"account_name": "mystorageaccount",
"container": "tornado-downloads",
"sas_token": "sv=2022-11-02&ss=b&srt=co&sp=rwdlacyx&se=2025-12-31T23:59:59Z&sig=..."
}'
import requests
response = requests.post(
"https://api.tornadoapi.io/user/blob",
headers={"x-api-key": "sk_your_api_key"},
json={
"account_name": "mystorageaccount",
"container": "tornado-downloads",
"account_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxx=="
}
)
print(response.json())
{
"message": "Azure Blob storage configured successfully",
"provider": "blob",
"container_or_bucket": "tornado-downloads"
}
Success Response
{
"message": "Azure Blob storage configured successfully",
"provider": "blob",
"container_or_bucket": "tornado-downloads"
}
Error Responses
{
"error": "Either account_key or sas_token must be provided"
}
{
"error": "Credential validation failed: AuthenticationFailed"
}
{
"error": "Account key must be valid Base64"
}
{
"error": "Invalid API Key"
}
{
"error": "Azure Blob storage configuration is temporarily unavailable"
}
Verification Process
When you submit storage configuration, Tornado:- Validates that either
account_keyorsas_tokenis provided - Creates a storage client with your credentials
- Attempts to upload a small test file (
verify_credentials.txt) - Deletes the test file
- If successful, saves the configuration encrypted
Required SAS Permissions
When using a SAS token, ensure these permissions are enabled:- Read (r) - For generating download URLs
- Write (w) - For uploading files
- Delete (d) - For cleanup operations
- List (l) - For validation
Was this page helpful?