Credits & Billing
Creating things costs credits. Credits come from a subscription. If you have none, creation fails with a 402.
What things cost
| Operation | Credits |
|---|---|
| Create a vault | 1 |
| Create a stream | 1 |
| Create a data attachment | 1 |
| Create a signature | 1 |
Setting short_url in the config of a vault or data attachment costs one extra credit. A
vault created with a short URL costs 2, not 1. This surcharge is not visible in the request schema
and is the usual explanation for a balance dropping faster than expected.
Who pays
Not necessarily the caller.
- Vaults are charged to the entity of the API key making the call.
- Streams and data attachments are charged to the vault owner, resolved from the vault.
So if you write into a vault someone else owns and has shared with you, their credits are spent, not yours.
Checking your balance
curl "$FILEDGR_API/balances" \
-H "x-api-key: $FILEDGR_API_KEY" -H "x-api-secret: $FILEDGR_API_SECRET"
Returns the current balance and its timestamps. There is no consumption history or ledger — track your own spend if you need an audit trail.
On renewal the balance is replaced with the period allowance rather than added to it, so unused credits do not roll over. An annual payment sets twelve times the plan's monthly allowance up front.
GET /plans defaults to plan_type=CORPORATE. Pass ?plan_type=PERSONAL explicitly if you are
looking for personal plans, or the list will look empty.
Two different 402s
The has_subscription field distinguishes them, and they need different handling:
{ "error": "InsufficientCreditsError", "message": "...",
"required": 1.0, "balance": 0.0, "has_subscription": false }
has_subscription: false— no active subscription. Subscribe.has_subscription: true— subscribed but out of credits. Wait for renewal or top up.
The credit check is not a guarantee
The pre-flight check fails open. If the billing service is unreachable, or the vault behind a
stream cannot be resolved, creation is allowed to proceed and the shortfall is caught later —
the resource ends up in an ERROR state instead of being refused up front.
The absence of a 402 therefore does not guarantee the operation will complete. Watch for the
*.failed and *.error webhook events, and check
entity status when something stalls.
The actual deduction happens asynchronously in a locked transaction after the pre-flight, so two concurrent creates can both pass the check and one can still fail.
Plans and subscriptions
GET /plans list available plans
GET /plans/{plan_id} plan detail
POST /subscriptions subscribe to a plan
GET /subscriptions your subscriptions
GET /subscriptions/{id} subscription detail
One subscription per entity. Attempting a second returns 400 (not 409, despite the conflict semantics).
A subscription moves through FILEDGR_RECEIVED → PAYMENT_PROCESSOR_RECEIVED →
PAYMENT_PROCESSOR_COMPLETED → FILEDGR_PROCESSOR_COMPLETED. Credits only arrive at the final
state.
The final state serialises as FILEDGR_PROCESSOR_COMPLETED. Some internal code refers to it by the
shorter name FILEDGR_COMPLETED — match on the value above, or your poll loop will never terminate.
Payment happens outside the API
Subscription responses carry a links object with subscription_link, and payment_link when
there is an outstanding payment. Payment is completed through those links in a browser — there is no
API call that settles it.
Subscription links require an email credential on the account. An API key whose holder has no email credential gets a 404 explaining that no links can be issued, which makes subscribing impossible from a pure machine integration. Have a person subscribe through the web app first, then use the API key against the subscribed entity.