API key expiration reminders
How WinkPG warns a key's owner ahead of API key expiry, and how to route those warnings to email, a webhook, or another channel your team reads.
An API key created with an expiration date stops authenticating the moment that date arrives, and an integration that learns this from a failed call learns it at the worst possible time. WinkPG therefore warns the key's owner ahead of expiry, more than once and with rising urgency, so the rollover happens on your schedule instead of the key's.
This guide covers when the reminders fire, where they arrive, how to route them to a channel your team reads, and how to plan the rollover they exist to prompt.
Which keys get reminders
Only keys with an expiration date. A key created without one never expires and never generates a reminder. The expiration is chosen when the key is created, from tomorrow up to a year out; Getting started with the API covers the creation flow.
Reminders are about expiry alone. Revoking or deleting a key takes effect immediately and sends no advance warning, because there's nothing to warn ahead of: the action itself is the decision.
When reminders fire
The cadence escalates as expiry approaches. By default:
| Reminder | Fires when |
|---|---|
| First warning | 30 days before expiry |
| Second warning | 7 days before expiry |
| Final warning | 1 day before expiry |
Four details are worth knowing:
- Each threshold fires at most once per key. A key that keeps its expiration date receives at most three reminders, one per threshold, not a daily drumbeat.
- Keys are checked once a day, so a reminder arrives within a day of the key crossing a threshold rather than at the precise instant.
- A key created close to expiry gets one warning, not a backlog. A key minted with three days to live is already inside both the 30-day and the 7-day windows; only the most urgent threshold fires, and the final warning still follows on its own schedule.
- Extending the expiration resets the cycle. A key whose expiration date is pushed out starts fresh and receives the full set of reminders for the new date.
The thresholds are platform settings, so a specific deployment can differ from the defaults above. There's no settings page for them; a platform administrator adjusts them through setting management.
Where reminders arrive
Both delivery paths are driven by the same underlying event:
- The key's owner is notified in the portal automatically. Every reminder arrives as a notification in the portal for the owner of the key, with the key's name, its expiration date, and the days remaining. This needs no setup and can't be turned off by mistake, so the person who created the key always hears about it.
- The
ApiKey.Expiringevent can be routed anywhere notifications go. A notification subscription can deliver each reminder to email, a webhook, Slack, SMS, or a queue.
The first path reaches one person, in the portal, and only when they sign in. Wire the second whenever the warning needs to reach a shared inbox, a team channel, or a system that opens a ticket.
Reminders are the push half. The same warning window also drives an Expiring soon badge wherever keys are listed, in the API Keys grid and in the Developer Portal, so the countdown is visible whenever you look rather than only when a reminder arrives.
Route reminders to a channel your team reads
The event appears in the event catalog (Notifications, then Event Types) as API Key Expiring, in the API Keys category. Subscribe from the catalog row's action or create a subscription at /Notifications/Subscriptions/add; Configuring notifications covers the destination, channel, and subscription model this rides on.
One constraint to know going in: the event's Max scope is Admin, so only a tenant-wide subscription can match it, and creating one requires administrative permissions. A merchant-scoped or reseller-scoped subscription never receives this event.
A tenant-wide subscription hears about every expiring key in the tenant. The event's filter fields narrow that:
| Field | Type | Use it to |
|---|---|---|
apiKey.name |
Text | Watch specific keys by name, such as everything named for production. |
apiKey.ownerUserId |
Text | Watch keys belonging to particular users. |
apiKey.daysRemaining |
Number | Match on the actual runway left when the reminder fired. |
apiKey.thresholdDays |
Number | Match on which reminder this is. |
The last two sound alike and answer different questions. apiKey.thresholdDays names the rung of the reminder ladder that fired: 30, 7, or 1 under the default cadence. apiKey.daysRemaining is the key's actual runway, which can be less than the threshold when a key entered the window late. To receive only the final reminder, filter on apiKey.thresholdDays equals 1.
What a webhook receiver gets
The event's data object carries the key's management identity and its runway, and never the key itself:
{
"ApiKeyId": "9d2c7f0e-5f3a-4b8e-9c1d-2e6f7a8b9c0d",
"Name": "Order service (production)",
"OwnerUserId": "5b0e8d3a-1c2b-4f6e-8a9d-0c1e2f3a4b5c",
"ExpiresAtUtc": "2026-09-30T00:00:00Z",
"DaysRemaining": 6,
"ThresholdDays": 7
}
ApiKeyIdis the key's id in the management API and the portal, so an alert can link straight to the key's detail page at/ApiKeys. It identifies the key and authenticates nothing. No field in this payload can: the key's secret value is shown once at creation and never delivered anywhere afterward.ExpiresAtUtcis the instant the key stops authenticating, in UTC.ThresholdDaysis what distinguishes the reminders from each other. A receiver that treats a later reminder as a duplicate of the first drops the final warning, which is the one that matters most. Deduplicate on the delivery headers instead, as covered in Webhook integration.
The envelope around data, the signature scheme, and the retry semantics are the standard webhook contract described in that guide, and the event's catalog entry carries a complete sample envelope. One thing to notice in the sample above: the data field names are PascalCase, unlike the camelCase envelope fields around them.
Plan the rollover
Treat an expiring key the way you'd treat an expiring certificate: replace it while the old one still works, and let the reminders set the pace rather than the deadline.
- Create the replacement. The simplest way is the Rotate action on the key's row at
/ApiKeys, which issues a replacement that inherits the old key's scopes and source-address allowlist, and keeps the old key working during a short overlap window so the switch isn't a hard cutover. Two properties of that window matter here: it never extends past the old key's own expiration date, so a rollover left until the final reminder gets little or none of it, and the replacement's term is a fresh one measured from the rotation, so rotating early costs you nothing. - Deploy the replacement to the systems that use the key.
- Confirm traffic has moved. Watch Last Used on both keys from
/ApiKeysuntil the old key goes quiet and the new one carries the traffic. - Retire the old key. Revoke or delete it, or let the overlap window end it for you.
A key past its expiration date answers every call with KEY_EXPIRED; the Getting started with the API guide covers that error and its recovery. Rotating an already-expired key is allowed and hands you a working replacement immediately, so an integration that did miss every reminder is still one action away from working again.
See also
- Getting started with the API: creating a key with an expiration date, and the
KEY_EXPIREDauthentication error a lapsed key produces. - Webhook integration: the envelope, the signature scheme, and the deduplication headers for the webhook path.
- Configuring notifications: the destination, channel, and subscription model that routes the
ApiKey.Expiringevent.