Skip to main content

Installation

uv add factify
Requirements: Python 3.8+

Client Setup

import os
from factify import Factify

factify = Factify(bearer_auth=os.environ["FACTIFY_KEY"])
The SDK supports both synchronous and asynchronous usage. Use the client as a context manager for proper resource cleanup:
with Factify(bearer_auth=os.environ["FACTIFY_KEY"]) as factify:
    result = factify.documents.list()

Configuration Options

OptionTypeDefaultDescription
bearer_authstrAPI key (required). Format: ffy_...
server_urlstrhttps://api.factify.comAPI base URL
timeout_msintNoneRequest timeout in milliseconds
retry_configRetryConfigSDK defaultRetry strategy configuration
from factify import Factify
from factify.utils import BackoffStrategy, RetryConfig

factify = Factify(
    bearer_auth=os.environ["FACTIFY_KEY"],
    server_url="https://api.factify.com",
    timeout_ms=30000,
    retry_config=RetryConfig(
        strategy="backoff",
        backoff=BackoffStrategy(
            initial_interval=1,
            max_interval=50,
            exponent=1.1,
            max_elapsed_time=100,
        ),
    ),
)

Available Resources

Documents

factify.documents.list(page_size=, query=, created_by_id=, access_level=, processing_status=, sort=, ownership=, trash_state=)
factify.documents.create(title=, payload={"file_name": ..., "content": ...})
factify.documents.get(document_id=)
factify.documents.update(document_id=, title=, description=)
factify.documents.export(document_id=)
factify.documents.process(document_id=)
factify.documents.trash(document_id=)
factify.documents.untrash(document_id=)
factify.documents.transfer_ownership(document_id=, new_owner_user_id=)
factify.documents.list_duplicates(document_id=)
factify.documents.get_quota()

Versions

factify.versions.list(document_id=)
factify.versions.create(document_id=, payload={"file_name": ..., "content": ...})
factify.versions.get(version_id=)
factify.versions.update(version_id=, description=)

Organizations

factify.organizations.list()
factify.organizations.get(organization_id=)
factify.organizations.update(organization_id=, name=)
factify.organizations.get_public_profile(organization_id=)

Members

factify.organizations.members.list(organization_id=)
factify.organizations.members.add(organization_id=, user_id=, role=)
factify.organizations.members.update(organization_id=, user_id=, role=)
factify.organizations.members.remove(organization_id=, user_id=)

Invites

factify.organizations.invites.list(organization_id=)
factify.organizations.invites.create(organization_id=, email=, role=)
factify.organizations.invites.accept(organization_id=)
factify.organizations.invites.resend(organization_id=, invite_id=)
factify.organizations.invites.revoke(organization_id=, invite_id=)

API Keys

factify.api_keys.list(organization_id=)
factify.api_keys.create(organization_id=, name=)
factify.api_keys.revoke(api_key_id=)

Sharing

factify.sharing.list(document_id=)
factify.sharing.grant(document_id=, recipient_id=, role=)
factify.sharing.update(document_id=, recipient_id=, role=)
factify.sharing.revoke(document_id=, recipient_id=)
factify.sharing.get_general_access(document_id=)
factify.sharing.set_general_access(document_id=, access_level=)
factify.sharing.create_share_link(document_id=)

Policies

factify.policies.list(document_id=)
factify.policies.attach(document_id=, kind=)
factify.policies.detach(document_id=, policy_id=)

Access Requests

factify.access_requests.list(document_id=)
factify.access_requests.create(document_id=)
factify.access_requests.check_status(document_id=)
factify.access_requests.approve(document_id=, access_request_id=)
factify.access_requests.deny(document_id=, access_request_id=)
factify.access_requests.inspect(document_id=)

Usage & Quotas

factify.usage.get()
factify.usage.get_history()
factify.usage.list_key_quotas()
factify.usage.set_key_quota(api_key_id=, monthly_limit=)
factify.usage.delete_key_quota(api_key_id=)

Timelines

factify.timelines.get(document_id=)

Users

factify.users.get_me()
factify.users.preferences.get()

Pagination

List endpoints support manual pagination via .next():
result = factify.documents.list(page_size=10)

while result is not None:
    for doc in result.documents:
        print(doc.title)
    result = result.next()

File Uploads

Pass a file stream as the content field:
with open("./report.pdf", "rb") as f:
    result = factify.documents.create(
        title="Q4 Financial Report",
        payload={"file_name": "report.pdf", "content": f},
    )
Using streams is recommended for large files to avoid loading the entire file into memory.

Error Handling

from factify import Factify
from factify.models import errors

try:
    doc = factify.documents.get(document_id="doc_abc123")
except errors.ErrorT as e:
    print(e.data.error)
    print(e.status_code)
except errors.FactifyError as e:
    print(e.message)
    print(e.status_code)
Error ClassWhen
FactifyErrorBase class for all HTTP errors
ErrorTStructured API error (4xx/5xx with body)
ConnectionErrorUnable to reach server
RequestTimeoutErrorRequest timed out
RequestAbortedErrorRequest was cancelled
ResponseValidationErrorResponse doesn’t match expected schema

Retries

Override retry behavior per-call:
from factify.utils import BackoffStrategy, RetryConfig

result = factify.documents.list(
    page_size=10,
    retries=RetryConfig(
        strategy="backoff",
        backoff=BackoffStrategy(1, 50, 1.1, 100),
    ),
)

Context Manager

The SDK uses httpx under the hood. Use the context manager to ensure connections are properly closed:
with Factify(bearer_auth=os.environ["FACTIFY_KEY"]) as factify:
    docs = factify.documents.list()
    # connections are cleaned up on exit

Async Support

import asyncio
from factify import Factify

async def main():
    async with Factify(bearer_auth=os.environ["FACTIFY_KEY"]) as factify:
        result = await factify.documents.list_async(page_size=10)
        print(result)

asyncio.run(main())

Source & Issues