Operations
Versioning policy, deprecation timeline, rate limits, and key management policy for the Donations Embed.
Operations
Operational policies for the Donations Embed: how we version, how long deprecation windows last, what the rate limits are, and how key management works.
Versioning policy
The Donations Embed follows Semantic Versioning. Three things are versioned independently:
- The API — the HTTP endpoints exposed at
https://api.1stflock.com. The current major is v1; every endpoint is prefixed/v1/embed/. A future major version (v2) will live under/v2/embed/and will not silently break existing integrations. - The browser embed bundle — the JavaScript shipped at
https://payments.1stflock.com/v1.js(live mode, paired withpk_live_…keys) and athttps://sandbox.payments.1stflock.com/v1.js(sandbox mode, paired withpk_test_…keys). The current major is v1. A future v2 will ship at/v2.json both hosts. Existing<script src="…/v1.js">tags will continue to work after a v2 is released. - The server SDKs —
@1st-flock/donations-embed-node,onefirstflock-donations-embed, and the Go module. Each follows semver in its own package registry. The current major is 1.x.x in every language. A future 2.x will ship under the same package name with a major-version bump.
What "v1" guarantees
Within v1 of any of the three artifacts:
- Additive changes — new fields on response bodies, new optional request parameters, new event types, new attributes on the embed, new methods on the SDKs — happen freely. Your code keeps working unless it explicitly forbids unknown fields (which you should not do).
- Behavioural improvements — better error messages, lower latency, broader retry coverage — happen freely.
- Breaking changes — removing a field, changing a field's type, removing a method, changing the meaning of an existing attribute — DO NOT happen. They wait for a major-version bump.
Patch and minor releases
- Patch (1.0.x) — bug fixes only. No new public surface.
- Minor (1.x.0) — additive changes. Backwards-compatible new features.
- Major (2.0.0) — breaking changes. Ships under a new URL path so existing integrations are never silently affected. Accompanied by a 12-month deprecation window for the previous major.
Deprecation timeline
When we deprecate a feature, the timeline is:
| Day | Event |
|---|---|
| 0 | Deprecation announced via the Changelog, in-Hub notification (when your account uses the deprecated surface), and an email to your account contacts. |
| 0–365 | Deprecated feature continues to work exactly as before. New deployments using the deprecated surface receive a Hub-side warning banner. |
| 365 | Deprecated feature is removed. Calls to it return a clear error pointing to the replacement. |
We do not remove anything inside a deprecation window. The 365-day clock is enforced for breaking changes within v1 (rare, but we reserve the option for security-driven removals) and for the v1 → v2 transition.
For security-critical removals (CVE response), we reserve the right to compress the window. We commit to communicating any compression at least 30 days before the new removal date, and we will not compress for non-security reasons.
How you will hear about deprecations
- Changelog — every deprecation lands in the Changelog at the time of announcement.
- In-Hub banner — if your organisation is using the deprecated surface, the Hub displays a banner on the Donations Embed dashboard with a link to migration instructions.
- Email — your account's listed contacts receive a deprecation email at announcement, at the 90-day mark, at the 30-day mark, and at the 7-day mark.
- API response header — calls to a deprecated endpoint include
Flock-Deprecation: <removal-date-iso>so your own monitoring can flag it.
The Hub banner and the API response header are the most important — they tell you specifically which surface in your specific integration is the problem.
Rate limits
| Cohort | Limit | Bucket |
|---|---|---|
| Browser embed (publishable key) | 60 requests / minute | per (publishable key, source IP) |
| Customer SDK (secret key) | 1000 requests / minute | per (secret key, source IP) |
| Hub portal | 1000 requests / minute | per (user, source IP) |
Rate limits use a sliding window with a 1-second granularity. Bursts are absorbed up to the per-minute total; sustained traffic above the limit returns 429.
Rate-limit response
When the limit is exceeded, the API returns 429 with:
HTTP/1.1 429 Too Many Requests
Retry-After: 30
Content-Type: application/json
{
"code": "rate_limited",
"message": "rate limit exceeded"
}
The Retry-After header gives the seconds to wait before retrying. Each SDK surfaces this as a RateLimitError with retryAfter / retry_after parsed from the header.
The 60-req/min browser limit is generous for a per-donor-IP limit (a single donor will not generate 60 requests in a normal flow). The 1000-req/min secret-key limit accommodates per-second polling and bulk operations comfortably.
If you need a higher limit, contact your account manager. We do not raise limits to defeat abuse protections, but we will accommodate genuine workload growth.
Key management
Key types
| Type | Prefix | Where it goes | Expires |
|---|---|---|---|
| Publishable | pk_live_… / pk_test_… | Browser embed, client-side code, public HTML | Never (until revoked or rotated) |
| Secret | sk_live_… / sk_test_… | Server environment variables only | Never (until revoked or rotated) |
| Webhook signing | whsec_… | Server environment variables only | Never (until rotated) |
A "key pair" is one publishable + one secret key, created together and tied to the same environment (live or test).
Creation
Generate keys in the Hub under Donations Embed → Keys. Click Create key pair, set the environment, and give it a descriptive name.
The Hub returns the secret key exactly once at creation time. Store it immediately in your secrets manager. Subsequent reads of the key pair show the publishable key in full but only show a truncated prefix of the secret (e.g. sk_live_a1b2c3d4…). The only way to recover access if you lose the secret is to rotate the pair.
Rotation
To rotate a key pair, click Rotate on the key pair in the Hub. We:
- Issue a new (publishable, secret) pair with the same name and environment.
- Return the new secret once in the response.
- Keep the previous pair valid for 24 hours as a grace window so you can deploy the new keys without downtime.
After 24 hours, the old pair stops working and any traffic still using it returns 401.
The 24-hour grace window is the recommended way to do a zero-downtime rotation:
- Rotate in the Hub. Save the new secret.
- Update your deployments to use the new pair.
- Verify the new pair is in use (check the Hub's Last used at column or your own logs).
- Optional: revoke the old pair explicitly to close the window early once you have confirmed the new pair is taking all traffic.
Revocation
Click Revoke on a key pair in the Hub. Revocation is immediate — there is no grace window. Subsequent requests authenticated with either half of the pair return 401.
Use revocation when:
- A key has been confirmed compromised (immediately stop the bad actor's access).
- A key is no longer needed (clean up after a project ends).
For routine credential rotation, prefer rotate (which gives you the 24-hour overlap) over revoke + create (which gives you immediate downtime).
Origin allowlist
Publishable keys are scoped to one or more origin patterns. Set the allowlist under Donations Embed → Keys → Edit allowlist for the key. Each entry must match ^(\*\.)?[A-Za-z0-9.-]+(:\*|:\d+)?$:
| Pattern | Matches |
|---|---|
donations.example.org | Exactly that origin. |
*.example.org | Any subdomain of example.org (including donations.example.org and give.example.org, but NOT example.org itself). |
localhost:3000 | Local development on port 3000. |
localhost:* | Local development on any port. |
Browsers send the Origin header on every cross-origin request; if the origin does not match any pattern on the key's allowlist, the API returns 403. This means a leaked publishable key cannot be used from a domain you do not control.
Automatic freezing
We monitor publishable keys for card-testing patterns — bursts of declined attempts within a short window. When detected, the key pair is frozen automatically:
- Subsequent requests authenticated with either half of the pair return
403. - A
key.frozenwebhook event is delivered to your endpoint with the trigger details (number of declines, window, frozen-at timestamp). - The Hub displays a banner on the dashboard.
To recover:
- Investigate the source of the abusive traffic. Often it is your publishable key being used from a domain you do not own — adjust the origin allowlist to lock it down.
- Rotate the pair from the Hub.
- Update your deployments to use the new pair.
- Contact 1st Flock support if you need the original pair manually unfrozen (rare; typically rotation is sufficient).
The freeze threshold is conservative — it triggers on patterns that are extremely unlikely under legitimate traffic. False positives are uncommon. If you believe one fired, contact support with the pk_prefix from the webhook payload.
Customer support
For everything else, contact us:
- Documentation feedback — open a GitHub issue on the docs repo (link in the footer of any docs page).
- Integration questions — developers@1stflock.com.
- Outages or incidents — support@1stflock.com, 24/7.
- Security disclosures — security@1stflock.com. PGP key on the security page.
- Compliance and SAQ A questions — compliance@1stflock.com.
For real-time integration support, your account manager can grant access to a private Slack channel — ask them.
Next steps
- Changelog — what changed in each release.
- API Reference — endpoint-by-endpoint detail.
- Compliance & Security — your obligations and our certifications.