FOR YOUR AGENT

Connect your agent.

Let your agent upload the file and bring back a download link. Recipients don’t need an account.

  1. Get your access token. Sign in to your account and create an agent token. Free accounts can send right away.
  2. Give your agent the details below. It will guide you through saving the token securely.
  3. Ask it to send a file. Your agent uploads it and gives you a link to share.

Free: 5 transfers a month, files up to 5 GB. Need more? Plus is $15 for up to 150 GB, Pro is $30 for up to 400 GB, files up to 50 GB. Pay per use, never a subscription.

Give your agent the connection details

Paste this once so your agent knows where Bilaga is and how to use it. This does not sign you in or grant access to your account.

Use your private token only in secure credential setup, not in the chat message.
Technical setup and API reference

MCP

If your agent speaks the Model Context Protocol, the MCP server is the shortest path: npx -y bilaga-mcp setup stores your token, and the server gives the agent a send_file tool that returns the link.

Start with a file

Use the Python client with Python 3.10 or later. It uses the standard library and retries failed chunks. Inspect the downloaded script before running it. Set BILAGA_TOKEN in your environment, then replace the filename below.

python3 bilaga.py \
  --base https://bilaga.link \
  --file report.pdf

The response includes the shareable link and expiry. Your agent delivers that link through its existing conversation or communication channel.

Upload in chunks and resume

Files upload sequentially in 8 MiB chunks. Save the transfer ID printed by the client. After interruption, keep the original file unchanged and resume within 24 hours:

python3 bilaga.py --base https://bilaga.link --file report.pdf --resume TRANSFER_ID

Resume skips confirmed parts only and retries unfinished parts. Changing a previously submitted chunk is rejected. The browser retries chunks while the page stays open; it does not resume after page closure.

Check the handoff

python3 bilaga.py --base https://bilaga.link \
  --status TRANSFER_ID

Poll at most once every 15 seconds. A download request means a download started; it doesn’t prove completion or that a human read the file. Bilaga only marks a transfer “sent” when the agent reports delivery.

Prove the handoff

python3 bilaga.py --base https://bilaga.link \
  --receipt PUBLIC_ID --verify downloaded-file

Every completed transfer has a receipt signed by Bilaga: content hash, size, sender, and timestamps. Anyone can verify it offline against the published key, with or without the file. It proves what was stored, not that a person read it. Receipts are kept after the file expires or is deleted, and --receipt-hash FILE finds the receipts for any file you hold, whoever sent it. The exact formats and verification steps are on the verification page.

Address a file to another agent

python3 bilaga.py --base https://bilaga.link \
  --file report.pdf --to them@example.com

An addressed transfer appears in the recipient’s inbox as soon as they sign in with that email, even if they have no account yet. Their agent lists it with --inbox, downloads it with --download PUBLIC_ID, and can answer with --file answer.pdf --reply-to PUBLIC_ID. When the recipient’s agent downloads or acknowledges the file, your receipt gains their account handle and a received time. Replies reference the original in their receipts, so a conversation of files is a chain of signed receipts.

Put a price on a file (experimental)

python3 bilaga.py --base https://bilaga.link \
  --file dataset.parquet --to them@example.com --price 250

A priced transfer must be addressed. The recipient sees the price on the download page and in their inbox, and their agent pays with --pay PUBLIC_ID from its balance. Only then does the file download. Bilaga moves the money, keeps 5%, and signs the settlement into the receipt as paid_at, paid_by_account, and fee_cents. Check what you have with --balance. Card top-ups are available on the account page when payments are enabled.

Hear about it without polling

python3 bilaga.py --base https://bilaga.link \
  --webhook https://your-agent.example/bilaga

Bilaga posts each event to your webhook as JSON, signed with the same Ed25519 key as receipts, and retries failures for about half a day. Events: transfer.completed, transfer.downloaded (first download), transfer.received, transfer.reply, transfer.paid, and transfer.deleted. Pipe a delivery to --verify-event to check it, or read the same events from --events if you would rather poll.

A small API, end to end

Send your token as Authorization: Bearer …. Keep it private: all tokens for an account can manage that account’s transfers. Recipient links never contain the token.

EndpointWhat it does
GET /api/configSee upload limits and availability.
GET /api/quote?bytes=…Estimate the future storage price. Storage is not charged yet.
POST /api/transfersCreate an upload with a filename and size in bytes.
PUT /api/transfers/{id}/parts/{n}Upload one binary chunk. Retry failed chunks.
POST /api/transfers/{id}/completeFinish the upload and receive the shareable link.
GET /api/transfers/{id}Check uploaded parts, expiry, and download requests.
POST /api/transfers/{id}/sentRecord that your agent delivered the link.
DELETE /api/transfers/{id}Revoke the link and delete the stored file.
GET /api/receipts/{public_id}Signed receipt with the content hash. No token needed.
POST /api/requestsCreate an account-free upload link for multiple files.
GET /api/requestsList your file requests.
GET /api/requests/{id}Read files and submission status.
GET /api/requests/{id}/receiptFetch the private signed submission record after Done.
DELETE /api/requests/{id}Close an upload request.
GET /api/inboxTransfers addressed to your account email.
POST /api/inbox/{public_id}/receivedAcknowledge a transfer addressed to you; the sender’s receipt records it.
GET /api/eventsYour signed event feed. Page with ?since=EVENT_ID.
PUT /api/webhookRegister one https URL to receive every event, signed with the receipt key.
POST /api/inbox/{public_id}/payPay for a priced transfer from your balance.
GET /api/balanceYour balance in cents and recent ledger entries.

Collect files without signup

Create a file request from your account or with POST /api/requests. Share the returned upload link. Anyone holding it can add multiple files without an account and click Done when finished. Each file uses your normal allowance or credit; Done adds no charge.

Use the signed request.submitted event to learn when the uploader has finished. It includes the request ID, your optional reference and the final file list. Individual transfer.completed events mean a file finished uploading, not that the collection is finished. Your application decides what to do next.

The private submission receipt records hashes, submission time and the email supplied by the uploader. That email is not verified and is never added to public file receipts. Links expire, can be closed, and cannot change files after Done. Defaults: 20 files, 5 GB total and 7 days; removed uploads count toward the request limits.

What it costs

Every account gets 5 transfers per rolling 30 days and 5 GB stored free, so a free file is at most 5 GB. Beyond that, a transfer is charged when it is created at $0.10 per decimal GB with a $0.25 minimum, rounded up to a cent, from a balance you add to by card on the account page: Plus is $15 for $15 of credit (up to 150 GB), Pro is $30 for $40 of credit (up to 400 GB). Both are one-time payments valid for 3 years; the minimum charge means many small transfers cover fewer GB. An upload that never completes is refunded to its original credit, without extending expiry or restoring expired portions. Oldest credit is used first; the account page shows expiry dates and we email a reminder 30 days before unused credit expires. Stored files count until they expire or you delete them, up to 100 GB. Priced transfers, where a recipient pays the sender, exist in the API but are not a launch feature.

Read the complete agent instructions