TYPE | VALUE | WHEN TO USE |
---|---|---|
Secret | sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | Use this key on the server side. It must be kept secret and stored securely in your web or application's server-side code. Don't expose this key on a website or embed it in a client-side application. |
Public | pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | Use this key on the client side. It can be exposed on website or in a client-side application. A request signature must be included in all requests using a public key. |
<html>
<body>
<div id="output">Retrieving log fields...</div>
<script>
// Replace with your Flight Reader API secret key
const secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Note: You should never expose your API secret key like this in a production environment.
// Anyone who has access to it will be able to make API requests on your behalf.
async function retrieveLogFields() {
try {
const response = await fetch("https://api.flightreader.com/v1/fields", {
headers: {
"Accept-Encoding": "gzip",
"Authorization": `Bearer ${secretApiKey}`
}
});
if (response.ok) {
const data = await response.json();
output.textContent = JSON.stringify(data.result);
} else {
output.textContent = `${response.status} ${response.statusText}`;
}
} catch (error) {
output.textContent = error;
}
}
retrieveLogFields();
</script>
</body>
</html>
<html>
<body>
<!-- https://github.com/brix/crypto-js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<div id="output">Retrieving log fields...</div>
<script>
// Replace with your Flight Reader API keys
const publicApiKey = "pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Note: You should never expose your API secret key like this in a production environment.
// Anyone who has access to it will be able to make API requests on your behalf.
async function retrieveLogFields() {
try {
// Create a request signature used by the Flight Reader API to verify the request was
// initiated by you. This signature will expire 5 minutes after it's created.
const signature = createSignature();
const response = await fetch("https://api.flightreader.com/v1/fields", {
headers: {
"Accept-Encoding": "gzip",
"Authorization": `Bearer ${publicApiKey}`,
"Api-Signature": signature.value,
"Api-Timestamp": signature.currentUnixTimeInSeconds
}
});
if (response.ok) {
const data = await response.json();
output.textContent = JSON.stringify(data.result);
} else {
output.textContent = `${response.status} ${response.statusText}`;
}
} catch (error) {
output.textContent = error;
}
}
function createSignature() {
const currentUnixTimeInSeconds = Math.floor(Date.now() / 1000);
const requestMethod = "GET";
const requestResource = "/v1/fields";
const stringToSign = requestMethod + requestResource + currentUnixTimeInSeconds;
const value = CryptoJS.HmacSHA256(stringToSign, secretApiKey).toString(CryptoJS.enc.Hex);
return { value, currentUnixTimeInSeconds };
}
retrieveLogFields();
</script>
</body>
</html>
using System.IO.Compression;
using System.Text;
internal class Program
{
static async Task Main()
{
// Replace with your Flight Reader API secret key
const string secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
using HttpClient client = new();
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {secretApiKey}");
var response = await client.GetAsync("https://api.flightreader.com/v1/fields");
if (response.IsSuccessStatusCode)
{
var responseBytes = await response.Content.ReadAsByteArrayAsync();
if (response.Content.Headers.ContentEncoding.Contains("gzip"))
{
using var compressedStream = new MemoryStream(responseBytes);
await using var decompressionStream = new GZipStream(compressedStream, CompressionMode.Decompress);
using var decompressedStream = new MemoryStream();
await decompressionStream.CopyToAsync(decompressedStream);
responseBytes = decompressedStream.ToArray();
}
var responseText = Encoding.UTF8.GetString(responseBytes);
Console.WriteLine(responseText);
}
else
{
Console.WriteLine($"Error: {response.StatusCode}");
}
}
}
using System.IO.Compression;
using System.Security.Cryptography;
using System.Text;
internal class Program
{
static async Task Main()
{
// Replace with your Flight Reader API keys
const string publicApiKey = "pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const string secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Create a request signature used by the Flight Reader API to verify the request was
// initiated by you. This signature will expire 5 minutes after it's created.
var currentUnixTimeInSeconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var requestMethod = "GET";
var requestResource = "/v1/fields";
var stringToSign = requestMethod + requestResource + currentUnixTimeInSeconds;
var signature = CreateSignature(stringToSign, secretApiKey);
using HttpClient client = new();
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {publicApiKey}");
client.DefaultRequestHeaders.Add("Api-Signature", signature);
client.DefaultRequestHeaders.Add("Api-Timestamp", currentUnixTimeInSeconds.ToString());
var response = await client.GetAsync("https://api.flightreader.com/v1/fields");
if (response.IsSuccessStatusCode)
{
var responseBytes = await response.Content.ReadAsByteArrayAsync();
if (response.Content.Headers.ContentEncoding.Contains("gzip"))
{
using var compressedStream = new MemoryStream(responseBytes);
await using var decompressionStream = new GZipStream(compressedStream, CompressionMode.Decompress);
using var decompressedStream = new MemoryStream();
await decompressionStream.CopyToAsync(decompressedStream);
responseBytes = decompressedStream.ToArray();
}
var responseText = Encoding.UTF8.GetString(responseBytes);
Console.WriteLine(responseText);
}
else
{
Console.WriteLine($"Error: {response.StatusCode}");
}
}
private static string CreateSignature(string value, string key)
{
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
var dataBytes = Encoding.UTF8.GetBytes(value);
var hashBytes = hmac.ComputeHash(dataBytes);
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
}
}
{
"statusCode": 200,
"message": "GET Request successful.",
"result": [
{
"name": "APP_Message",
"displayName": "APP.message",
"description": "An informational message generated by the application being used to control the aircraft."
},
{
"name": "APP_Tip",
"displayName": "APP.tip",
"description": "An informational message generated by the application being used to control the aircraft."
},
{...},
{...}
]
}
<html>
<body>
<div id="output">Deleting API key...</div>
<script>
// Replace with your Flight Reader API secret key
const secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Note: You should never expose your API secret key like this in a production environment.
// Anyone who has access to it will be able to make API requests on your behalf.
// Set this to the secret key to delete. The associated public key will also be deleted.
const secretApiKeyToDelete = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
async function deleteApiKey() {
try {
const response = await fetch(`https://api.flightreader.com/v1/keys/${secretApiKeyToDelete}`, {
method: "DELETE",
headers: {
"Accept-Encoding": "gzip",
"Authorization": `Bearer ${secretApiKey}`
}
});
if (response.ok) {
const data = await response.json();
output.textContent = JSON.stringify(data);
} else {
output.textContent = `${response.status} ${response.statusText}`;
}
} catch (error) {
output.textContent = error;
}
}
deleteApiKey();
</script>
</body>
</html>
using System.IO.Compression;
using System.Text;
internal class Program
{
static async Task Main()
{
// Replace with your Flight Reader API secret key
const string secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Set this to the secret key to delete. The associated public key will also be deleted.
const string secretApiKeyToDelete = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
using HttpClient client = new();
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {secretApiKey}");
var response = await client.DeleteAsync($"https://api.flightreader.com/v1/keys/{secretApiKeyToDelete}");
if (response.IsSuccessStatusCode)
{
var responseBytes = await response.Content.ReadAsByteArrayAsync();
if (response.Content.Headers.ContentEncoding.Contains("gzip"))
{
using var compressedStream = new MemoryStream(responseBytes);
await using var decompressionStream = new GZipStream(compressedStream, CompressionMode.Decompress);
using var decompressedStream = new MemoryStream();
await decompressionStream.CopyToAsync(decompressedStream);
responseBytes = decompressedStream.ToArray();
}
var responseText = Encoding.UTF8.GetString(responseBytes);
Console.WriteLine(responseText);
}
else
{
Console.WriteLine($"Error: {response.StatusCode}");
}
}
}
{
"statusCode": 200,
"message": "DELETE Request successful."
}
<html>
<body>
<div id="output">Retrieving API keys...</div>
<script>
// Replace with your Flight Reader API secret key
const secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Note: You should never expose your API secret key like this in a production environment.
// Anyone who has access to it will be able to make API requests on your behalf.
async function retrieveApiKeys() {
try {
const response = await fetch("https://api.flightreader.com/v1/keys", {
headers: {
"Accept-Encoding": "gzip",
"Authorization": `Bearer ${secretApiKey}`
}
});
if (response.ok) {
const data = await response.json();
output.textContent = JSON.stringify(data.result);
} else {
output.textContent = `${response.status} ${response.statusText}`;
}
} catch (error) {
output.textContent = error;
}
}
retrieveApiKeys();
</script>
</body>
</html>
using System.IO.Compression;
using System.Text;
internal class Program
{
static async Task Main()
{
// Replace with your Flight Reader API secret key
const string secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
using HttpClient client = new();
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {secretApiKey}");
var response = await client.GetAsync("https://api.flightreader.com/v1/keys");
if (response.IsSuccessStatusCode)
{
var responseBytes = await response.Content.ReadAsByteArrayAsync();
if (response.Content.Headers.ContentEncoding.Contains("gzip"))
{
using var compressedStream = new MemoryStream(responseBytes);
await using var decompressionStream = new GZipStream(compressedStream, CompressionMode.Decompress);
using var decompressedStream = new MemoryStream();
await decompressionStream.CopyToAsync(decompressedStream);
responseBytes = decompressedStream.ToArray();
}
var responseText = Encoding.UTF8.GetString(responseBytes);
Console.WriteLine(responseText);
}
else
{
Console.WriteLine($"Error: {response.StatusCode}");
}
}
}
{
"statusCode": 200,
"message": "GET Request successful.",
"result": [
{
"publicKey": "pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"secretKey": "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"createdUtc": "2023-08-21T11:37:38Z"
},
{...},
{...}
]
}
<html>
<body>
<div id="output">Creating API key...</div>
<script>
// Replace with your Flight Reader API secret key
const secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Note: You should never expose your API secret key like this in a production environment.
// Anyone who has access to it will be able to make API requests on your behalf.
async function createApiKey() {
try {
const response = await fetch("https://api.flightreader.com/v1/keys", {
method: "POST",
headers: {
"Accept-Encoding": "gzip",
"Authorization": `Bearer ${secretApiKey}`
}
});
if (response.ok) {
const data = await response.json();
output.textContent = JSON.stringify(data.result);
} else {
output.textContent = `${response.status} ${response.statusText}`;
}
} catch (error) {
output.textContent = error;
}
}
createApiKey();
</script>
</body>
</html>
using System.IO.Compression;
using System.Text;
internal class Program
{
static async Task Main()
{
// Replace with your Flight Reader API secret key
const string secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
using HttpClient client = new();
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {secretApiKey}");
var response = await client.PostAsync("https://api.flightreader.com/v1/keys", null);
if (response.IsSuccessStatusCode)
{
var responseBytes = await response.Content.ReadAsByteArrayAsync();
if (response.Content.Headers.ContentEncoding.Contains("gzip"))
{
using var compressedStream = new MemoryStream(responseBytes);
await using var decompressionStream = new GZipStream(compressedStream, CompressionMode.Decompress);
using var decompressedStream = new MemoryStream();
await decompressionStream.CopyToAsync(decompressedStream);
responseBytes = decompressedStream.ToArray();
}
var responseText = Encoding.UTF8.GetString(responseBytes);
Console.WriteLine(responseText);
}
else
{
Console.WriteLine($"Error: {response.StatusCode}");
}
}
}
{
"statusCode": 201,
"message": "POST Request successful.",
"result": {
"publicKey": "pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"secretKey": "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
<html>
<body>
<div id="output">Retrieving log field...</div>
<script>
// Replace with your Flight Reader API secret key
const secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Note: You should never expose your API secret key like this in a production environment.
// Anyone who has access to it will be able to make API requests on your behalf.
// Call the "/api/v1/fields" endpoint to see a complete list of log fields that can be set here
const fieldName = "OSD_IsGpsUsed";
async function retrieveLogField() {
try {
const response = await fetch(`https://api.flightreader.com/v1/fields/${fieldName}`, {
headers: {
"Accept-Encoding": "gzip",
"Authorization": `Bearer ${secretApiKey}`
}
});
if (response.ok) {
const data = await response.json();
output.textContent = JSON.stringify(data.result);
} else {
output.textContent = `${response.status} ${response.statusText}`;
}
} catch (error) {
output.textContent = error;
}
}
retrieveLogField();
</script>
</body>
</html>
<html>
<body>
<!-- https://github.com/brix/crypto-js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<div id="output">Retrieving log field...</div>
<script>
// Replace with your Flight Reader API secret key
const publicApiKey = "pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Note: You should never expose your API secret key like this in a production environment.
// Anyone who has access to it will be able to make API requests on your behalf.
// Call the "/api/v1/fields" endpoint to see a complete list of log fields that can be set here
const fieldName = "OSD_IsGpsUsed";
async function retrieveLogField() {
try {
// Create a request signature used by the Flight Reader API to verify the request was
// initiated by you. This signature will expire 5 minutes after it's created.
const signature = createSignature();
const response = await fetch(`https://api.flightreader.com/v1/fields/${fieldName}`, {
headers: {
"Accept-Encoding": "gzip",
"Authorization": `Bearer ${publicApiKey}`,
"Api-Signature": signature.value,
"Api-Timestamp": signature.currentUnixTimeInSeconds
}
});
if (response.ok) {
const data = await response.json();
output.textContent = JSON.stringify(data.result);
} else {
output.textContent = `${response.status} ${response.statusText}`;
}
} catch (error) {
output.textContent = error;
}
}
function createSignature() {
const currentUnixTimeInSeconds = Math.floor(Date.now() / 1000);
const requestMethod = "GET";
const requestResource = "/v1/fields/OSD_IsGpsUsed";
const stringToSign = requestMethod + requestResource + currentUnixTimeInSeconds;
const value = CryptoJS.HmacSHA256(stringToSign, secretApiKey).toString(CryptoJS.enc.Hex);
return { value, currentUnixTimeInSeconds };
}
retrieveLogField();
</script>
</body>
</html>
using System.IO.Compression;
using System.Text;
internal class Program
{
static async Task Main()
{
// Replace with your Flight Reader API secret key
const string secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
using HttpClient client = new();
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {secretApiKey}");
const string fieldName = "OSD_IsGpsUsed";
var response = await client.GetAsync($"https://api.flightreader.com/v1/fields/{fieldName}");
if (response.IsSuccessStatusCode)
{
var responseBytes = await response.Content.ReadAsByteArrayAsync();
if (response.Content.Headers.ContentEncoding.Contains("gzip"))
{
using var compressedStream = new MemoryStream(responseBytes);
await using var decompressionStream = new GZipStream(compressedStream, CompressionMode.Decompress);
using var decompressedStream = new MemoryStream();
await decompressionStream.CopyToAsync(decompressedStream);
responseBytes = decompressedStream.ToArray();
}
var responseText = Encoding.UTF8.GetString(responseBytes);
Console.WriteLine(responseText);
}
else
{
Console.WriteLine($"Error: {response.StatusCode}");
}
}
}
using System.IO.Compression;
using System.Security.Cryptography;
using System.Text;
internal class Program
{
static async Task Main()
{
// Replace with your Flight Reader API keys
const string publicApiKey = "pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const string secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Create a request signature used by the Flight Reader API to verify the request was
// initiated by you. This signature will expire 5 minutes after it's created.
var currentUnixTimeInSeconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var requestMethod = "GET";
var requestResource = "/v1/fields/OSD_IsGpsUsed";
var stringToSign = requestMethod + requestResource + currentUnixTimeInSeconds;
var signature = CreateSignature(stringToSign, secretApiKey);
using HttpClient client = new();
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {publicApiKey}");
client.DefaultRequestHeaders.Add("Api-Signature", signature);
client.DefaultRequestHeaders.Add("Api-Timestamp", currentUnixTimeInSeconds.ToString());
const string fieldName = "OSD_IsGpsUsed";
var response = client.GetAsync($"https://api.flightreader.com/v1/fields/{fieldName}").Result;
if (response.IsSuccessStatusCode)
{
var responseBytes = await response.Content.ReadAsByteArrayAsync();
if (response.Content.Headers.ContentEncoding.Contains("gzip"))
{
using var compressedStream = new MemoryStream(responseBytes);
await using var decompressionStream = new GZipStream(compressedStream, CompressionMode.Decompress);
using var decompressedStream = new MemoryStream();
await decompressionStream.CopyToAsync(decompressedStream);
responseBytes = decompressedStream.ToArray();
}
var responseText = Encoding.UTF8.GetString(responseBytes);
Console.WriteLine(responseText);
}
else
{
Console.WriteLine($"Error: {response.StatusCode}");
}
}
private static string CreateSignature(string value, string key)
{
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
var dataBytes = Encoding.UTF8.GetBytes(value);
var hashBytes = hmac.ComputeHash(dataBytes);
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
}
}
{
"statusCode": 200,
"message": "GET Request successful.",
"result": {
"name": "OSD_IsGpsUsed",
"displayName": "OSD.isGPSUsed",
"description": "When true, the aircraft is able to use the GPS satellite data for positioning purposes."
}
}
<html>
<body>
<input type="file" id="fileInput">
<br><br>
<div id="output"></div>
<script>
// Replace with your Flight Reader API secret key
const secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Note: You should never expose your API secret key like this in a production environment.
// Anyone who has access to it will be able to make API requests on your behalf.
// Call the "/api/v1/fields" endpoint to see a complete list of log fields that can be set here
const fields = ["OSD_FlyTimeMilliseconds", "OSD_Latitude", "OSD_Longitude"];
async function processFlightLog() {
try {
const formData = new FormData();
formData.append("file", fileInput.files[0]);
// Remove this forEach loop if you'd like to retrieve all available fields
fields.forEach((value, index) => {
formData.append("fields", value);
});
const response = await fetch("https://api.flightreader.com/v1/logs", {
method: "POST",
body: formData,
headers: {
"Accept-Encoding": "gzip",
"Authorization": `Bearer ${secretApiKey}`
}
});
if (response.ok) {
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", "DJIFlightRecord.csv");
link.setAttribute("target", "_blank");
document.body.appendChild(link);
link.click();
output.textContent = "CSV file successfully downloaded";
} else {
output.textContent = `${response.status} ${response.statusText}`;
}
} catch (error) {
output.textContent = error;
}
finally {
fileInput.value = null;
}
}
fileInput.addEventListener("change", () => {
output.textContent = "Processing flight log file...";
processFlightLog();
});
</script>
</body>
</html>
<html>
<body>
<!-- https://github.com/brix/crypto-js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<input type="file" id="fileInput">
<br><br>
<div id="output"></div>
<script>
// Replace with your Flight Reader API keys
const publicApiKey = "pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Note: You should never expose your API secret key like this in a production environment.
// Anyone who has access to it will be able to make API requests on your behalf.
// Call the "/api/v1/fields" endpoint to see a complete list of log fields that can be set here
const fields = ["OSD_FlyTimeMilliseconds", "OSD_Latitude", "OSD_Longitude"];
async function processFlightLog() {
try {
const formData = new FormData();
formData.append("file", fileInput.files[0]);
// Remove this forEach loop if you'd like to retrieve all available fields
fields.forEach((value, index) => {
formData.append("fields", value);
});
// Create a request signature used by the Flight Reader API to verify the request was
// initiated by you. This signature will expire 5 minutes after it's created.
const signature = createSignature(formData);
const response = await fetch("https://api.flightreader.com/v1/logs", {
method: "POST",
body: formData,
headers: {
"Accept-Encoding": "gzip",
"Authorization": `Bearer ${publicApiKey}`,
"Api-Signature": signature.value,
"Api-Timestamp": signature.currentUnixTimeInSeconds
}
});
if (response.ok) {
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", "DJIFlightRecord.csv");
link.setAttribute("target", "_blank");
document.body.appendChild(link);
link.click();
output.textContent = "CSV file successfully downloaded";
} else {
output.textContent = `${response.status} ${response.statusText}`;
}
} catch (error) {
output.textContent = error;
}
finally {
fileInput.value = null;
}
}
function formDataToString(formData) {
const excludedKeys = new Set(["file"]);
const keyValuePairs = {};
for (const [key, value] of formData.entries()) {
if (excludedKeys.has(key)) {
continue;
}
if (!keyValuePairs[key]) {
keyValuePairs[key] = [value];
} else {
keyValuePairs[key].push(value);
}
}
return Object.entries(keyValuePairs)
.map(([key, values]) => `${key}=${values.join(",")}`)
.join("&");
}
function createSignature(formData) {
const currentUnixTimeInSeconds = Math.floor(Date.now() / 1000);
const requestMethod = "POST";
const requestResource = "/v1/logs";
const formDataString = formDataToString(formData);
const stringToSign = requestMethod + requestResource + formDataString + currentUnixTimeInSeconds;
const value = CryptoJS.HmacSHA256(stringToSign, secretApiKey).toString(CryptoJS.enc.Hex);
return { value, currentUnixTimeInSeconds };
}
fileInput.addEventListener("change", () => {
output.textContent = "Processing flight log file...";
processFlightLog();
});
</script>
</body>
</html>
using System.IO.Compression;
using System.Net.Http.Headers;
using System.Text;
internal class Program
{
static async Task Main()
{
// Replace with your Flight Reader API secret key
const string secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const string logFilePath = "C:\\DJIFlightRecord_2020-12-08_[13-39-22].txt";
var fields = new List<string>
{
"OSD_FlyTimeMilliseconds",
"OSD_Latitude",
"OSD_Longitude"
};
var formContent = new MultipartFormDataContent();
// Add file to form
var fileContent = new ByteArrayContent(await File.ReadAllBytesAsync(logFilePath));
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "file",
FileName = Path.GetFileName(logFilePath)
};
fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
formContent.Add(fileContent);
// Add fields to form (remove this foreach loop if you'd like to retrieve all available fields)
foreach (var field in fields)
{
formContent.Add(new StringContent(field), "fields");
}
// Process log
using HttpClient client = new();
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {secretApiKey}");
var response = await client.PostAsync("https://api.flightreader.com/v1/logs", formContent);
var responseBytes = await response.Content.ReadAsByteArrayAsync();
if (response.Content.Headers.ContentEncoding.Contains("gzip"))
{
using var compressedStream = new MemoryStream(responseBytes);
await using var decompressionStream = new GZipStream(compressedStream, CompressionMode.Decompress);
using var decompressedStream = new MemoryStream();
await decompressionStream.CopyToAsync(decompressedStream);
responseBytes = decompressedStream.ToArray();
}
var responseText = Encoding.UTF8.GetString(responseBytes);
Console.WriteLine(responseText);
}
}
using System.IO.Compression;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
internal class Program
{
private static async Task Main()
{
// Replace with your Flight Reader API keys
const string publicApiKey = "pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const string secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const string logFilePath = "C:\\DJIFlightRecord_2020-12-08_[13-39-22].txt";
var fields = new List<string>
{
"OSD_FlyTimeMilliseconds",
"OSD_Latitude",
"OSD_Longitude"
};
var formContent = new MultipartFormDataContent();
// Add file to form
var fileContent = new ByteArrayContent(await File.ReadAllBytesAsync(logFilePath));
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "file",
FileName = Path.GetFileName(logFilePath)
};
fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
formContent.Add(fileContent);
// Add fields to form (remove this foreach loop if you'd like to retrieve all available fields)
foreach (var field in fields)
{
formContent.Add(new StringContent(field), "fields");
}
// Create a request signature used by the Flight Reader API to verify the request was
// initiated by you. This signature will expire 5 minutes after it's created.
var currentUnixTimeInSeconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var requestMethod = "POST";
var requestResource = "/v1/logs";
var formData = await GetFormDataAsync(formContent);
var stringToSign = $"{requestMethod}{requestResource}{formData}{currentUnixTimeInSeconds}";
var signature = CreateSignature(stringToSign, secretApiKey);
// Process log
using HttpClient client = new();
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {publicApiKey}");
client.DefaultRequestHeaders.Add("Api-Signature", signature);
client.DefaultRequestHeaders.Add("Api-Timestamp", currentUnixTimeInSeconds.ToString());
var response = await client.PostAsync("https://api.flightreader.com/v1/logs", formContent);
var responseBytes = await response.Content.ReadAsByteArrayAsync();
if (response.Content.Headers.ContentEncoding.Contains("gzip"))
{
using var compressedStream = new MemoryStream(responseBytes);
await using var decompressionStream = new GZipStream(compressedStream, CompressionMode.Decompress);
using var decompressedStream = new MemoryStream();
await decompressionStream.CopyToAsync(decompressedStream);
responseBytes = decompressedStream.ToArray();
}
var responseText = Encoding.UTF8.GetString(responseBytes);
Console.WriteLine(responseText);
}
private static async Task<string> GetFormDataAsync(MultipartFormDataContent formContent)
{
var formData = "";
var lastFieldName = "";
foreach (var content in formContent)
{
if (content is not StringContent stringContent)
{
continue;
}
var fieldName = content.Headers.ContentDisposition?.Name?.Trim('"');
if (fieldName != lastFieldName)
{
lastFieldName = fieldName;
if (formData.Length > 0)
{
formData += "&";
}
formData += $"{fieldName}=";
}
else
{
formData += ",";
}
formData += await stringContent.ReadAsStringAsync();
}
return formData;
}
private static string CreateSignature(string value, string key)
{
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
var dataBytes = Encoding.UTF8.GetBytes(value);
var hashBytes = hmac.ComputeHash(dataBytes);
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
}
}
OSD.flyTime [ms],OSD.latitude,OSD.longitude
100,53.62646476704494,16.87070193398017
300,53.62646474133018,16.87070199143842
500,53.62646469232834,16.870702037681247
...
<html>
<body>
<div id="output">Processing flight log...</div>
<script>
// Replace with your Flight Reader API secret key
const secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Note: You should never expose your API secret key like this in a production environment.
// Anyone who has access to it will be able to make API requests on your behalf.
// Set this URL to the location of the DJI TXT flight log file to download
const flightLogUrl = "https://www.YourWebsite.com/DJIFlightRecord_2020-05-16_[19-02-56].txt";
// Call the "/api/v1/fields" endpoint to see a complete list of log fields that can be set here
const fields = ["OSD_FlyTimeMilliseconds", "OSD_Latitude", "OSD_Longitude"];
async function processFlightLog() {
try {
const output = document.getElementById("output");
const formData = new FormData();
formData.append("url", flightLogUrl);
// Remove this forEach loop if you'd like to retrieve all available fields
fields.forEach((value, index) => {
formData.append("fields", value);
});
const response = await fetch("https://api.flightreader.com/v1/logs", {
method: "POST",
body: formData,
headers: {
"Accept-Encoding": "gzip",
"Authorization": `Bearer ${secretApiKey}`
}
});
if (response.ok) {
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", "DJIFlightRecord.csv");
link.setAttribute("target", "_blank");
document.body.appendChild(link);
link.click();
output.textContent = "CSV file successfully downloaded";
} else {
output.textContent = `${response.status} ${response.statusText}`;
}
} catch (error) {
output.textContent = error;
}
}
processFlightLog();
</script>
</body>
</html>
<html>
<body>
<!-- https://github.com/brix/crypto-js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<div id="output">Processing flight log...</div>
<script>
// Replace with your Flight Reader API keys
const publicApiKey = "pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Note: You should never expose your API secret key like this in a production environment.
// Anyone who has access to it will be able to make API requests on your behalf.
// Set this URL to the location of the DJI TXT flight log file to download
const flightLogUrl = "https://www.YourWebsite.com/DJIFlightRecord_2020-05-16_[19-02-56].txt";
// Call the "/api/v1/fields" endpoint to see a complete list of log fields that can be set here
const fields = ["OSD_FlyTimeMilliseconds", "OSD_Latitude", "OSD_Longitude"];
async function processFlightLog() {
try {
const formData = new FormData();
formData.append("url", flightLogUrl);
// Remove this forEach loop if you'd like to retrieve all available fields
fields.forEach((value, index) => {
formData.append("fields", value);
});
// Create a request signature used by the Flight Reader API to verify the request was
// initiated by you. This signature will expire 5 minutes after it's created.
const signature = createSignature(formData);
const response = await fetch("https://api.flightreader.com/v1/logs", {
method: "POST",
body: formData,
headers: {
"Accept-Encoding": "gzip",
"Authorization": `Bearer ${publicApiKey}`,
"Api-Signature": signature.value,
"Api-Timestamp": signature.currentUnixTimeInSeconds
}
});
if (response.ok) {
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", "DJIFlightRecord.csv");
link.setAttribute("target", "_blank");
document.body.appendChild(link);
link.click();
output.textContent = "CSV file successfully downloaded";
} else {
output.textContent = `${response.status} ${response.statusText}`;
}
} catch (error) {
output.textContent = error;
}
}
function formDataToString(formData) {
const keyValuePairs = {};
for (const [key, value] of formData.entries()) {
if (!keyValuePairs[key]) {
keyValuePairs[key] = [value];
} else {
keyValuePairs[key].push(value);
}
}
return Object.entries(keyValuePairs)
.map(([key, values]) => `${key}=${values.join(",")}`)
.join("&");
}
function createSignature(formData) {
const currentUnixTimeInSeconds = Math.floor(Date.now() / 1000);
const requestMethod = "POST";
const requestResource = "/v1/logs";
const formDataString = formDataToString(formData);
const stringToSign = requestMethod + requestResource + formDataString + currentUnixTimeInSeconds;
const value = CryptoJS.HmacSHA256(stringToSign, secretApiKey).toString(CryptoJS.enc.Hex);
return { value, currentUnixTimeInSeconds };
}
processFlightLog();
</script>
</body>
</html>
using System.IO.Compression;
using System.Text;
internal class Program
{
private static async Task Main()
{
// Replace with your Flight Reader API secret key
const string secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const string logFileUrl = "https://www.YourWebsite.com/DJIFlightRecord_2020-05-16_[19-02-56].txt";
var fields = new List<string>
{
"OSD_FlyTimeMilliseconds",
"OSD_Latitude",
"OSD_Longitude"
};
var formContent = new MultipartFormDataContent();
// Add url to form
formContent.Add(new StringContent(logFileUrl), "url");
// Add fields to form (remove this foreach loop if you'd like to retrieve all available fields)
foreach (var field in fields)
{
formContent.Add(new StringContent(field), "fields");
}
// Process log
using HttpClient client = new();
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {secretApiKey}");
var response = await client.PostAsync("https://api.flightreader.com/v1/logs", formContent);
var responseBytes = await response.Content.ReadAsByteArrayAsync();
if (response.Content.Headers.ContentEncoding.Contains("gzip"))
{
using var compressedStream = new MemoryStream(responseBytes);
await using var decompressionStream = new GZipStream(compressedStream, CompressionMode.Decompress);
using var decompressedStream = new MemoryStream();
await decompressionStream.CopyToAsync(decompressedStream);
responseBytes = decompressedStream.ToArray();
}
var responseText = Encoding.UTF8.GetString(responseBytes);
Console.WriteLine(responseText);
}
}
using System.IO.Compression;
using System.Security.Cryptography;
using System.Text;
internal class Program
{
private static async Task Main()
{
// Replace with your Flight Reader API keys
const string publicApiKey = "pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const string secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const string logFileUrl = "https://www.YourWebsite.com/DJIFlightRecord_2020-05-16_[19-02-56].txt";
var fields = new List<string>
{
"OSD_FlyTimeMilliseconds",
"OSD_Latitude",
"OSD_Longitude"
};
var formContent = new MultipartFormDataContent();
// Add url to form
formContent.Add(new StringContent(logFileUrl), "url");
// Add fields to form (remove this foreach loop if you'd like to retrieve all available fields)
foreach (var field in fields)
{
formContent.Add(new StringContent(field), "fields");
}
// Create a request signature used by the Flight Reader API to verify the request was
// initiated by you. This signature will expire 5 minutes after it's created.
var currentUnixTimeInSeconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var requestMethod = "POST";
var requestResource = "/v1/logs";
var formData = await GetFormDataAsync(formContent);
var stringToSign = requestMethod + requestResource + formData + currentUnixTimeInSeconds;
var signature = CreateSignature(stringToSign, secretApiKey);
// Process log
using HttpClient client = new();
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {publicApiKey}");
client.DefaultRequestHeaders.Add("Api-Signature", signature);
client.DefaultRequestHeaders.Add("Api-Timestamp", currentUnixTimeInSeconds.ToString());
var response = await client.PostAsync("https://api.flightreader.com/v1/logs", formContent);
var responseBytes = await response.Content.ReadAsByteArrayAsync();
if (response.Content.Headers.ContentEncoding.Contains("gzip"))
{
using var compressedStream = new MemoryStream(responseBytes);
await using var decompressionStream = new GZipStream(compressedStream, CompressionMode.Decompress);
using var decompressedStream = new MemoryStream();
await decompressionStream.CopyToAsync(decompressedStream);
responseBytes = decompressedStream.ToArray();
}
var responseText = Encoding.UTF8.GetString(responseBytes);
Console.WriteLine(responseText);
}
private static async Task<string> GetFormDataAsync(MultipartFormDataContent formContent)
{
var formData = "";
var lastFieldName = "";
foreach (var content in formContent)
{
if (content is not StringContent stringContent)
{
continue;
}
var fieldName = content.Headers.ContentDisposition?.Name?.Trim('"');
if (fieldName != lastFieldName)
{
lastFieldName = fieldName;
if (formData.Length > 0)
{
formData += "&";
}
formData += $"{fieldName}=";
}
else
{
formData += ",";
}
formData += await stringContent.ReadAsStringAsync();
}
return formData;
}
private static string CreateSignature(string value, string key)
{
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
var dataBytes = Encoding.UTF8.GetBytes(value);
var hashBytes = hmac.ComputeHash(dataBytes);
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
}
}
OSD.flyTime [ms],OSD.latitude,OSD.longitude
100,53.62646476704494,16.87070193398017
300,53.62646474133018,16.87070199143842
500,53.62646469232834,16.870702037681247
...
<html>
<body>
<div id="output">Retrieving flight log list...</div>
<script>
// Replace with your Flight Reader API secret key
const secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Note: You should never expose your API secret key like this in a production environment.
// Anyone who has access to it will be able to make API requests on your behalf.
// Use the "/v1/accounts/dji" endpoint to retrieve this DJI account id
const id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
async function retrieveFlightLogList() {
try {
// The optional "limit" and "createdAfterId" parameters can be appended to the URL
// like this:
//
// https://api.flightreader.com/v1/logs/${id}?limit=20&createdAfterId=5926331
const response = await fetch(`https://api.flightreader.com/v1/logs/${id}`, {
headers: {
"Accept-Encoding": "gzip",
"Authorization": `Bearer ${secretApiKey}`
}
});
if (response.ok) {
const data = await response.json();
output.textContent = JSON.stringify(data.result);
} else {
output.textContent = `${response.status} ${response.statusText}`;
}
} catch (error) {
output.textContent = error;
}
}
retrieveFlightLogList();
</script>
</body>
</html>
<html>
<body>
<!-- https://github.com/brix/crypto-js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<div id="output">Retrieving flight log list...</div>
<script>
// Replace with your Flight Reader API keys
const publicApiKey = "pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Note: You should never expose your API secret key like this in a production environment.
// Anyone who has access to it will be able to make API requests on your behalf.
// Use the "/api/v1/accounts/dji" endpoint to retrieve this DJI account id
const id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
async function retrieveFlightLogList() {
try {
// Create a request signature used by the Flight Reader API to verify the request was
// initiated by you. This signature will expire 5 minutes after it's created.
const signature = createSignature();
// The optional "limit" and "createdAfterId" parameters can be appended to the URL
// like this:
//
// https://api.flightreader.com/v1/logs/${id}?limit=20&createdAfterId=5926331
const response = await fetch(`https://api.flightreader.com/v1/logs/${id}`, {
headers: {
"Accept-Encoding": "gzip",
"Authorization": `Bearer ${secretApiKey}`,
"Api-Signature": signature.value,
"Api-Timestamp": signature.currentUnixTimeInSeconds
}
});
if (response.ok) {
const data = await response.json();
output.textContent = JSON.stringify(data.result);
} else {
output.textContent = `${response.status} ${response.statusText}`;
}
} catch (error) {
output.textContent = error;
}
}
function createSignature() {
const currentUnixTimeInSeconds = Math.floor(Date.now() / 1000);
const requestMethod = "GET";
const requestResource = `/v1/logs/${id}`;
const stringToSign = requestMethod + requestResource + currentUnixTimeInSeconds;
const value = CryptoJS.HmacSHA256(stringToSign, secretApiKey).toString(CryptoJS.enc.Hex);
return { value, currentUnixTimeInSeconds };
}
retrieveFlightLogList();
</script>
</body>
</html>
using System.IO.Compression;
using System.Text;
internal class Program
{
private static async Task Main()
{
// Replace with your Flight Reader API secret key
const string secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Use the "/api/v1/accounts/dji" endpoint to retrieve this DJI account id
const string id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// The optional "limit" and "createdAfterId" parameters can be appended to the URL
// like this:
//
// var response = await client.GetAsync($"https://api.flightreader.com/v1/logs/{id}?limit=20&createdAfterId=5926331");
using HttpClient client = new();
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {secretApiKey}");
var response = await client.GetAsync($"https://api.flightreader.com/v1/logs/{id}");
if (response.IsSuccessStatusCode)
{
var responseBytes = await response.Content.ReadAsByteArrayAsync();
if (response.Content.Headers.ContentEncoding.Contains("gzip"))
{
using var compressedStream = new MemoryStream(responseBytes);
await using var decompressionStream = new GZipStream(compressedStream, CompressionMode.Decompress);
using var decompressedStream = new MemoryStream();
await decompressionStream.CopyToAsync(decompressedStream);
responseBytes = decompressedStream.ToArray();
}
var responseText = Encoding.UTF8.GetString(responseBytes);
Console.WriteLine(responseText);
}
else
{
Console.WriteLine($"Error: {response.StatusCode}");
}
}
}
using System.IO.Compression;
using System.Security.Cryptography;
using System.Text;
internal class Program
{
private static async Task Main()
{
// Replace with your Flight Reader API keys
const string publicApiKey = "pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const string secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Use the "/api/v1/accounts/dji" endpoint to retrieve this DJI account id
const string id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// The optional "limit" and "createdAfterId" parameters can be appended to the URL
// like this:
//
// var response = await client.GetAsync($"https://api.flightreader.com/v1/logs/{id}?limit=20&createdAfterId=5926331");
// Create a request signature used by the Flight Reader API to verify the request was
// initiated by you. This signature will expire 5 minutes after it's created.
var currentUnixTimeInSeconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var requestMethod = "GET";
var requestResource = $"/v1/logs/{id}";
var stringToSign = requestMethod + requestResource + currentUnixTimeInSeconds;
var signature = CreateSignature(stringToSign, secretApiKey);
using HttpClient client = new();
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {publicApiKey}");
client.DefaultRequestHeaders.Add("Api-Signature", signature);
client.DefaultRequestHeaders.Add("Api-Timestamp", currentUnixTimeInSeconds.ToString());
var response = await client.GetAsync($"https://api.flightreader.com/v1/logs/{id}");
if (response.IsSuccessStatusCode)
{
var responseBytes = await response.Content.ReadAsByteArrayAsync();
if (response.Content.Headers.ContentEncoding.Contains("gzip"))
{
using var compressedStream = new MemoryStream(responseBytes);
await using var decompressionStream = new GZipStream(compressedStream, CompressionMode.Decompress);
using var decompressedStream = new MemoryStream();
await decompressionStream.CopyToAsync(decompressedStream);
responseBytes = decompressedStream.ToArray();
}
var responseText = Encoding.UTF8.GetString(responseBytes);
Console.WriteLine(responseText);
}
else
{
Console.WriteLine($"Error: {response.StatusCode}");
}
}
private static string CreateSignature(string value, string key)
{
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
var dataBytes = Encoding.UTF8.GetBytes(value);
var hashBytes = hmac.ComputeHash(dataBytes);
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
}
}
{
"statusCode": 200,
"message": "GET Request successful.",
"result": [
{
"aircraftName": "Mavic 3",
"aircraftSerialNumber": "125A845TA35AF2AG0220",
"downloadUrl": "https://api.flightreader.com/v1/files/flight-logs/1d8a3d88433bf0a59537c2bc748f68710/DJIFlightRecord_2023-03-29_[12-28-24].txt",
"fileName": "DJIFlightRecord_2023-03-29_[12-28-24].txt",
"id": 5926331,
"maxHeight": 65,
"md5Hash": "436412e045c9ad2db38c18cfc4cb0149",
"timestamp": 1680107304788,
"totalDistance": 1485.5077,
"totalTime": 165400
},
{...},
{...}
]
}
<html>
<body>
<div id="output">Retrieving DJI account id...</div>
<script>
// Replace with your Flight Reader API secret key
const secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Note: You should never expose your API secret key like this in a production environment.
// Anyone who has access to it will be able to make API requests on your behalf.
// Set the DJI account credentials
const email = "[email protected]";
const password = "abc123";
const formData = new FormData();
formData.append("email", email);
formData.append("password", password);
async function retrieveDjiAccount() {
try {
const response = await fetch("https://api.flightreader.com/v1/accounts/dji", {
method: "POST",
body: formData,
headers: {
"Accept-Encoding": "gzip",
"Authorization": `Bearer ${secretApiKey}`
}
});
if (response.ok) {
const data = await response.json();
output.textContent = JSON.stringify(data.result);
} else {
output.textContent = `${response.status} ${response.statusText}`;
}
} catch (error) {
output.textContent = error;
}
}
retrieveDjiAccount();
</script>
</body>
</html>
<html>
<body>
<!-- https://github.com/brix/crypto-js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<div id="output">Retrieving DJI account id...</div>
<script>
// Replace with your Flight Reader API keys
const publicApiKey = "pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Note: You should never expose your API secret key like this in a production environment.
// Anyone who has access to it will be able to make API requests on your behalf.
// Set the DJI account credentials
const email = "[email protected]";
const password = "abc123";
async function retrieveDjiAccount() {
try {
const formData = new FormData();
formData.append("email", email);
formData.append("password", password);
// Create a request signature used by the Flight Reader API to verify the request was
// initiated by you. This signature will expire 5 minutes after it's created.
const signature = createSignature(formData);
const response = await fetch("https://api.flightreader.com/v1/accounts/dji", {
method: "POST",
body: formData,
headers: {
"Accept-Encoding": "gzip",
"Authorization": `Bearer ${publicApiKey}`,
"Api-Signature": signature.value,
"Api-Timestamp": signature.currentUnixTimeInSeconds
}
});
if (response.ok) {
const data = await response.json();
output.textContent = JSON.stringify(data.result);
} else {
output.textContent = `${response.status} ${response.statusText}`;
}
} catch (error) {
output.textContent = error;
}
}
function formDataToString(formData) {
const keyValuePairs = {};
for (const [key, value] of formData.entries()) {
if (!keyValuePairs[key]) {
keyValuePairs[key] = [value];
} else {
keyValuePairs[key].push(value);
}
}
return Object.entries(keyValuePairs)
.map(([key, values]) => `${key}=${values.join(",")}`)
.join("&");
}
function createSignature(formData) {
const currentUnixTimeInSeconds = Math.floor(Date.now() / 1000);
const requestMethod = "POST";
const requestResource = "/v1/accounts/dji";
const formDataString = formDataToString(formData);
const stringToSign = requestMethod + requestResource + formDataString + currentUnixTimeInSeconds;
const value = CryptoJS.HmacSHA256(stringToSign, secretApiKey).toString(CryptoJS.enc.Hex);
return { value, currentUnixTimeInSeconds };
}
retrieveDjiAccount();
</script>
</body>
</html>
using System.IO.Compression;
using System.Text;
internal class Program
{
private static async Task Main()
{
// Replace with your Flight Reader API secret key
const string secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Set the DJI account credentials
const string email = "[email protected]";
const string password = "abc123";
var formContent = new MultipartFormDataContent
{
{ new StringContent(email), "email" },
{ new StringContent(password), "password" }
};
using HttpClient client = new();
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {secretApiKey}");
var response = await client.PostAsync("https://api.flightreader.com/v1/accounts/dji", formContent);
if (response.IsSuccessStatusCode)
{
var responseBytes = await response.Content.ReadAsByteArrayAsync();
if (response.Content.Headers.ContentEncoding.Contains("gzip"))
{
using var compressedStream = new MemoryStream(responseBytes);
await using var decompressionStream = new GZipStream(compressedStream, CompressionMode.Decompress);
using var decompressedStream = new MemoryStream();
await decompressionStream.CopyToAsync(decompressedStream);
responseBytes = decompressedStream.ToArray();
}
var responseText = Encoding.UTF8.GetString(responseBytes);
Console.WriteLine(responseText);
}
else
{
Console.WriteLine($"Error: {response.StatusCode}");
}
}
}
using System.IO.Compression;
using System.Security.Cryptography;
using System.Text;
internal class Program
{
private static async Task Main()
{
// Replace with your Flight Reader API keys
const string publicApiKey = "pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const string secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Set the DJI account credentials
const string email = "[email protected]";
const string password = "abc123";
var formContent = new MultipartFormDataContent
{
{ new StringContent(email), "email" },
{ new StringContent(password), "password" }
};
// Create a request signature used by the Flight Reader API to verify the request was
// initiated by you. This signature will expire 5 minutes after it's created.
var currentUnixTimeInSeconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var requestMethod = "POST";
var requestResource = "/v1/accounts/dji";
var formData = await GetFormDataAsync(formContent);
var stringToSign = requestMethod + requestResource + formData + currentUnixTimeInSeconds;
var signature = CreateSignature(stringToSign, secretApiKey);
using HttpClient client = new();
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {publicApiKey}");
client.DefaultRequestHeaders.Add("Api-Signature", signature);
client.DefaultRequestHeaders.Add("Api-Timestamp", currentUnixTimeInSeconds.ToString());
var response = await client.PostAsync("https://api.flightreader.com/v1/accounts/dji", formContent);
if (response.IsSuccessStatusCode)
{
var responseBytes = await response.Content.ReadAsByteArrayAsync();
if (response.Content.Headers.ContentEncoding.Contains("gzip"))
{
using var compressedStream = new MemoryStream(responseBytes);
await using var decompressionStream = new GZipStream(compressedStream, CompressionMode.Decompress);
using var decompressedStream = new MemoryStream();
await decompressionStream.CopyToAsync(decompressedStream);
responseBytes = decompressedStream.ToArray();
}
var responseText = Encoding.UTF8.GetString(responseBytes);
Console.WriteLine(responseText);
}
else
{
Console.WriteLine($"Error: {response.StatusCode}");
}
}
private static async Task<string> GetFormDataAsync(MultipartFormDataContent formContent)
{
var formData = "";
var lastFieldName = "";
foreach (var content in formContent)
{
if (content is not StringContent stringContent)
{
continue;
}
var fieldName = content.Headers.ContentDisposition?.Name?.Trim('"');
if (fieldName != lastFieldName)
{
lastFieldName = fieldName;
if (formData.Length > 0)
{
formData += "&";
}
formData += $"{fieldName}=";
}
else
{
formData += ",";
}
formData += await stringContent.ReadAsStringAsync();
}
return formData;
}
private static string CreateSignature(string value, string key)
{
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
var dataBytes = Encoding.UTF8.GetBytes(value);
var hashBytes = hmac.ComputeHash(dataBytes);
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
}
}
{
"statusCode": 200,
"message": "POST Request successful.",
"result": {
"id": "a014f2df954b87acd647918c73a9cffc"
}
}
<html>
<body>
<div id="output">Retrieving API usage...</div>
<script>
// Replace with your Flight Reader API secret key
const secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// Note: You should never expose your API secret key like this in a production environment.
// Anyone who has access to it will be able to make API requests on your behalf.
async function retrieveApiUsage() {
try {
// The optional "limit" parameter can be appended to the URL like this:
//
// https://api.flightreader.com/v1/usage?limit=7
const response = await fetch(`https://api.flightreader.com/v1/usage`, {
headers: {
"Accept-Encoding": "gzip",
"Authorization": `Bearer ${secretApiKey}`
}
});
if (response.ok) {
const data = await response.json();
output.textContent = JSON.stringify(data.result);
} else {
output.textContent = `${response.status} ${response.statusText}`;
}
} catch (error) {
output.textContent = error;
}
}
retrieveApiUsage();
</script>
</body>
</html>
using System.IO.Compression;
using System.Text;
internal class Program
{
private static async Task Main()
{
// Replace with your Flight Reader API secret key
const string secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
using HttpClient client = new();
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {secretApiKey}");
// The optional "limit" parameter can be appended to the URL like this:
//
// https://api.flightreader.com/v1/usage?limit=7
var response = await client.GetAsync("https://api.flightreader.com/v1/usage");
if (response.IsSuccessStatusCode)
{
var responseBytes = await response.Content.ReadAsByteArrayAsync();
if (response.Content.Headers.ContentEncoding.Contains("gzip"))
{
using var compressedStream = new MemoryStream(responseBytes);
await using var decompressionStream = new GZipStream(compressedStream, CompressionMode.Decompress);
using var decompressedStream = new MemoryStream();
await decompressionStream.CopyToAsync(decompressedStream);
responseBytes = decompressedStream.ToArray();
}
var responseText = Encoding.UTF8.GetString(responseBytes);
Console.WriteLine(responseText);
}
else
{
Console.WriteLine($"Error: {response.StatusCode}");
}
}
}
{
"statusCode": 200,
"message": "GET Request successful.",
"result": {
"totalRequests": 9,
"requestsByDate": [
{
"date": "2023-08-31",
"totalRequests": 8,
"requests": [
{
"endpoint": "/accounts/dji",
"count": 2
},
{
"endpoint": "/logs/{id}",
"count": 6
}
]
},
{...},
{...}
]
}
}