Metadata-Version: 2.4
Name: sendflo
Version: 0.7.0
Summary: SendFlo for Python: send files, request files, manage transfers and AI agent tasks. Standard library only.
Project-URL: Homepage, https://sendflo.app
Project-URL: Documentation, https://sendflo.app/docs/cli#python
Author-email: SendFlo LLC <dev@sendflo.app>
License: MIT
License-File: LICENSE
Keywords: ai agents,file sharing,file transfer,sendflo,upload
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Communications :: File Sharing
Requires-Python: >=3.9
Provides-Extra: e2e
Requires-Dist: cryptography==50.0.2; extra == 'e2e'
Description-Content-Type: text/markdown

# sendflo

SendFlo for Python: send files and get a link, ask someone for a file, manage your transfers, and
give files to AI agents. Python 3.9+, **standard library only** — nothing else to install, so it
drops into locked-down agent containers.

```sh
pip install sendflo
```

Create an API key in SendFlo → Settings → Developer (<https://sendflo.app/settings/developer>)
and set `SENDFLO_API_KEY` (or pass `api_key=`).

## Send a file

```python
from sendflo import SendFlo

flo = SendFlo()                      # reads SENDFLO_API_KEY
sent = flo.send_file("report.pdf", password="optional")
print(sent.url)                      # https://sendflo.app/l/…
```

The bytes go straight to storage through a presigned multipart upload, each part retried on its
own.

### End-to-end encrypted

```sh
pip install "sendflo[e2e]"           # adds one package, cryptography, for AES-GCM
```

```python
sent = flo.send_file("contract.pdf", encrypt=True, password="a passphrase")
print(sent.url)                      # https://sendflo.app/l/…#k=2.…  ← your half of the key
```

The file is sealed on your machine (AES-256-GCM, the format the SendFlo apps use) before it
leaves, and SendFlo stores ciphertext it can't read. The key is split: the link's `#k=` part,
which browsers never send to a server, carries one half; SendFlo keeps the other, gives it only to
someone past the link's password (or email check), and deletes it when the link is revoked or
expires. If the link is lost, the file can't be recovered. Paid plans.

## Ask someone for a file

```python
ask = flo.request_file("Upload your Q3 expense CSV")
print(ask.url)                       # they upload there with no account

items = flo.list_inbox(inbox_id)
flo.save_inbox_item(items[0].id, "q3.csv")
```

A file someone uploaded end to end (a page that encrypts uploads) opens only on your devices:
`save_inbox_item` refuses it (`e2e_locked`) — use the CLI (`sendflo keys enrol`, then
`sendflo received get`) or the app.

Send a file to someone's upload page as anyone with the address can:
`flo.upload_to_page("https://sendflo.app/u/acme-intake", "statement.pdf")`. A page that encrypts
uploads is refused (`e2e_page`): its files are sealed to keys this SDK can't use yet — use the CLI.

## Manage what you've sent

`list_links()`, `revoke_link(id)`, and for a whole send: `get_transfer`, `pause_transfer`,
`resume_transfer`, `revoke_transfer`, `transfer_activity`, `transfer_audit`, `transfer_people`,
`set_transfer_person_access`. Recipient feedback: `link_feedback`, `link_feedback_comments`,
`export_link_feedback`.

## Agents

`list_agents()`, `send_to_agent(cloud_agent_id, file_ids, instruction=…)`, `list_agent_tasks()`,
`get_agent_task(id)`, `answer_agent_task(…)`, `cancel_agent_task`, `retry_agent_task`,
`wait_for_agent_task(id)`.

## Webhooks and events

```python
from sendflo import verify_webhook

hook = flo.create_webhook("https://example.com/sendflo", ["transfer.completed", "link.downloaded"])
# hook["secret"] is shown only now: store it.

event = verify_webhook(os.environ["SENDFLO_WEBHOOK_SECRET"], request.headers, request.get_data())
if event is None:
    abort(400)
```

- Endpoints: `list_webhooks()`, `update_webhook(id, url=, events=, description=, enabled=)`,
  `delete_webhook(id)`, `rotate_webhook_secret(id)`, `test_webhook(id, type)`, `resume_webhook(id)`.
- The log: `webhook_deliveries(id)`, `webhook_delivery(delivery_id)`,
  `resend_webhook_delivery(id, delivery_id)`, and `replay_webhook(id, since=, types=,
  only_failed=)`.
- The events (30 days): `list_events(types=, since=)`, `events()`, `get_event(id)`, and
  `webhook_event_types()`.
- `verify_standard_webhook(...)` returns True or False. `verify_webhook_signature` checks the old
  `sendflo-signature` header (until 2027-04-28).

## Notifications

Notification channels: `list_notification_channels`,
`add_notification_channel`, `update_notification_channel`, `remove_notification_channel`,
`test_notification_channel`.

## Errors

Every non-2xx response raises `SendFloError` with `status`, a stable `code`, and `retryable` /
`out_of_credits`. Reads are retried with backoff; `402` (out of credits) never is.

## Licence

MIT © SendFlo LLC. Questions: support@sendflo.app.
