APIs: Concepts, Design, Requests, Responses, and Integration

Download API

Learn how download API endpoints retrieve protected files and exports, including authentication, streaming, redirects, headers, errors, retries, and integrity checks.

A download endpoint is an API route that returns a file or provides access to file content. The downloaded resource might be a document, image, archive, binary asset, or generated export.

Downloading is different from retrieving metadata. A metadata request usually returns JSON describing a file, such as its name, size, type, or status. A download request returns the file's bytes directly, redirects to a file location, or returns a temporary URL that the client must fetch separately.

How a download API works

A typical protected download follows this sequence:

  1. The client identifies a file, object, export, or other resource.
  2. The client sends an authenticated request to the download endpoint.
  3. The API validates the identifier and checks the caller's permissions.
  4. The API either streams the file, redirects to storage, or returns a separate download location.
  5. The client checks the response before saving or processing the bytes.
  6. The client streams the content to a destination and verifies that the transfer completed correctly.

Use HTTPS whenever credentials or private file content are involved. The exact HTTP method, path, parameter names, and authentication scheme must come from the API contract. The examples below use conventional placeholders rather than claiming a fixed endpoint design.

Download request structure

A download request contains an HTTP method, an endpoint path, a resource identifier, optional parameters, and authentication headers. Many download routes use GET because the operation reads a resource, but an API may define another method when a request body or export-generation action is required.

FieldLocationRequiredDescriptionExample
HTTP methodRequest lineAPI-definedThe method used to initiate delivery.GET
Resource identifierPath or queryUsually yesIdentifies the file, object, export, or document.resource-123
Version or revisionQuery or pathOptionalSelects a particular version when the API supports versioned resources.version=4
FormatQuery or headerOptionalRequests an available representation or export format.format=pdf
AuthorizationRequest headerProtected routesCredentials proving the caller's identity and permissions.Bearer <access-token>
AcceptRequest headerOptionalIndicates which media types the client can receive.application/pdf

A path parameter is part of the route, such as /resources/{resource-id}/download. A query parameter follows a question mark, such as ?version=4. Request headers carry authentication, content negotiation, tracing, or client-specific information.

Identifying and validating the resource

The identifier must use the format specified by the API. It may be a numeric ID, UUID, opaque token, object key, or export job ID. Validate identifiers before sending them, encode reserved characters correctly, and do not substitute a user-controlled value into a filesystem path without validation.

Optional version, format, or revision values should also be validated against the API's supported values. An unsupported value can produce a client error, while an unavailable version may produce a not-found or conflict response.

If the resource does not exist, has been deleted, has expired, is still being generated, or is not downloadable, the API should return an error response rather than file bytes. Do not assume that a visible metadata record is automatically downloadable; download authorization may be checked separately.

HTTP request example

The following illustrative command assumes a GET route and a path identifier. Replace the route, method, parameters, and authentication format with those defined by the API.

curl --fail --location \
  --header "Authorization: Bearer <access-token>" \
  --header "Accept: application/octet-stream" \
  "https://api.example.test/resources/<resource-id>/download" \
  --output "downloaded-resource.bin"

--location follows HTTP redirects and --output writes the response to a local file. Redirect behavior must be configured carefully: credentials should not be forwarded to an unrelated host unless the client and API explicitly permit that behavior.

Interpreting the response

The HTTP response body is the payload returned by the server. For a download, it is often binary data: bytes that represent a PDF, image, archive, spreadsheet, or other file. Binary data should be read as bytes, not decoded as text or parsed as JSON.

Check the status code and relevant headers before creating a file. An authentication or validation error may itself be JSON or HTML. Saving that error body as a file can produce a file with the expected extension but invalid content.

Status codeMeaningClient action
200 OKFile content was returned successfully.Read the binary body, save or stream it, then verify completion.
206 Partial ContentA requested byte range was returned.Combine it with the correct offset when implementing resume support.
3xxThe file is available at another location, often a storage URL.Follow redirects only under safe policy, or fetch the returned location before it expires.
400 Bad RequestParameters, identifier syntax, or requested options are invalid.Correct the request; do not retry unchanged.
401 UnauthorizedCredentials are missing, invalid, or expired.Refresh or replace credentials, then retry only when appropriate.
403 ForbiddenThe caller is authenticated but lacks permission.Check scopes, roles, ownership, and resource-level access.
404 Not FoundThe identifier or downloadable representation does not exist or is unavailable.Confirm the identifier and resource state.
409 or 425The resource may be in a conflicting or not-yet-ready state.Check the documented workflow, such as waiting for export completion.
408 or 504The request or upstream service timed out.Use streaming, suitable timeouts, and bounded retries.
429 Too Many RequestsThe client exceeded a rate limit.Honor Retry-After when present and apply backoff.
5xxThe service or an upstream storage system failed.Retry transient failures with exponential backoff and a limit.

Important response headers

HeaderPurposeClient handling
Content-TypeIdentifies the media type of the returned content.Use it to select handling logic and reject unexpected error formats.
Content-LengthIndicates the expected body size in bytes when known.Track progress and compare the final byte count; it may be absent for streamed or chunked responses.
Content-DispositionCan indicate attachment behavior and a suggested filename.Parse the filename safely; treat it as untrusted input.
Content-RangeDescribes the returned byte interval for a range response.Use it to place partial data at the correct offset.
ETag or Last-ModifiedIdentifies a representation for caching or change detection.Use conditional requests only as documented.
Cache-ControlControls caching behavior and freshness.Respect private, no-store, and expiration directives for sensitive files.
LocationProvides the next URL for a redirect or separate download location.Fetch it promptly, because a signed URL may expire.
Digest or API checksum headerMay provide an integrity value.Compare the calculated checksum with the published value.

Direct responses, redirects, and signed URLs

An API can deliver a file in three common ways:

  • Direct streaming: the successful response body contains the file bytes.
  • HTTP redirect: a 3xx response points to a storage provider. The client follows it and receives the file from the new location.
  • Separate download location: the API returns JSON containing a temporary URL. The client then makes a second request to that URL.

A signed URL is a time-limited URL that grants controlled access to a resource. Treat it like a credential: do not put it in logs, analytics events, public pages, tickets, or chat messages. Check its expiry and host before fetching it.

Saving and streaming content

For small files, a client may read the complete response into memory and then write it to disk. For large exports and archives, use streaming: process chunks as they arrive and write each chunk immediately. Streaming limits memory use and allows progress reporting.

response = send_download_request(url, headers)

if response.status_code not in [200, 206]:
    raise DownloadError("Download failed: inspect status and error body")

content_type = response.headers.get("Content-Type", "")
if content_type indicates an unexpected JSON or HTML error:
    raise DownloadError("Server returned an error payload")

filename = safe_filename(
    response.headers.get("Content-Disposition"),
    fallback="download.bin"
)
output_path = choose_allowed_destination(filename)
bytes_written = 0

with open(output_path, "wb") as output:
    for chunk in response.stream_chunks():
        output.write(chunk)
        bytes_written += len(chunk)

verify_length_or_checksum(output_path, response.headers, bytes_written)

Choose the destination directory explicitly. Prefer an application-controlled directory, prevent path traversal such as ../, remove directory components, reject unsafe characters where appropriate, and avoid blindly trusting a server-provided filename. A filename extension is not proof of file type.

Checking completion and integrity

A completed network request is not always proof of a valid file. Compare the number of bytes written with Content-Length when present. If the API publishes a checksum, calculate the same checksum locally and compare the values. For range downloads, verify every range, offset, and final total.

When no length or checksum is available, use format-specific validation where possible, such as opening an archive in a safe inspection tool or checking a file signature. Do not execute an untrusted download merely to test it.

Authentication and authorization

Protected downloads commonly use a bearer access token in the Authorization header, an API key header, a mutually authenticated connection, or an authenticated session cookie. Use the mechanism documented by the service and send credentials only over HTTPS.

Authentication establishes who the caller is. Authorization determines whether that caller may download the particular resource. The server should check ownership, organization membership, roles, scopes, resource state, and any download-specific policy before returning content.

  • 401 commonly indicates missing, malformed, invalid, or expired credentials.
  • 403 commonly indicates valid authentication without sufficient permission.
  • A token may authenticate successfully for metadata while lacking the scope required for file content.

Never place long-lived credentials in a URL query string. Avoid logging authorization headers and signed URLs. If a redirect crosses hosts, ensure that the client does not accidentally send the original API credential to the storage host.

Retries, rate limits, and operational behavior

Retry only failures that may be temporary, such as selected 429, 502, 503, 504, connection resets, or timeouts. Use exponential backoff with jitter, a maximum attempt count, and an overall deadline. Do not repeatedly retry invalid identifiers, malformed parameters, or permission failures.

Honor Retry-After when supplied. Configure separate connection and read timeouts, because a large file may take a long time to transfer after the connection succeeds. Stream the response so that slow transfers do not cause unnecessary memory growth.

Check whether the API supports range requests, which request only a specified byte interval using the Range header. A server that supports ranges typically responds with 206 Partial Content and a Content-Range header. Range support can enable resumable downloads after interruption, but a client must validate offsets and avoid combining pieces from different file versions.

If ranges, resumable transfers, or checksums are not documented, do not assume they work. A server may ignore Range and return 200, or it may require an upload/export job workflow before a download becomes available.

Practical download patterns

Authenticated file download

Send the resource identifier with the documented authorization header. Check for a successful file response, select a safe local filename from Content-Disposition or a controlled fallback, and stream the body to disk.

Streaming a large export

For a report or archive that may exceed available memory, write each response chunk as it arrives. Record the expected length, checksum, or export version, and retain enough state to determine whether a retry must restart or can resume.

Handling a storage redirect

Follow a documented redirect or read the temporary URL returned by the API. Fetch it before expiration, validate the destination policy, and do not forward the API's bearer token to the storage provider unless explicitly required.

Checking response type before saving

Check the status code first, then inspect Content-Type. If a supposed download returns application/json or text/html, parse it as an error or control response instead of saving it with a file extension.

Security considerations

  • Use HTTPS for authenticated requests and private content.
  • Keep access tokens, API keys, cookies, and signed URLs out of source control, logs, URLs, screenshots, and client-visible error messages.
  • Perform authorization checks before making file content available, including when generating a signed URL.
  • Treat downloaded files as untrusted. Scan or sandbox them when appropriate, restrict file permissions, and do not execute them automatically.
  • Prevent path traversal and unsafe overwrites when using server-provided filenames.
  • Apply size limits, timeout limits, and storage quotas to protect the client from unexpectedly large responses.
  • Validate the content type, file signature, size, and checksum where possible; never rely on a filename extension alone.

Troubleshooting

The request returns an authorization error

Check whether the credential is present, correctly formatted, valid, unexpired, and issued for the correct environment. Verify token scopes, roles, organization membership, and resource-level permissions. A valid token can still receive 403 when it cannot access that file.

The downloaded file is empty, incomplete, or corrupted

The client may have saved an error payload, stopped reading before the response ended, or lost the connection. Check the status code and Content-Type, compare the byte count with Content-Length, validate the checksum if available, and retry or resume when supported.

The client receives a redirect instead of file data

The API may delegate delivery to a storage service. Enable safe redirect handling or fetch the returned location explicitly. Confirm that the URL is still valid and has not expired, and prevent credentials from being sent to an unintended host.

The request returns not found

Confirm the identifier, URL encoding, version, and revision. The resource may have been deleted, expired, not yet generated, or marked as non-downloadable. Also verify that the authenticated caller is allowed to view it; some services intentionally conceal unauthorized resources as not found.

Large downloads consume too much memory or time out

The client may be buffering the complete body. Switch to streamed I/O, use appropriate read timeouts, write to a controlled destination, and use range or resumable downloads if the API documents them.

Exam-relevant notes

  • A download response body is often binary data, not JSON.
  • Content-Type describes the media type; Content-Length describes the expected size when known; Content-Disposition may provide attachment behavior and a filename.
  • 401 concerns authentication, while 403 generally concerns authorization.
  • A redirect or signed URL means the first API response may not contain the file bytes.
  • Streaming is preferred for large files because it avoids buffering the entire response in memory.
  • Checksums, byte counts, and range metadata help detect truncation and corruption.
  • Use HTTPS and protect credentials and temporary URLs as sensitive information.

Related API concepts include fetching resources, account access, and webhooks for asynchronous export status.