MegalaniaDocs
Docs menu
  1. Docs
  2. Guides
  3. Your account
Guides

Your account

llms.txtUpdated 8 Nov 2026

Everything about your account lives under /v1/account on https://api.megalania.io: balance, keys, people, usage, request records, purchases, top-ups and the referral program. Sign in with Google or GitHub, make an account key (meg_ak_…) on the Keys page, and send it in the Authorization header. Only GET /v1/account also takes your scrape key.

Every example reads MEG_ACCOUNT_KEY from the environment. Get a key shows where the key comes from. The account reference lists every route, generated from the API contract.

Keys and scopes

A key has one scope, chosen when it is made. The prefix shows it: meg_sk_ is a scrape key, meg_ak_ is an account key. The rest is 43 random characters. We store only a hash and the last 4 characters, so we can never show a key again.

scope works on does not work on
scrape /v1 (scraping), batches, GET /v1/account the rest of /v1/account: 403 wrong_scope
account everything under /v1/account scraping, batches, proxy: 403 wrong_scope
  • Header only. Send Authorization: Bearer $MEG_ACCOUNT_KEY. The api_key query parameter is refused here with 401 bad_token, because a key in a URL ends up in logs and browser history.
  • A revoked key stops working in about 1 second. A new key works within about a second.
  • Every answer carries Cache-Control: no-store and X-Request-Id. There are no CORS headers: call this API from your server, never from a browser page.
  • Every write takes JSON. Send Content-Type: application/json, even with an empty {} body. Bodies are at most 4 KiB. A key the request does not take is a 400 bad_parameter naming it.
  • 10 requests a second per key, bursts of 20. Above that: 429 rate_limited with Retry-After.

Roles

A person in the account is an owner or a member.

what owner member
read the account, usage, the member list yes yes (no emails)
make a key for themselves yes yes
list and revoke keys every key their own keys
read request records every request requests made with their own keys
add people, change roles yes no: 403 owner_only
remove a person anyone only themselves (leave)
read purchases, top up yes no: 403 owner_only
the referral program yes no: 403 owner_only

The account always keeps at least one owner: 409 last_owner otherwise.

Balance and limits

Shell
curl -s -H "Authorization: Bearer $MEG_ACCOUNT_KEY" "https://api.megalania.io/v1/account"
JSON
{
  "id": "0199b0a1-0000-7000-8000-00000000a001",
  "created_at": "2026-09-23T10:00:00Z",
  "balance": 98750,
  "held": 150,
  "grant": null,
  "plan": { "name": "prepaid", "concurrency": 5, "max_members": 10, "max_keys": 20 },
  "caps": {
    "daily_cost_cap":  { "reached": false, "resets_at": "2026-09-24T00:00:00Z" },
    "period_cost_cap": { "reached": false, "resets_at": null },
    "free_failures":   { "used_percent": 12, "reached": false, "resets_at": "2026-09-24T00:00:00Z" },
    "spend_cap":       { "cap": 50000, "used": 12500, "used_percent": 25, "reached": false, "resets_at": "2026-10-01T00:00:00Z" }
  },
  "default_country": "DE",
  "found_us": "friend",
  "country_in_use": "DE",
  "premium_credits": 3,
  "alerts": { "webhook_url": "https://hooks.example.com/megalania", "email": false, "email_available": false },
  "webhook_secret": { "set": true, "rotated_at": "2026-09-20T08:00:00Z", "previous_valid_until": null },
  "subscription": null,
  "caller": { "person_id": "0199b0a1-...", "role": "owner", "key_id": "0199b0a1-...", "scope": "account" }
}
  • balance: credits you can spend now. held: credits reserved by requests still running. They go back to balance, or are charged, when those finish.
  • grant: the part of balance from a free grant, with its end date. null when there is none.
  • plan: your limits. caps: whether a usage limit is reached, named like the 429 you would get, and when it resets. free_failures: how much of today’s free browser and residential retries you used, in percent; at reached such requests answer 429 free_failures_spent until 00:00 UTC.
  • default_country: the country requests without country_code exit from, set by an owner. null means the platform default. country_in_use is the country used now; it differs when we no longer serve your choice. See Countries.
  • premium_credits: the extra credits per request on a premium country.
  • found_us: how an owner said the account found us: search, ai_assistant, friend, social, community, directory, blog or other. null until they answer. Set it once with PATCH /v1/account {"found_us": "friend"}; the first answer is kept and a later one is ignored. It is optional, and only an owner sets it.
  • caps.spend_cap: your monthly spend cap and this UTC month’s use against it, named like the 402 you would get. See Spending cap.
  • alerts: where usage alerts go, and whether we can send email yet. See Usage alerts.
  • webhook_secret: whether a secret exists and when it was rotated. Never the secret itself. See Webhook secret.
  • subscription: your latest subscription (plan, status, period_end, cancel_at_period_end), or null when you never subscribed.
  • caller: who you are: your person_id, your role, the key you sent.

It is free. $MEG_API_KEY works here too.

Keys

List them. An owner sees every key, a member sees their own:

Shell
curl -s -H "Authorization: Bearer $MEG_ACCOUNT_KEY" "https://api.megalania.io/v1/account/keys"

The list gives each key’s kind (api, mcp or dashboard) and hint (its last 4 characters). mcp marks a key made by an MCP connection (Claude, ChatGPT). The list never holds the key itself.

Make one. expires_at is required, in the future and at most 400 days ahead. name is 1 to 64 characters, default the scope word. scope is scrape (the default) or account:

Shell
curl -s -X POST "https://api.megalania.io/v1/account/keys" \
  -H "Authorization: Bearer $MEG_ACCOUNT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "laptop", "scope": "scrape", "expires_at": "2027-01-01T00:00:00Z"}'

The answer is 201 with api_key (a meg_sk_... or meg_ak_... string), shown once, and key, its record. A key always belongs to the person who made it. When that person leaves the account, their keys are revoked. Too many keys is 402 over_plan. A new key works within about 1 second. A script that uses it right away waits 1 second first, or retries a 401 once after 1 second.

Revoke one. It stops working in about 1 second:

Shell
export KEY_ID='<id from the list>'
curl -s -X DELETE -H "Authorization: Bearer $MEG_ACCOUNT_KEY" \
  "https://api.megalania.io/v1/account/keys/$KEY_ID"

The answer is the key as it was. A key you cannot see is 404 not_found.

People

Members are API only in the beta: the dashboard has no Members page yet.

List them. Owners see emails; for members email is null:

Shell
curl -s -H "Authorization: Bearer $MEG_ACCOUNT_KEY" "https://api.megalania.io/v1/account/members"

Add one (owner). role is member (the default) or owner. We send no email:

Shell
curl -s -X POST "https://api.megalania.io/v1/account/members" \
  -H "Authorization: Bearer $MEG_ACCOUNT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]"}'

The answer is 201 with the new person_id. An email that is already in this account is 409 already_member. Too many people is 402 over_plan.

The new member signs in with Google or GitHub with that email and lands in this account. They make their own keys on the Keys page. Never send a key by chat or email.

Change a role (owner):

Shell
export PERSON_ID='<person_id from the list>'
curl -s -X PATCH "https://api.megalania.io/v1/account/members/$PERSON_ID" \
  -H "Authorization: Bearer $MEG_ACCOUNT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"role": "owner"}'

Remove someone (owner), or leave (your own person_id):

Shell
curl -s -X DELETE -H "Authorization: Bearer $MEG_ACCOUNT_KEY" \
  "https://api.megalania.io/v1/account/members/$PERSON_ID"
JSON
{ "person_id": "0199b0a1-...", "keys_revoked": 2, "items_canceled": 40 }

Removing a person revokes every key they made and cancels their batch items that have not started, in one step.

Usage

Requests and credits per UTC day, newest first. days is 1 to 90, default 30. Today is included and still growing:

Shell
curl -s -H "Authorization: Bearer $MEG_ACCOUNT_KEY" "https://api.megalania.io/v1/account/usage?days=7"
JSON
{ "days": 7, "usage": [
  { "date": "2026-09-23", "requests": 1200, "delivered": 1100, "blocked": 60, "credits_charged": 5400, "credits_refunded": 40,
    "by_source": { "api": { "requests": 1000, "credits": 4600 }, "mcp": { "requests": 150, "credits": 600 }, "job": { "requests": 50, "credits": 200 } } }
] }

credits_charged is what you paid that day, already net: a refunded request adds 0 to it. credits_refunded is for information; do not subtract it again. by_source splits the day: job is a batch item, mcp a request made with a key from an MCP sign-in (Claude, ChatGPT), api everything else.

Request records

One record per request, newest first, the last 90 days. limit is 1 to 100, default 50. key_id keeps one key’s requests; source (api, mcp, job or monitor) keeps one source’s, and api also matches proxy; host (like example.com, any case) keeps one site’s. With any filter the list covers the last 7 days, not 90:

Shell
curl -s -H "Authorization: Bearer $MEG_ACCOUNT_KEY" "https://api.megalania.io/v1/account/requests?limit=50"

Each record has id (the X-Request-Id you got), created_at, key_id, key_name (null once the key is deleted), source (api, proxy, job, monitor or mcp), client (claude or chatgpt when source is mcp), job_id, monitor_id (the monitor when source is monitor), engine, target_status, error_code (a code from errors.md, null when delivered), error_message (the one-line message for that code, the same text the API answered with; absent when delivered), blocked, challenge, credits_charged, duration_ms, bytes and target_host: the site’s host name only, like example.com. We never store the path, the query or the full URL. It is null when your account keeps no hosts (audit level minimal).

A record is mcp while its key exists. Once an MCP key is deleted (unused for 30 days, expired, or replayed), its records show as api here. The usage totals keep them as mcp once their hour is rolled up, about an hour after the hour ends, because the rollup fixes the source.

One request

GET /v1/account/requests/{id} gives one record, by the X-Request-Id you got, with more detail: the climb and where the credits came from.

Shell
curl -s -H "Authorization: Bearer $MEG_ACCOUNT_KEY" "https://api.megalania.io/v1/account/requests/<request id>"
JSON
{"id": "...", "credits_charged": 12, "route": "h:dc>c:dc",
 "hops": [{"rung": "h:dc", "identity": "firefox", "ms": 310, "outcome": "blocked"},
          {"rung": "c:dc", "identity": "chrome", "ms": 1200, "outcome": "ok"}],
 "credit_parts": {"route": 9, "output": 2, "other": 1},
 "llm_tokens": 0, "response_types": ["markdown", "json"], "...": "the list fields"}
  • hops is each route we tried, in order, the same as the X-Hops header. Every try before the last was not delivered and cost nothing. It is null when no route was tried.
  • credit_parts is the same split as the X-Credits-Route, X-Credits-Output and X-Credits-Other headers (Credits). route + output + other is credits_charged. It is null for requests from before we kept the parts.
  • llm_tokens is the language-model tokens the request used, and response_types the outputs you asked for.
  • A member sees only the requests of their own keys. Any other id is a 404, never a 403. The dashboard reads the same record at GET /api/account/requests/{id}.

Every list here pages the same way: send next_cursor back as cursor until it is null.

Shell
curl -s -H "Authorization: Bearer $MEG_ACCOUNT_KEY" \
  "https://api.megalania.io/v1/account/requests?limit=50&cursor=<next_cursor>"

What we keep about your requests. For each request we keep a record: its id, time, key, engine, result, credits and the target’s host name (like shop.example.com). We never write the full target URL, its path or query, your request headers, cookies, or your IP address into a log or a table. A batch is the one exception you choose: it needs its URLs to run them, so it keeps them while it runs and deletes them 7 days after it ends (see Batches). GET /v1/account/requests shows you your records.

Purchases

Owner only. Paid purchases, newest first:

Shell
curl -s -H "Authorization: Bearer $MEG_ACCOUNT_KEY" "https://api.megalania.io/v1/account/purchases"
JSON
{ "purchases": [
  { "id": "0199b0a1-...", "created_at": "2026-09-23T10:00:00Z", "credits": 100000,
    "amount": "25.00", "currency": "USD", "status": "paid", "paid_by": null,
    "campaign": "reddit-launch", "receipt_url": null }
], "next_cursor": null }

amount is a decimal string. paid_by is the person who bought, null once that person has left the account. receipt_url is always null today.

Spending cap

Owner only. A cap is the most credits this account may spend in one UTC month. Requests, batch items, monitor checks and LLM steps all count, as charged, plus what requests still running have reserved.

Shell
curl -s -X PATCH "https://api.megalania.io/v1/account" \
  -H "Authorization: Bearer $MEG_ACCOUNT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"spend_cap": 50000}' | jq .caps.spend_cap
JSON
{ "cap": 50000, "used": 12500, "used_percent": 25, "reached": false, "resets_at": "2026-11-01T00:00:00Z" }
  • A request that would take this month past the cap answers 402 spend_cap. It costs nothing, and the message says when it resets. A batch item ends failed with the same error; a monitor check is skipped for free.
  • The cap resets at 00:00 UTC on the 1st. Send "spend_cap": null to remove it. A member can read the cap but not change it.
  • The cap counts credits, not money: it is the same number you see in X-Credits-Charged.
  • The dashboard sets it on Plan and billing, and shows a banner at 80% and 100%.

Usage alerts

We tell you at 50, 80 and 100% of your spend cap. With no cap set, we count against your last grant or top-up instead. Each step is sent once. We also tell you once when a request is stopped: by the cap, or, with no cap, because the balance could not cover it.

Shell
curl -s -X PATCH "https://api.megalania.io/v1/account" \
  -H "Authorization: Bearer $MEG_ACCOUNT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"alerts": {"webhook_url": "https://hooks.example.com/megalania"}}'
  • webhook_url gets a signed POST, like the batch webhook (same secret, same headers, X-Megalania-Event: account.usage). It must be https on a public host. null removes it. A failed delivery is tried again after 1 s, 5 s, 25 s and 125 s.
  • email: true mails every owner whose email is verified. Email is not available yet: alerts.email_available is false, and email: true is refused with 400 bad_parameter until it is.
JSON
{
  "event": "account.usage",
  "kind": "used",
  "used_percent": 80,
  "base": "spend_cap",
  "spend_cap": 50000,
  "resets_at": "2026-11-01T00:00:00Z",
  "created_at": "2026-10-22T09:14:03Z"
}
  • kind is used (a step was reached) or stopped (a request was refused; used_percent is the real use before it).
  • base is spend_cap or grant. The body then carries spend_cap (the cap) or grant (the credits of the last grant). resets_at is null for a grant.
  • The body names no host and no URL.

Webhook secret

Every webhook we send you (batches, monitors, usage alerts) is signed with one secret per account. We show it once, when it is made, and never again:

Shell
curl -s -X POST "https://api.megalania.io/v1/account/webhook-secret/rotate" \
  -H "Authorization: Bearer $MEG_ACCOUNT_KEY"
JSON
{ "secret": "bmV3LXNlY3JldC1ieXRlcy0wMTIzNDU2Nzg5YWJjZGVmZ2g=", "previous_valid_until": "2026-10-23T09:14:03Z" }
  • Owner only, with an account key, or on the dashboard: Connect, Webhooks, Rotate and show.
  • Store it in your secret manager at once. Lost it? Rotate again.
  • For 24 hours the old secret also signs: the signature header carries both values, newest first. Update your receivers in that window. A second rotation inside it drops the oldest secret.
  • Leaked? Rotate twice. The second rotation ends the leaked secret at once, instead of after 24 hours.
  • At most 5 rotations an hour.
  • How to check a signature: Batches, check the signature.

Webhooks

Send a signed test event to check your receiver:

Shell
curl -s -X POST "https://api.megalania.io/v1/account/webhooks/test" \
  -H "Authorization: Bearer $MEG_ACCOUNT_KEY" -H "Content-Type: application/json" \
  -d '{}'
JSON
{ "status": 200, "error": null, "duration_ms": 87 }
  • {} sends it to your alerts.webhook_url. To try another receiver, send {"url": "<https URL>"}. It must be one https URL on a public host.
  • The body is {"id", "event": "test", "created_at"}, signed like every webhook, with X-Megalania-Event: test. We send it once, with no retry.
  • The answer is what your receiver said: status is its HTTP status, null when it did not answer. Then error says why: timeout, connect, private (the host is not on the public internet) or request.
  • It is free. At most 5 a minute per account.
  • Every member can send a test; only an owner rotates.

Subscribe

Owner only. GET /v1/plans lists the plans (no key needed). The first one, free, is the free tier: its price and currency are null, and it needs no subscription. Subscribe to one of the others:

Shell
curl -s -X POST "https://api.megalania.io/v1/account/subscription" \
  -H "Authorization: Bearer $MEG_ACCOUNT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"plan": "starter"}' | jq -r .checkout_url

Open the printed link and pay. Each paid month adds the plan’s monthly credits; they last 61 days. With a subscription, the same call changes the plan: a higher plan is charged in full now and starts a new month with its full credits ({"change": "upgrade"}); a lower plan starts at your next renewal ({"change": "downgrade"}). Your card, your invoices and canceling are on the billing portal: POST /v1/account/billing-portal returns portal_url. A cancel takes effect at the end of the paid month, and your credits stay until they expire.

Top up

Owner only. A pack tops up an active subscription and is sold only for your plan; without a subscription the answer is 409 no_subscription. It opens a Stripe payment page whose credits land on this account. The dashboard’s Plan and billing page does the same, under Top up. It makes no keys:

Shell
curl -s -X POST "https://api.megalania.io/v1/account/checkout" \
  -H "Authorization: Bearer $MEG_ACCOUNT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"pack": "starter"}' | jq -r .checkout_url

Open the printed link in a browser and pay. The credits show in balance once Stripe confirms the payment.

A body may carry ref_token (from a referral link) or ref_code (a code someone gave you). Only the account’s first paid purchase binds a referral; a ref on a later purchase is dropped. A bad ref is never an error.

Referral program

Owner only. Share your link; when an account you referred pays real money, you earn 12% of what it paid, as credits, never cash.

  • Your account can join after one paid purchase that was not refunded or disputed. Otherwise: 403 not_eligible.
  • Earnings wait 60 days after each payment, then are paid as credits at the list price once a month.
  • It counts the referred account’s purchases in its first 12 months, up to $250 per referred account.
  • Nothing is earned on your own account, an account that shares a person with yours, an account whose people already belong to another account, a free account, or a click from an ad. We match people by their sign-in email, never by the email typed into Stripe.

Join. It makes your first code. Sending it again changes nothing:

Shell
curl -s -X POST "https://api.megalania.io/v1/account/affiliate" \
  -H "Authorization: Bearer $MEG_ACCOUNT_KEY" \
  -H "Content-Type: application/json" -d '{}'

Your link is link in the answer: https://api.megalania.io/r/<code>. Add ?campaign=<name> to see which post it came from, and to=/buy to send people straight to the Buy credits page. The referral binds when the referred account makes its first paid purchase, after it signs in.

Read your status, terms, codes and earnings:

Shell
curl -s -H "Authorization: Bearer $MEG_ACCOUNT_KEY" "https://api.megalania.io/v1/account/affiliate"

Make another code (at most 5):

Shell
curl -s -X POST "https://api.megalania.io/v1/account/affiliate/codes" \
  -H "Authorization: Bearer $MEG_ACCOUNT_KEY" \
  -H "Content-Type: application/json" -d '{}'

Clicks, referrals and earnings per month, months 1 to 12, default 6:

Shell
curl -s -H "Authorization: Bearer $MEG_ACCOUNT_KEY" "https://api.megalania.io/v1/account/affiliate/stats?months=3"

Before you join, these three answer 404 not_enrolled.

Errors

HTTP error.code what to do
400 bad_parameter Read error.field and the message.
400 bad_request Send one JSON object.
401 bad_token Send your key as Authorization: Bearer <key>. Not in the query.
402 over_plan Revoke a key or remove a person, then try again.
402 spend_cap Your monthly spend cap is reached. Raise it with PATCH /v1/account, or wait for the 1st (UTC). Nothing was charged.
403 wrong_scope Use your account key, not your scrape key.
403 owner_only Ask an owner.
404 not_found No key, person or pack with that id or name in this account.
409 already_member The email is already here. Find its person_id in the list.
409 last_owner Make someone else an owner first.
429 rate_limited Wait the seconds in Retry-After.
503 busy Send the same request again in a few seconds.

The referral codes not_eligible and not_enrolled, and every other code with its cost, are in errors.md.