# Show usage in your app (/docs/tutorials/show-usage-in-your-app)

In this tutorial you show a customer their usage this month in your app, as a bar such as "8,300 of 10,000 calls used". Then you email them when they pass 80% of what their plan includes, so a big bill is never a surprise.

## Before you start [#before-you-start]

- An agreement with a metered entitlement, for example from [Bill for API calls](/docs/tutorials/bill-for-api-calls).
- A test secret token in `COMECERO_SECRET_TOKEN`, used only on your server.
- A public HTTPS address for webhooks. For local testing, a tunnel such as `ngrok` works.

<Steps>

<Step>

## Read usage so far on your server [#read-usage-so-far-on-your-server]

[Get usage this period so far](/api/usage-agreements/get-usage-so-far) answers what each metered entitlement has used, what is included and the price so far, worked out as the bill will be.

```js title="usage-so-far.js"
const cache = new Map();

export async function usageSoFar(agreementId) {
  const hit = cache.get(agreementId);
  if (hit && Date.now() - hit.at < 5 * 60_000) return hit.value;

  const response = await fetch(`https://api.comecero.com/api/v1/usage/agreements/${encodeURIComponent(agreementId)}/current`, {
    headers: { Authorization: `Bearer ${process.env.COMECERO_SECRET_TOKEN}` },
  });
  if (!response.ok) throw new Error(`usage so far: ${response.status}`);
  const value = await response.json();
  cache.set(agreementId, { at: Date.now(), value });
  return value;
}
```

Keep the answer for a few minutes, as above. Comecero keeps it for 5 minutes anyway, and an account can make about 30 uncached usage reads a minute (more answer `429`). Never call this from the browser: it needs your secret token.

</Step>

<Step>

## Show the bar [#show-the-bar]

Send your page only what it needs:

```js title="server.js"
app.get('/account/usage', async (req, res) => {
  const period = await usageSoFar(`agr_${req.teamId}`);
  res.json({
    period_end: period.period_end,
    lines: period.entitlements.map((line) => ({
      name: line.metric_name,
      unit: line.unit_label,
      used: line.used,
      included: line.included,
      percent: line.percent,
    })),
  });
});
```

```js title="usage-bar.js"
const { period_end, lines } = await fetch('/account/usage').then((r) => r.json());
for (const line of lines) {
  const percent = Math.min(line.percent ?? 0, 100);
  document.querySelector('#usage').insertAdjacentHTML('beforeend', `
    <p>${line.name}: ${line.used.toLocaleString()} of ${line.included.toLocaleString()} ${line.unit}s</p>
    <progress max="100" value="${percent}"></progress>`);
}
document.querySelector('#renews').textContent = `Resets on ${new Date(period_end).toLocaleDateString()}`;
```

`percent` can be over 100 when the customer is past what is included. The line's `amount` is the price so far, before prepaid credit. Show it only if your customers see prices.

If your customers use the Comecero customer account page, it already shows these meters on its **Subscriptions** page, without prices.

</Step>

<Step>

## Get an alert at 80% [#get-an-alert-at-80]

Create an event subscription for `usage:threshold_reached`. Set `active` to `true`: a new event subscription is off until you do.

```bash title="Request"
curl https://api.comecero.com/api/v1/event_subscriptions \
  -H "Authorization: Bearer $COMECERO_SECRET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "event_type": "usage:threshold_reached",
    "method": "http",
    "format": "json",
    "destination": "https://example.com/webhooks/comecero",
    "active": true
  }'
```

Comecero checks usage about once an hour. When a customer passes 50%, 80% or 100% of an included allowance, it sends the event once for that threshold and period. If usage jumps past two thresholds between checks, only the higher one is sent.

</Step>

<Step>

## Email the customer [#email-the-customer]

Check the signature first, as in the [webhooks guide](/docs/guides/webhooks#check-the-signature). Then act on the alert:

```js title="webhooks.js"
app.post('/webhooks/comecero', express.raw({ type: 'application/json' }), async (req, res) => {
  if (!isFromComecero(req.body, req.get('x-comecero-signature'))) return res.sendStatus(401);
  res.sendStatus(200); // answer fast, then do the work

  const event = JSON.parse(req.body);
  if (event.type !== 'usage:threshold_reached') return;
  if (await alreadyHandled(event.event_id)) return;

  const alert = event.data;
  if (alert.threshold >= 80) {
    await emailTeam(alert.customer_id, {
      subject: `You have used ${alert.percent}% of your ${alert.metric_key} this month`,
      used: alert.used,
      included: alert.included,
      resets: alert.period_end,
    });
  }
});
```

`customer_id` is your own id for the customer, the one your app sends to the usage meter. The alert has ids and numbers only, no email address, so look the customer up in your own data.

</Step>

</Steps>

## Next steps [#next-steps]

- [Follow usage](/docs/usage-billing/follow-usage) has every way to read usage: so far, by hour, and event by event.
- [Usage threshold reached](/api/webhooks/usage-threshold-reached) lists every field of the alert.
- [Sell prepaid credit](/docs/tutorials/sell-prepaid-credit) so customers can pay ahead.
