Webhook-free integrations: polling /api/v1/usage for credit alerts
By Qrop Team ·
Qrop's API surface has one webhook: the PayFast payment notification that reconciles your own billing (that's an inbound webhook Qrop's own server receives, not one you can subscribe to). There is no outbound webhook for usage events. Nothing fires when you cross 80% of your included credits, nothing fires when you tip into overage, and nothing fires when your carried credits run out. The only way to know where you stand is to ask, via GET /api/v1/usage.
That's a deliberate gap, not a missing feature you should wait on: usage numbers change on every generation call, and a webhook system for a value that mutates hundreds of times a minute at real volume is a lot of infrastructure for something a single polled endpoint already answers cheaply. This guide covers what that endpoint actually returns, how often to poll it without wasting requests, and how to turn the response into the low-credit and overage alerts you'd otherwise expect a webhook to give you.
What GET /api/v1/usage actually returns
The endpoint is a single authenticated GET, same Bearer key as every other API call, and it returns a snapshot: current plan, the billing period's start and end, included credits and how many of them are used, carried-over credits from prior periods, overage credits already consumed this period, the per-credit overage rate, and a running estimated overage cost in ZAR. It also echoes your plan's current rate limit, which is useful context if you're about to raise your polling frequency.
Two fields matter more than the rest for alerting: includedCreditsUsed against includedCredits tells you how close you are to exhausting your free allocation, and overageCredits tells you whether you've already crossed it. Carried credits are drawn down before included credits, so a low includedCreditsUsed number doesn't necessarily mean you're safe if your carried pool is the one actually being spent, check both before assuming you have headroom.
There's no hard stop, so "credit alert" means something specific here
Unlike anonymous or free registered generation, the API doesn't cut you off at zero. Once includedCredits and any carried credits are exhausted, requests keep succeeding and overageCredits starts climbing, billed post-paid at overagePerCredit at the end of the period. So a credit alert on the API side isn't preventing a 402 the way it would be for a free-tier UI user, it's a cost control: you want to know you've entered overage while it's still a small number, not discover it as a line item after the period closes.
That reframes what you're polling for. You're not racing to react before generation stops working, you're watching a number that quietly increases in the background and deciding at what point it's worth investigating, whether that's a runaway job, a traffic spike worth a plan upgrade, or just expected seasonal volume you're fine paying overage on.
Picking a polling interval
- Once per hour is enough for most integrations. Usage moves in proportion to your own generation volume, not in real time from something external, so there's no benefit to sub-minute polling unless your generation rate is high enough that an hour represents a meaningful chunk of your plan.
- High-volume plans (Growth, Enterprise) generating continuously can reasonably poll every 5 to 15 minutes, since a bad deploy or a runaway retry loop burns through more credits per hour at that volume and you'd rather catch it inside the same incident window than the next morning.
- Don't poll on every generation request, or even once per batch. The usage snapshot doesn't need to be that fresh to be useful, and it adds a second API call (against the same rate limit) for every generation call you make, which is pure overhead for a number that's informational, not something you branch your generation logic on per request.
- Whatever interval you pick, run it from a scheduled job (a cron, a queue worker, a serverless scheduled function) separate from your generation code path, not inline with request handling. Usage checking is a background concern; coupling it to the hot path just adds latency to every generation call for no benefit.
Building the alert yourself
There's no threshold field in the response, you decide what counts as "low" and compare it yourself. A common pattern: alert once when (includedCreditsUsed + carriedCredits used so far) crosses 80% of your effective allocation, and alert again, separately, the moment overageCredits first goes above 0. Two distinct alerts, not one, because they mean different things: the first is a heads-up before you're paying anything extra, the second confirms you're now in overage and every subsequent generation has a real marginal cost.
Store the last value you alerted on (in whatever state store your polling job already has access to, a database row, a key-value cache) so you don't re-send the same alert every poll once a threshold is crossed. A simple pattern is to only fire when the current period's usage crosses a threshold that the previous poll's usage hadn't, then reset that flag when currentPeriodStart changes, which it will automatically at the start of each new billing period.
If overageCostZar is the number your finance side actually cares about rather than raw credit counts, alert on that directly instead of on overageCredits, the two move together but overageCostZar is already in the currency someone has to justify on an invoice.
What to do when the alert fires
A low-credit alert (approaching your included allocation) is a signal to check whether the increase is expected. If it's normal growth, that's a prompt to look at Starter, Pro, and Growth plan tiers and see whether the next one up pays for itself against the overage rate you'd otherwise pay, they all share the same per-credit overage cost, so the only real question is whether the included headroom is worth the higher base price this period and going forward.
An overage alert (already above 0) is worth a quick check for anything unexpected first, a misconfigured retry loop hitting POST /api/v1/generate repeatedly on a failure path burns real credits fast and won't show up as a deliberate spike anywhere except this number. If the usage is legitimate, there's nothing further to do, overage bills automatically at period close, there's no action required to keep generating.
Frequently asked questions
Does Qrop have any usage or billing webhooks I can subscribe to?
No. The only webhook in the system is the inbound PayFast ITN that Qrop's own server receives to reconcile payments, there's nothing you can register an endpoint against for usage events. GET /api/v1/usage is the only way to check current usage.
Will polling GET /api/v1/usage frequently affect my rate limit?
It counts against the same per-second and per-minute rate limit as your generation calls, since it's authenticated with the same API key. For the polling intervals recommended here (5 minutes to hourly) this is a negligible fraction of any plan's limit, it only becomes a concern if you poll far more often than the usage number actually changes.
Does the API stop generating codes once I run out of included credits?
No. There's no hard cap on the API side, once included and carried credits are exhausted, generation continues and overageCredits accrues at overagePerCredit, billed post-paid at the end of the period. This is different from anonymous and free registered web generation, which do stop at their daily or monthly limit.
What's the difference between carriedCredits and includedCredits in the response?
includedCredits is this period's fresh allocation from your plan. carriedCredits are unused included credits rolled over from prior periods, capped at 3x the plan's monthly allocation, and they're drawn down before the current period's includedCredits when metering usage, so they appear as a separate field rather than inflating the current period's number.
Can I get near-real-time usage updates instead of polling on an interval?
Not currently, there's no streaming or push option for usage data. GET /api/v1/usage always reflects the latest committed usage at the moment you call it, so the only way to get more current data is to poll more frequently, within the rate-limit tradeoffs covered above.
Related guides
Ready to create your QR code?
Generate a free QR code in seconds: custom colours, logos, and PNG, SVG or PDF output.
Open the generator