POST/api/auth/sign-up/emailOpen
Creates an account and sends the confirmation e-mail.
- Body
email,password(at least 10 characters),name- Answers
- the new user and a session
- Limit
- 5 per hour and IP address
Every endpoint of the core API. Paths are relative to this site: it forwards /api and /v1 to the core, so a browser session and a script use exactly the same URLs.
Sign-up, sign-in, password and profile. Served by Better Auth.
/api/auth/sign-up/emailOpenCreates an account and sends the confirmation e-mail.
email, password (at least 10 characters), name/api/auth/sign-in/emailOpenSigns in with an e-mail address.
email, passwordset-auth-token header for callers without cookies/api/auth/sign-in/usernameOpenSigns in with a username instead of an e-mail address.
username, password/api/auth/sign-outPersonEnds the current session.
{ success: true }/api/auth/update-userPersonChanges the profile: display name, username and whether Deeds may show the name.
name, username, defaultVisibility/api/auth/request-password-resetOpenSends a password reset link. Answers the same way whether or not the address exists.
email, redirectTo{ status: true }/api/auth/reset-passwordOpenSets a new password and ends all other sessions of that account.
token from the e-mail link, newPassword{ status: true }/api/auth/verify-emailOpenConfirms an e-mail address from the link in the message.
?token the token from the e-mail link (required)Everything anyone may read: rules, money, catalog, Deeds with receipts, statistics, map.
/v1/public/rulesOpenThe earning rules that are active right now.
{ rules: [...] } with reward, unit, daily cap, the minimum trust level and audience; invited-only rules add invitedCount (never names)/v1/public/changelogOpenEvery rule version with its reason, plus every budget deposit. Nothing is ever changed in place.
{ ruleVersions: [...], budgetDeposits: [...] }/v1/public/budgetOpenWhere the money behind the Drops is: deposited, not yet issued, in wallets, reserved, donated.
/v1/public/catalogOpenThe redemption catalog by category, with current prices and pool state.
{ categories: [...], providers: [...] }/v1/public/catalog/:slugOpenOne project with its complete price history.
:slug project slug, e.g. ecologi-treepriceHistory/v1/public/deedsOpenAll settled payouts. Contributors who chose anonymity have name: null.
{ deeds: [...] } newest first/v1/public/deeds/:idOpenOne Deed with its proof: the snapshot frozen at payout time, the ledger posting and a fresh check of the receipt hash.
:id payout id (UUID)receiptCheck: matches, differs or missing/v1/public/payouts/:id/receiptOpenThe receipt file of a payout, so anyone can hash it themselves.
:id payout id (UUID)/v1/public/impactOpenThe headline totals: donated and queued Drops, Deeds, contributors.
/v1/public/statsOpenWhat the Deeds financed per project, with CO₂e grouped by period, impact type and how well the figure is backed. Living units are counted from the day they were paid for, so the totals grow on their own.
{ since, deeds, contributors, financed: [...], co2e: { groups, dropsWithoutFactor } }; each group carries accumulated and perYear/v1/public/mapOpenActivity per country for the world map. Never finer than a country.
?days window of 1 to 90 days, 7 by default{ days, countries: [{ country, activities, people }] }/v1/public/footprintOpenThe server's estimated CO₂e and water use as reported by the hosting provider, the website's traffic, and what the Deeds dealt with in the same days. They stand side by side; nothing is offset or subtracted.
?period day, week, month (default) or year: a rolling window ending on the last day the provider has figures for{ period, since, window: { from, to, days, bucket }, server: { co2eGrams, waterLitres, daysWithData }, visits: { bytes, responses, daysWithData, since }, buckets: [{ start, days, co2eGrams, waterLitres, bytes, uptake }], deeds: [{ period, impactType, basis, units, amount, sourceUrls }] }; window and server are null before the first figures arrive, visits before the website reported traffic; uptake is the estimated daily uptake of living units, never subtracted from anythingYour own data, redemptions, devices and your right to export or delete everything.
/v1/mePersonThe signed-in person with their Drops and Sparks balance.
{ user, balances }/v1/me/activitiesPersonYour own reported activities and what they earned.
{ activities: [...] }/v1/me/activitiesPersonReports an activity yourself. Trust level self_reported, so most rules will not pay for it.
source, type, quantity, unit, startedAt, endedAt, optional externalId and zone/v1/me/statsPersonYour own share: what your Drops financed and the CO₂e estimate behind it, counted from the day each Deed was paid.
/v1/public/stats, limited to your redemptions/v1/me/invitationsPersonThe rules you are invited to. Rules with audience invited pay only invited people; being invited also lets you confirm your device's link code.
{ invitations: [{ ruleId, key, title, source, translations, createdAt }] }/v1/me/redemptionsPersonYour redemptions with their status.
{ redemptions: [...] }/v1/me/redemptionsPersonTurns Drops into a queued donation; the Drops are reserved at today's price.
projectId plus quantity (unit projects) or drops (free amount), optional visibility/v1/me/redemptions/:id/cancelPersonTakes a redemption back while it is still queued and returns the Drops.
:id redemption id (UUID)/v1/me/clientsPersonYour connected apps and devices.
{ clients: [...] } without key hashes/v1/me/clientsPersonCreates an API key for an app. The key is shown once and only its hash is stored. Only admins may do this for now (403 clients_owner_only otherwise); a key made by anyone else counts as a third-party app.
name, optional kind (first_party for admins), optional signingPublicKey (Ed25519, base64)apiKey (Status 201)/v1/me/clients/:idPersonRevokes a device: its key stops working immediately.
:id client id (UUID)/v1/me/link/:codePersonShows which app and device are waiting behind a link code.
:code the code shown on the device, e.g. K7QM-3XRA/v1/me/link/:code/approvePersonApproves a device. It may then report activities for you, nothing else. Only admins may do this for now (403 clients_owner_only).
:code the code shown on the device/v1/me/link/:code/denyPersonRefuses a link request.
:code the code shown on the device/v1/me/exportPersonYour data as one JSON file (GDPR art. 15 and 20). Contains no password hash, token or key hash.
/v1/me/deletePersonDeletes your account by anonymising it: the ledger and the Deeds stay, everything that points at you goes. Queued redemptions are donated anonymously, the rest of the Drops goes back to the budget.
passwordThe machine side: reporting activities with an API key.
/v1/client/activitiesApp or deviceReports one activity. externalId makes it idempotent, so a retry never pays twice. With an Ed25519 signature in X-Elpia-Signature the activity counts as verified, otherwise as device.
source, type, quantity, unit, startedAt, endedAt, externalId, optional zone, energyWhMeasured, energyWhEstimated/v1/client/meApp or deviceWhat this key reported and earned (last 24 hours and in total), the latest reward decision and the account's balances. Nothing about other apps.
{ client, last24h, total, lastRewardStatus, balances }, amounts in milli units/v1/client/meApp or deviceRevokes this key, e.g. when someone logs out on the device. It stops working immediately and cannot be restored.
How a device without a browser gets a key: it shows a code, you approve it here.
/v1/link/startOpenStarts pairing and returns a code the person types into the website.
app, deviceName, optional signingPublicKey{ code, pollToken, expiresIn, interval }; the code is valid for 10 minutes (Status 201)/v1/link/pollOpenAsks whether the person approved. The API key comes back exactly once, on the first approved answer.
pollTokenpending, denied, expired, or approved with apiKeyRules, budget, catalog, payouts and the integrity audit.
/v1/admin/auditOwnerChecks the books: balanced postings, no unexpected negative balances, redemptions matching payouts, receipts matching their hash.
/v1/admin/rulesOwnerAll rule versions, including the disabled ones.
{ versions: [...] }/v1/admin/rulesOwnerCreates a rule with its first version.
key and a version object with reward, unit, caps, minimum trust and a public reason/v1/admin/rules/:id/versionsOwnerAdds a new version of a rule. The old one stays readable; nothing is ever rewritten.
:id rule id (UUID)reason/v1/admin/rules/:id/invitationsOwnerWho is invited to a rule that only pays invited people.
:id rule id (UUID){ invitations: [{ userId, username, email, createdAt }] }/v1/admin/rules/:id/invitationsOwnerInvites a person to a rule. Inviting someone twice changes nothing; an unknown person gives 404 user_not_found.
:id rule id (UUID)user: username or e-mail address/v1/admin/rules/:id/invitations/:userIdOwnerRemoves an invitation. New activities stop earning; rewards already booked stay.
:id rule id (UUID):userId the invited person's id/v1/admin/budget/depositsOwnerPays money into the budget. Drops can only be issued from it.
amountCents, optional memo/v1/admin/catalogOwnerThe catalog including inactive providers and projects.
/v1/admin/categoriesOwnerCreates a category.
slug, name, optional description, translations, sortOrder/v1/admin/categories/:idOwnerChanges a category. Only the fields that are sent change.
:id category id (UUID)/v1/admin/providersOwnerCreates a provider with its minimum payment and fee note.
slug, name, website, optional minPayout, feeNote, translations/v1/admin/providers/:idOwnerChanges a provider.
:id provider id (UUID)/v1/admin/projectsOwnerCreates a project. impactType is required, so no card is ever ambiguous about what the money does.
slug, providerId, categoryId, title, kind, impactType, optional unitName, co2e, translations/v1/admin/projects/:idOwnerChanges a project. kind is fixed because redemptions depend on it.
:id project id (UUID)co2e: null removes the CO₂e figure/v1/admin/projects/:id/pricesOwnerAdds a price. Prices are append-only and queued redemptions keep the price they were made at.
:id project id (UUID)price, currency, fxToEur, public reason/v1/admin/queueOwnerThe pools waiting for a payout and whether they have reached the provider's minimum.
{ pools: [...] }/v1/admin/budget/forecastOwnerWhat paying out today would cost, how much the owner would have to add, and how long the budget lasts at the pace of the last 30 days.
/v1/admin/payoutsOwnerRecords a real payment with its receipt and turns the settled redemptions into a Deed. Payouts cannot be changed afterwards.
projectId, redemptionIds, amountPaid, currency, paidAt, optional comment, and the receipt file/v1/admin/payouts/:id/reviewsOwnerRecords what the provider delivered after the payment. Append-only: a correction never hides the earlier entry.
:id payout id (UUID)status (confirmed, needs_clarification, corrected), note, evidenceUrl (required for confirmed)What a container orchestrator asks before it sends traffic.
/healthOpenChecks the process and its database. Answers 503 when the database is unreachable, so a broken instance is taken out of rotation.
{ status, database }/v1/ops/trafficInternalThe website reports how many compressed bytes and responses it sent per UTC day since its last report; the API adds them up. Only totals: no address, cookie or page, so no visit can be told apart.
{ days: [{ day, bytes, responses }] }; days older than 30 days or in the future are skipped{ stored }, the number of days added