Flight Reader API Documentation

The Flight Reader API is organized around REST. The API has predictable resource-oriented URLs, accepts multipart form data request bodies, returns JSON-encoded responses, and uses standard HTTP response codes, Bearer authentication, and verbs.

Authentication

The Flight Reader API uses a Bearer token and optional request signing (required when using your public API key) to authenticate requests.All API requests must be made over HTTPS. Calls made over plain HTTP will fail. Requests to authenticated endpoints without a valid API key will fail. The DJI Cloud flight log download endpoint uses authorization embedded in the returned downloadUrl and does not require a separate Bearer header.Do not share your secret API key in publicly accessible areas like GitHub or client-side code. Anyone who has access to your secret API key will be able to make API requests on your behalf.
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 a website or in a client-side application. A request signature must be included in all requests using a public key.

Request Signing

When authenticating with a public API key, include the following headers. Requests authenticated with a secret API key do not require signing.

  • Authorization
    Use Bearer pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx with your public API key.
  • Api-Timestamp
    The current UTC Unix timestamp in seconds. The timestamp must be within five minutes of the API server's current time.
  • Api-Signature
    The lowercase hexadecimal HMAC-SHA256 signature calculated using the matching secret API key.

Construct the string to sign by concatenating HTTP method + request path + form data + timestamp, without additional separators:

  1. Use the uppercase HTTP method, such as GET or POST.
  2. Use the exact request path, including /v1 and actual route parameter values. Exclude the scheme, hostname, and query string.
  3. For multipart POST requests, join the text form fields as name=value pairs separated by &, in the order their distinct names first appear in the submitted form. Join repeated values for the same field with commas. Use the original field names and text values without URL encoding. Exclude uploaded files, file contents, and multipart boundaries. For requests without text form fields, use an empty string.
  4. Append the exact timestamp sent in Api-Timestamp.

Calculate HMAC-SHA256 over the UTF-8 bytes of this string, using the UTF-8 bytes of the matching secret API key as the HMAC key. Send the resulting lowercase hexadecimal digest in Api-Signature.

Generate signatures on your server so the secret API key stays private. A client using the public key sends the signature and timestamp supplied by your server. Requests with an invalid signature or timestamp return 401 Unauthorized.


Response Compression

By default, the Flight Reader API returns uncompressed responses. In order to reduce both the API response time and bandwidth consumption, you should include the Accept-Encoding header in all requests with a value of gzip (for Gzip compression) or br (for Brotli compression).

Errors

The Flight Reader API uses conventional HTTP response codes to indicate the success or failure of an API request. Codes in the 2xx range indicate success. Codes in the 4xx range indicate an error that failed given the information provided (e.g. a required parameter was omitted). Codes in the 5xx range indicate an error with Flight Reader's servers.The Flight Reader API raises exceptions for many reasons, such as invalid parameters, authentication errors, and network unavailability. You should ensure your code is able to gracefully handle all possible API exceptions.

Versioning

When backwards-incompatible changes are made to the API, a new version will be released. For example, version 1 (the current version) is accessible at https://api.flightreader.com/v1. When version 2 is released, it will be available at https://api.flightreader.com/v2.The following changes are considered to be backwards-compatible:
  • Adding a new API resource.
  • Adding a new optional request parameter to an existing API method.
  • Adding a new property to an existing API response.
  • Changing the order of properties in existing API responses.
  • Changing the length or format of strings in error messages, field descriptions, or other human-readable strings.

Resources

POST /v1/keys Non-Billable
Creates a new set of secret and public API keys.

GET /v1/keys Non-Billable
Retrieves all active API keys.

DELETE /v1/keys/{key} Non-Billable
Deletes a set of secret and public API keys.


GET /v1/fields Non-Billable
Retrieves a list of all available flight log fields.

GET /v1/fields/{field-name} Non-Billable
Retrieves a single flight log field by name.


POST /v1/logs Billable
Uploads a DJI TXT flight log file and returns the processed data in CSV format.

POST /v1/logs Billable
Processes a DJI Cloud download URL or DJI SmartFarm processing reference and returns the processed data in CSV format.


POST /v1/accounts/dji/cloud Billable
Retrieves a DJI Cloud account, which is required to list, download, or process flight logs stored in the DJI Cloud.

POST /v1/accounts/dji/smartfarm Billable
Retrieves a DJI SmartFarm account, which is required to list or process flight logs stored in the DJI SmartFarm.

GET /v1/logs/{id} Billable
Retrieves a list of flight logs from DJI Cloud or DJI SmartFarm.

GET /v1/files/flight-logs/{id}/{filename} Billable
Downloads a DJI TXT flight log from the DJI Cloud as a ZIP file.


GET /v1/usage Non-Billable
Retrieves a list of billable API requests made by your API account.

GET /v1/usage/{key} Non-Billable
Retrieves billable API usage for one key belonging to your API account.



Create API key

POST /v1/keys

Creates a new set of secret and public API keys in your account.

Returns

Returns a 201 Created JSON response with the newly created publicKey and secretKey in result.

POST /v1/keys

                                <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: {
                                                        "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}");
                                        }
                                    }
                                }
                            

Response

                                {
                                    "statusCode": 201,
                                    "message": "POST Request successful.",
                                    "result": {
                                        "publicKey": "pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                                        "secretKey": "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
                                    }
                                }
                            


Retrieve API keys

GET /v1/keys

Retrieves all active API keys from your account.

Returns

Returns a JSON response with an array of active API key pairs in result. Each pair includes publicKey, secretKey, and its creation time, createdUtc.

GET /v1/keys

                                <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: {
                                                        "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}");
                                        }
                                    }
                                }
                            

Response

                                {
                                    "statusCode": 200,
                                    "message": "GET Request successful.",
                                    "result": [
                                        {
                                            "publicKey": "pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                                            "secretKey": "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                                            "createdUtc": "2023-08-21T11:37:38Z"
                                        }
                                    ]
                                }
                            


Delete API keys

DELETE /v1/keys/{key}

Deletes a set of secret and public API keys from your account.

Route Parameters

  • key string Required
    Replace {key} with the secret or public API key from the key pair you want to delete.

Returns

Returns a 200 OK JSON response confirming that the API key pair was deleted. No resource data is returned in result.

DELETE /v1/keys/{key}

                                <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: {
                                                        "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}");
                                        }
                                    }
                                }
                            

Response

                                {
                                    "statusCode": 200,
                                    "message": "DELETE Request successful."
                                }
                            


Retrieve all flight log fields

GET /v1/fields

Retrieves a list of all available flight log fields. These field names can be used to specify which fields to return when processing a flight log.

Returns

Returns a JSON response with an array of available flight log fields in result. Each field includes its name and description.

GET /v1/fields

                                <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: {
                                                        "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: {
                                                        "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();
                                    }
                                }
                            

Response

                                {
                                    "statusCode": 200,
                                    "message": "GET Request successful.",
                                    "result": [
                                        {
                                            "name": "APP.message",
                                            "description": "An informational message generated by the application being used to control the aircraft."
                                        },
                                        {
                                            "name": "APP.tip",
                                            "description": "An informational message generated by the application being used to control the aircraft."
                                        }
                                    ]
                                }
                            


Retrieve flight log field

GET /v1/fields/{field-name}

Retrieves a single flight log field by name.

Route Parameters

  • field-name string Required
    Replace {field-name} with a field name returned by GET /v1/fields.

Returns

Returns a JSON response with the matching field's name and description in result. Returns 404 Not Found if the field does not exist.

GET /v1/fields/{field-name}

                                <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 "/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: {
                                                        "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 "/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: {
                                                        "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();
                                    }
                                }
                            

Response

                                {
                                    "statusCode": 200,
                                    "message": "GET Request successful.",
                                    "result": {
                                        "name": "OSD.isGpsUsed",
                                        "description": "When true, the aircraft is able to use the GPS satellite data for positioning purposes."
                                    }
                                }
                            


Process a flight log file

POST /v1/logs

Upload a DJI TXT flight log or a ZIP containing a DJI TXT log. The file should be named like DJIFlightRecord_2022-05-16_[19-02-56].txt or DJIFlightRecord_2022-05-16_[19-02-56].zip.

Multipart Form Fields

  • file file Required
    The DJI TXT flight log or ZIP containing a DJI TXT flight log. Include the original filename in the multipart file part.
  • fields array of strings
    Optional. Repeat the fields form field for each CSV column you want to include, using field names from GET /v1/fields. For best performance, specify only the flight log fields you need included in the returned CSV file. Omitting this field returns the default field set. Field availability depends on the telemetry data contained in the flight log.

Returns

Returns the processed flight log as a downloadable CSV file with a .csv filename and content type text/plain. The CSV contains the selected fields, or the default field set if none were supplied. Read the response as text or file bytes.

Privacy and Data Handling

Flight logs are processed entirely in memory and are retained only for the duration of processing. Neither the uploaded flight log file nor its processed contents are logged or permanently stored on Flight Reader API servers.

POST /v1/logs

                                <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 "/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 to use the default field set
                                                fields.forEach((value, index) => {
                                                    formData.append("fields", value);
                                                });

                                                const response = await fetch("https://api.flightreader.com/v1/logs", {
                                                    method: "POST",
                                                    body: formData,
                                                    headers: {
                                                        "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 {
                                                    const errorBody = await response.text();
                                                    output.textContent =
                                                        `${response.status} ${response.statusText}\n${errorBody}`;
                                                }
                                            } 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 "/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 to use the default field set
                                                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: {
                                                        "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 {
                                                    const errorBody = await response.text();
                                                    output.textContent =
                                                        `${response.status} ${response.statusText}\n${errorBody}`;
                                                }
                                            } 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 to use the default field set)
                                        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);

                                        if (response.IsSuccessStatusCode)
                                        {
                                            // The successful response contains CSV data
                                            Console.WriteLine(responseText);
                                        }
                                        else
                                        {
                                            Console.WriteLine($"Error: {(int)response.StatusCode} {response.ReasonPhrase}");
                                            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 to use the default field set)
                                        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);

                                        if (response.IsSuccessStatusCode)
                                        {
                                            // The successful response contains CSV data
                                            Console.WriteLine(responseText);
                                        }
                                        else
                                        {
                                            Console.WriteLine($"Error: {(int)response.StatusCode} {response.ReasonPhrase}");
                                            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();
                                    }
                                }
                            

Response

                                OSD.flyTime [ms],OSD.latitude,OSD.longitude
                                100,53.62646476704494,16.87070193398017
                                300,53.62646474133018,16.87070199143842
                                500,53.62646469232834,16.870702037681247
                                ...
                            


Process a flight log URL

POST /v1/logs

To process a flight log using its URL, submit the complete downloadUrl returned by GET /v1/logs/{id} as the url multipart form field in a POST /v1/logs request.

This feature supports flight logs from DJI Cloud, DJI SmartFarm, and third-party websites. The API automatically downloads the flight log, processes its telemetry and metadata, and returns the results as a CSV file.

Multipart Form Fields

  • url string Required
    The complete flight log download URL or DJI SmartFarm processing reference. Use the complete downloadUrl returned by GET /v1/logs/{id}, or a supported third-party URL. Submit either url or file; an uploaded file takes precedence if both are provided.
  • fields array of strings
    Optional. Repeat the fields form field for each CSV column you want to include, using names from GET /v1/fields. For best performance, specify only the flight log fields you need included in the returned CSV file. Omitting this field returns the default field set. Field availability depends on the telemetry data contained in the flight log.

Supported URLs

The following URLs can be used:

  • DJI Cloud: Use the complete downloadUrl value returned by the GET /v1/logs/{id} endpoint.
  • DJI SmartFarm: Use the complete downloadUrl value returned by the GET /v1/logs/{id} endpoint.
  • Third-party websites: DJI TXT flight logs and ZIP files containing DJI TXT flight logs can also be downloaded from any publicly accessible third-party website.

Required Filename Format

All flight log filenames must follow the naming format DJIFlightRecord_YYYY-MM-DD_[HH-mm-ss] and have a .TXT or .ZIP file extension for DJI TXT flight logs or a .RAW file extension for DJI SmartFarm flight logs.

For example:

  • DJIFlightRecord_2026-10-09_[14-30-00].txt
  • DJIFlightRecord_2026-10-09_[14-30-00].zip
  • DJIFlightRecord_2026-10-09_[14-30-00].raw

Returns

Returns the processed flight log as a downloadable CSV file with a .csv filename and content type text/plain. The CSV contains the selected fields, or the default field set if none were supplied. Read the response as text or file bytes. Returns 404 Not Found if the flight log cannot be downloaded.

Privacy and Data Handling

Flight logs are processed entirely in memory and are retained only for the duration of processing. Neither the original flight log nor its processed contents are logged or permanently stored on Flight Reader API servers.

POST /v1/logs

                                <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 complete downloadUrl returned by the "/v1/logs/{id}" endpoint
                                        // for DJI Cloud or DJI SmartFarm flights. Alternatively, use a direct URL to a
                                        // DJI TXT flight log hosted on your own website or another third-party website, like
                                        // https://www.YourWebsite.com/DJIFlightRecord_2023-03-29_[12-28-24].txt                                    
                                        const flightLogUrl = "https://api.flightreader.com/v1/files/flight-logs/01234567890123456789/DJIFlightRecord_2023-03-29_[12-28-24].txt";

                                        // Call the "/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 to use the default field set
                                                fields.forEach((value, index) => {
                                                    formData.append("fields", value);
                                                });

                                                const response = await fetch("https://api.flightreader.com/v1/logs", {
                                                    method: "POST",
                                                    body: formData,
                                                    headers: {
                                                        "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 {
                                                    const errorBody = await response.text();
                                                    output.textContent =
                                                        `${response.status} ${response.statusText}\n${errorBody}`;
                                                }
                                            } 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 complete downloadUrl returned by GET /v1/logs/{id} (Cloud or SmartFarm)
                                        const flightLogUrl = "https://www.YourWebsite.com/DJIFlightRecord_2020-05-16_[19-02-56].txt";

                                        // Call the "/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 to use the default field set
                                                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: {
                                                        "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 {
                                                    const errorBody = await response.text();
                                                    output.textContent =
                                                        `${response.status} ${response.statusText}\n${errorBody}`;
                                                }
                                            } 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 to use the default field set)
                                        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);

                                        if (response.IsSuccessStatusCode)
                                        {
                                            // The successful response contains CSV data
                                            Console.WriteLine(responseText);
                                        }
                                        else
                                        {
                                            Console.WriteLine($"Error: {(int)response.StatusCode} {response.ReasonPhrase}");
                                            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 to use the default field set)
                                        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);

                                        if (response.IsSuccessStatusCode)
                                        {
                                            // The successful response contains CSV data
                                            Console.WriteLine(responseText);
                                        }
                                        else
                                        {
                                            Console.WriteLine($"Error: {(int)response.StatusCode} {response.ReasonPhrase}");
                                            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();
                                    }
                                }
                            

Response

                                OSD.flyTime [ms],OSD.latitude,OSD.longitude
                                100,53.62646476704494,16.87070193398017
                                300,53.62646474133018,16.87070199143842
                                500,53.62646469232834,16.870702037681247
                                ...
                            


Retrieve DJI Cloud account

POST /v1/accounts/dji/cloud

Retrieves the unique ID associated with a DJI Cloud account. Submit the DJI account's email and password as multipart form fields. The returned result.id can then be used with GET /v1/logs/{id} to retrieve the account's flight logs.

Multipart Form Fields

  • email string Required
    The email address for the DJI Cloud account.
  • password string Required
    The password for the DJI Cloud account.

Credential Storage and Token Renewal

For security, the DJI account's email, password, and authentication token are stored together in AWS Systems Manager Parameter Store as an encrypted SecureString.

If a DJI request fails because its authentication token is invalid or expired, the API automatically uses the stored credentials to obtain a new token and retries the failed request once.

If authentication or the retry fails, you can reconnect the DJI Cloud account by submitting its current email and password to this endpoint again. The existing account ID is preserved, so there's no need to update any references to that account in your application.

Returns

Returns a JSON response with the DJI Cloud account ID in result.id. Use this ID to retrieve the account's flight log list. If the account is already registered, the existing ID is returned.

POST /v1/accounts/dji/cloud

Response

                                {
                                    "statusCode": 200,
                                    "message": "POST Request successful.",
                                    "result": {
                                        "id": "a014f2df954b87acd647918c73a9cffc"
                                    }
                                }
                            


Retrieve DJI SmartFarm account

POST /v1/accounts/dji/smartfarm

Retrieves the unique ID associated with a DJI SmartFarm account. Submit the DJI account's email and password as multipart form fields. The returned result.id can then be used with GET /v1/logs/{id} to retrieve the account's flight logs.

Multipart Form Fields

  • email string Required
    The email address for the DJI SmartFarm account.
  • password string Required
    The password for the DJI SmartFarm account.

Credential Storage and Token Renewal

For security, the DJI account's email, password, and authentication token are stored together in AWS Systems Manager Parameter Store as an encrypted SecureString.

If a DJI request fails because its authentication token is invalid or expired, the API automatically uses the stored credentials to obtain a new token and retries the failed request once.

If authentication or the retry fails, you can reconnect the DJI SmartFarm account by submitting its current email and password to this endpoint again. The existing account ID is preserved, so there's no need to update any references to that account in your application.

Returns

Returns a JSON response with the DJI SmartFarm account ID in result.id. Use this ID to retrieve the account's flight log list. If the account is already registered, the existing ID is returned.

POST /v1/accounts/dji/smartfarm

Response

                                {
                                    "statusCode": 200,
                                    "message": "POST Request successful.",
                                    "result": {
                                        "id": "a014f2df954b87acd647918c73a9cffc"
                                    }
                                }
                            



Retrieve flight log list

GET /v1/logs/{id}

Retrieves flight logs from DJI Cloud or SmartFarm, based on the account id returned by POST /v1/accounts/dji/cloud or POST /v1/accounts/dji/smartfarm.

Pass the complete downloadUrl to POST /v1/logs to obtain CSV.

Route Parameters

URL Parameters

  • limit integer
    The maximum number of flights to return. The default is 200.
  • createdAfterId integer
    Returns flights with an ID greater than the specified value. Set to 0 to retrieve the oldest available flights, up to the specified limit. For incremental imports, use the highest flight ID returned in the previous batch.
  • createdAfterTimestamp integer
    Returns flights created after the specified timestamp. For DJI Cloud accounts, provide the timestamp in Unix milliseconds. For DJI SmartFarm accounts, provide the timestamp in Unix seconds.

Returns

Returns a JSON response with an array of flight logs in result. Each entry includes id, fileName, downloadUrl, aircraftName, aircraftSerialNumber, timestamp, md5Hash, and available flight statistics: maxHeight, totalDistance, and totalTime. Use the complete downloadUrl to download or process a flight log.

GET /v1/logs/{id}

                                <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 /v1/accounts/dji/cloud or /v1/accounts/dji/smartfarm to retrieve this 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: {
                                                        "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 /v1/accounts/dji/cloud or /v1/accounts/dji/smartfarm to retrieve this 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: {
                                                        "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/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 /v1/accounts/dji/cloud or /v1/accounts/dji/smartfarm to retrieve this 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 /v1/accounts/dji/cloud or /v1/accounts/dji/smartfarm to retrieve this 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();
                                    }
                                }
                            

Response
                    
                        {
                            "statusCode": 200,
                            "message": "GET Request successful.",
                            "result": [
                                {
                                    "aircraftName": "Mavic 3",
                                    "aircraftSerialNumber": "125A845TA35AF2AG0220",
                                    "downloadUrl": "https://api.flightreader.com/v1/files/flight-logs/01234567890123456789/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
                                }
                            ]
                        }
                    
                


Download a DJI Cloud flight log

GET /v1/files/flight-logs/{id}/{filename}

Downloads the original DJI TXT flight log from DJI Cloud. Use the complete downloadUrl returned by GET /v1/logs/{id} to request the download. The URL provides download authorization, so a separate Bearer header is not required. Keep the URL private.

Route Parameters

  • id string Required
    The download authorization identifier embedded in the returned downloadUrl. Preserve this value exactly; do not substitute an account ID or flight ID.
  • filename string Required
    The original DJI TXT flight log filename embedded in the returned downloadUrl. Preserve the filename and its URL encoding exactly.

Returns

Returns a downloadable ZIP file containing the original DJI TXT flight log, with content type application/zip and a .zip attachment filename. Read the response as file bytes. Returns 404 Not Found if the download is invalid or unavailable.


Retrieve API usage

GET /v1/usage

Retrieves a list of billable API requests made by your API account. Returns usage across all API keys belonging to your account.

URL Parameters

  • limit integer
    Sets the maximum number of days to retrieve. The default value is 30.

Returns

Returns a JSON response with account-wide usage in result for the requested number of days. It includes totalRequests, counts grouped by API key in requestsByKey, and daily totals and request counts in requestsByDate.

GET /v1/usage

                                <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: {
                                                        "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}");
                                        }
                                    }
                                }
                            

Response

                                {
                                    "statusCode": 200,
                                    "message": "GET Request successful.",
                                    "result": {
                                        "totalRequests": 8,
                                        "requestsByDate": [
                                            {
                                                "date": "2023-08-31",
                                                "totalRequests": 8,
                                                "requests": [
                                                    {
                                                        "endpoint": "/accounts/dji",
                                                        "count": 2
                                                    },
                                                    {
                                                        "endpoint": "/logs/{id}",
                                                        "count": 6
                                                    }
                                                ]
                                            }
                                        ]
                                    }
                                }
                            


Retrieve API usage for a key

GET /v1/usage/{key}

Retrieves a list of billable API requests made using a single API key belonging to your API account.

Route Parameters

  • key string Required
    Replace {key} in the route with the API key whose usage you want to retrieve.

URL Parameters

  • limit integer
    Sets the maximum number of days to retrieve. The default value is 30.

Returns

Returns a JSON response with usage for the specified API key in result for the requested number of days. It includes totalRequests, counts, and daily totals and request counts in requestsByDate.

GET /v1/usage/{key}

                                <html>

                                <body>
                                    <div id="output">Retrieving API usage for a key...</div>

                                    <script>
                                        // Replace with your Flight Reader API secret key
                                        const secretApiKey = "sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
                                        // Replace with the API key whose usage you want to retrieve
                                        const apiKey = "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/{key}?limit=7

                                                const response = await fetch(`https://api.flightreader.com/v1/usage/${encodeURIComponent(apiKey)}`, {
                                                    headers: {
                                                        "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";
                                        // Replace with the API key whose usage you want to retrieve
                                        const string apiKey = "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/{key}?limit=7

                                        var response = await client.GetAsync($"https://api.flightreader.com/v1/usage/{Uri.EscapeDataString(apiKey)}");

                                        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}");
                                        }
                                    }
                                }
                            

Response

                                {
                                    "statusCode": 200,
                                    "message": "GET Request successful.",
                                    "result": {
                                        "totalRequests": 8,
                                        "requestsByDate": [
                                            {
                                                "date": "2023-08-31",
                                                "totalRequests": 8,
                                                "requests": [
                                                    {
                                                        "endpoint": "/accounts/dji",
                                                        "count": 2
                                                    },
                                                    {
                                                        "endpoint": "/logs/{id}",
                                                        "count": 6
                                                    }
                                                ]
                                            }
                                        ]
                                    }
                                }