Skip to content

API reference

Clients

DRSClient

DRSClient(
    api_key: str | None = None,
    *,
    base_url: str = DEFAULT_BASE_URL,
    timeout: float | Timeout = DEFAULT_TIMEOUT,
    max_retries: int = DEFAULT_MAX_RETRIES,
    http_client: Client | None = None,
)

Synchronous client for the FAA DRS API.

Parameters:

Name Type Description Default
api_key str | None

DRS API key. Defaults to the DRS_API_KEY environment variable.

None
base_url str

API root. Change only for testing.

DEFAULT_BASE_URL
timeout float | Timeout

Seconds, or an httpx.Timeout.

DEFAULT_TIMEOUT
max_retries int

Retries for connection errors, timeouts, HTTP 429 and 5xx.

DEFAULT_MAX_RETRIES
http_client Client | None

Your own httpx.Client. The client does not close it.

None
Example
from faa_drs import DRSClient, DocType

with DRSClient() as drs:
    for doc in drs.iter_documents(DocType.SAIB, limit=10):
        print(doc.number, doc.title)

list_documents

list_documents(
    doctype: str,
    *,
    offset: int = 0,
    modified_after: DateLike | None = None,
    sort: SortOrder | str | None = None,
    filters: Filters | None = None,
    keywords: Iterable[str] | str | None = None,
) -> Page

Get one page of up to 750 documents.

Without filters or keywords this calls GET /{doctype}. With them it calls POST /{doctype}/filtered.

Parameters:

Name Type Description Default
doctype str

Document type code, for example DocType.AC or "AC".

required
offset int

Number of documents to skip.

0
modified_after DateLike | None

Return only documents modified after this time (UTC).

None
sort SortOrder | str | None

Sort by last-modified date. None uses the API default sort.

None
filters Filters | None

Metadata filters, for example {"drs:status": ["Current"]}. Date fields take a (start, end) pair.

None
keywords Iterable[str] | str | None

Full-text search terms. A document matches if it has any term.

None

iter_pages

iter_pages(
    doctype: str,
    *,
    offset: int = 0,
    modified_after: DateLike | None = None,
    sort: SortOrder | str | None = DESC,
    filters: Filters | None = None,
    keywords: Iterable[str] | str | None = None,
) -> Iterator[Page]

Get all pages, one request per page.

The default sort is newest-modified first, and documents with no date come last. Paging uses offsets. With this order, an update to DRS during a long read can repeat a document but does not skip one that did not change. A document that changes during the read can be missed, but it is newer than the first document, so a later read with modified_after gets it. Use sort=None for the API default order.

iter_documents

iter_documents(
    doctype: str,
    *,
    offset: int = 0,
    modified_after: DateLike | None = None,
    sort: SortOrder | str | None = DESC,
    filters: Filters | None = None,
    keywords: Iterable[str] | str | None = None,
    limit: int | None = None,
) -> Iterator[Document]

Get all matching documents. Pages are requested as needed.

Parameters:

Name Type Description Default
limit int | None

Stop after this many documents.

None

Other arguments are the same as iter_pages.

get_attachments

get_attachments(source: Document | str) -> list[Attachment]

Get the additional attachments of a document.

Parameters:

Name Type Description Default
source Document | str

A Document, or the file id or download URL of its main file.

required

download

download(source: FileSource) -> bytes

Download a file into memory.

Parameters:

Name Type Description Default
source FileSource

A Document (its main file), an Attachment, a download URL or a file id.

required

download_to

download_to(
    source: FileSource, dest: str | PathLike[str]
) -> Path

Stream a file to disk and return its path.

If dest is an existing directory, or ends with /, the file is saved in it. The file name comes from the document or attachment, else from the response. The write is atomic. A partial file is never left at the destination.

AsyncDRSClient

AsyncDRSClient(
    api_key: str | None = None,
    *,
    base_url: str = DEFAULT_BASE_URL,
    timeout: float | Timeout = DEFAULT_TIMEOUT,
    max_retries: int = DEFAULT_MAX_RETRIES,
    http_client: AsyncClient | None = None,
)

Asynchronous client for the FAA DRS API.

The methods and arguments are the same as DRSClient.

Example
from faa_drs import AsyncDRSClient, DocType

async with AsyncDRSClient() as drs:
    async for doc in drs.iter_documents(DocType.SAIB, limit=10):
        print(doc.number, doc.title)

list_documents async

list_documents(
    doctype: str,
    *,
    offset: int = 0,
    modified_after: DateLike | None = None,
    sort: SortOrder | str | None = None,
    filters: Filters | None = None,
    keywords: Iterable[str] | str | None = None,
) -> Page

Get one page of up to 750 documents. See DRSClient.list_documents.

iter_pages async

iter_pages(
    doctype: str,
    *,
    offset: int = 0,
    modified_after: DateLike | None = None,
    sort: SortOrder | str | None = DESC,
    filters: Filters | None = None,
    keywords: Iterable[str] | str | None = None,
) -> AsyncIterator[Page]

Get all pages. See DRSClient.iter_pages.

iter_documents async

iter_documents(
    doctype: str,
    *,
    offset: int = 0,
    modified_after: DateLike | None = None,
    sort: SortOrder | str | None = DESC,
    filters: Filters | None = None,
    keywords: Iterable[str] | str | None = None,
    limit: int | None = None,
) -> AsyncIterator[Document]

Get all matching documents. See DRSClient.iter_documents.

get_attachments async

get_attachments(source: Document | str) -> list[Attachment]

Get the additional attachments of a document. See DRSClient.get_attachments.

download async

download(source: FileSource) -> bytes

Download a file into memory. See DRSClient.download.

download_to async

download_to(
    source: FileSource, dest: str | PathLike[str]
) -> Path

Stream a file to disk and return its path. See DRSClient.download_to.

Models

Page

Bases: _Model

One page of results. The API returns at most 750 documents per page.

next_offset property

next_offset: int | None

Offset of the next page, or None if this is the last page.

Document

Bases: _Model

One DRS document.

Common fields are typed attributes. Only guid is always present. Fields specific to the document type are in metadata, keyed by their API name (for example drs:title). The value _EMPTY_ from the API is converted to None.

content property

content: dict[str, str]

Full-text fields returned inline by the API, keyed by field name.

Empty for document types that publish their content only as a file. List values are joined with blank lines.

get_list

get_list(key: str) -> list[str]

Return a metadata value as a list of strings. None items are dropped.

get_date

get_date(key: str) -> date | None

Return a YYYY-MM-DD metadata value as a date.

Attachment

Bases: _Model

An additional file attached to a document.

SortOrder

Bases: StrEnum

Document types

DocType

Bases: StrEnum

DRS document type codes. Members are strings and work anywhere a code does.

catalog

Document types and their metadata fields.

Source: the FAA "DRS Document Types Metadata Mapping" spreadsheet, corrected against the live API.

DocTypeInfo dataclass

DocTypeInfo(
    code: str,
    name: str,
    service: str,
    sort_field: str | None,
    internal_only: bool,
    fields: Mapping[str, FieldInfo],
    content_fields: tuple[str, ...],
)

code instance-attribute

code: str

API code, for example AC.

name instance-attribute

name: str

Display name in the DRS web application.

service instance-attribute

service: str

FAA service or office, for example AIR or FS.

sort_field instance-attribute

sort_field: str | None

Field the API sorts by when no sort order is given.

internal_only instance-attribute

internal_only: bool

External API keys cannot read this type.

fields instance-attribute

fields: Mapping[str, FieldInfo]

Metadata fields, keyed by API name.

content_fields instance-attribute

content_fields: tuple[str, ...]

Fields that carry the full document text inline.

FieldInfo dataclass

FieldInfo(key: str, label: str, type: FieldType)

key instance-attribute

key: str

API name, for example drs:title.

label instance-attribute

label: str

Display name in the DRS web application.

FieldType

Bases: StrEnum

TEXT class-attribute instance-attribute

TEXT = 'TEXT'

A string or None.

ARRAY class-attribute instance-attribute

ARRAY = 'ARRAY'

A list of strings, or None.

DATE class-attribute instance-attribute

DATE = 'DATE'

A YYYY-MM-DD string, or None.

get_doctype

get_doctype(code: str) -> DocTypeInfo

Return the document type for a code.

Raises:

Type Description
KeyError

The catalog does not have the code.

find_doctype

find_doctype(code: str) -> DocTypeInfo | None

Return the document type for a code, or None if the catalog does not have it.

list_doctypes

list_doctypes(
    *,
    service: str | None = None,
    include_internal: bool = False,
) -> list[DocTypeInfo]

Return document types, sorted by code.

Parameters:

Name Type Description Default
service str | None

Return only this service, for example AIR.

None
include_internal bool

Include types that external API keys cannot read.

False

Errors

DRSError

Bases: Exception

Base class for all errors raised by this package.

UnknownFieldWarning

Bases: UserWarning

A filter field is not in the catalog for its document type.

The client sends the filter anyway, because the catalog can be behind the API. If the API does not know the field either, the request fails with BadRequestError.

InvalidQueryError

Bases: DRSError, ValueError

The query fails local validation. No request was sent.

DRSConnectionError

Bases: DRSError

The client cannot reach the DRS API.

DRSTimeoutError

Bases: DRSConnectionError

The request exceeded the configured timeout.

ResponseValidationError

Bases: DRSError

The API response does not have the expected shape.

APIError

APIError(
    message: str,
    *,
    status_code: int,
    response: Response | None = None,
)

Bases: DRSError

The DRS API rejected the request or returned an error message.

BadRequestError

BadRequestError(
    message: str,
    *,
    status_code: int,
    response: Response | None = None,
)

Bases: APIError

HTTP 400. Usually an invalid filter for the document type.

AuthenticationError

AuthenticationError(
    message: str,
    *,
    status_code: int,
    response: Response | None = None,
)

Bases: APIError

HTTP 403. The API key is missing, invalid or expired.

NotFoundError

NotFoundError(
    message: str,
    *,
    status_code: int,
    response: Response | None = None,
)

Bases: APIError

HTTP 404. The file or resource does not exist.

UnknownDocTypeError

UnknownDocTypeError(
    message: str,
    *,
    status_code: int,
    response: Response | None = None,
)

Bases: APIError

The document type is not present in DRS.

RestrictedDocTypeError

RestrictedDocTypeError(
    message: str,
    *,
    status_code: int,
    response: Response | None = None,
)

Bases: APIError

The document type is internal only. External API keys cannot read it.

RateLimitError

RateLimitError(
    message: str,
    *,
    status_code: int,
    response: Response | None = None,
)

Bases: APIError

HTTP 429.

ServerError

ServerError(
    message: str,
    *,
    status_code: int,
    response: Response | None = None,
)

Bases: APIError

HTTP 5xx, or a DRS system error message.