The Bonusly RESTful JSON API is a great way to programmatically manage parts of your organization's account. You can use it to roll your own solutions, gather data and more. Our API is easy to integrate with any stack or programming language.
In this article, we'll walk through generating an API key and making a request to the API using your key. This article assumes some familiarity with RESTful APIs, including making requests, setting headers and interpreting JSON responses.
Getting an API access token
Bonusly's API uses **Personal Access Tokens (PATs)**. There are two mint surfaces depending on what the token is for:
Company-wide integration tokens** (Snowflake ETLs, Zapier replacements, MCP-adjacent automations on behalf of the org, etc.) are minted by a Global or Tech admin from **Company → Integrations → API & Tokens
Personal automation tokens** (calling the API on your own behalf — e.g. a script that gives recognition from your account or pulls your own feed) are minted from your own **Settings → Services** page. Any Bonusly user can do this; the scopes you see are filtered to what your role is allowed to grant.
Both surfaces produce the same kind of bearer token — the API itself doesn't distinguish "admin-minted" from "user-minted" PATs. What each token can do is decided entirely by the scopes attached at mint time.
To mint one:
Open the appropriate mint surface (above).
Click **Create token** (admin page) or **Generate** (Settings → Services).
Give the token a descriptive name (e.g. "Snowflake nightly ETL", "Personal Slack daily-bonus script"), pick an expiration (up to 365 days; the modal offers 30/90/180/365), and select the scopes the integration needs.
Click **Create**. Bonusly will show the token string **once** — copy it into your integration before closing the dialog. We only store a hash; the plaintext is not retrievable afterwards. If you lose the token, mint a new one.
A few things worth knowing:
Tokens expire.** Every PAT has an expiration of up to one year. Bonusly emails the token's owner 30 days and 7 days before expiry; mint a replacement and update the integration when you get those reminders.
One token per integration.** If a vendor changes or a key is exposed, you can revoke that one token without touching the others.
Revocation is immediate.** Use the row's revoke action on the API & Tokens page to invalidate a token right away.
The full scope catalog and details on each endpoint live at docs.bonus.ly
Permissions and scopes
There are no longer two flavors of token ("admin" vs "regular user"). What a token can do is determined entirely by the **scopes** it was granted at mint time:
Global admin** can mint a token with any scope, including finance-, awards-, and company-administer scopes.
Tech admin** can mint tokens that read or write company data, including `user:administer` (needed for SCIM). Some scopes (e.g. `finance:administer`) are reserved for Global admins.
Regular user** can mint tokens scoped to actions they could already take in the UI on their own account — useful for personal automation. Company-administer scopes aren't offered on the user-settings mint surface.
Common scopes:
`user:read`, `user:write`, `user:administer` (the last is required for SCIM, but SCIM tokens are minted from the SCIM tile, not hand-picked here — see Bonusly API access for admins)
`recognition:read`, `recognition:write`, `recognition:administer`
`awards:read`, `awards:write`, `awards:administer`
`finance:administer`
`company:read`, `company:administer`
`analytics:read`
`uploads:write`
When you mint a token, the scopes your admin role can't grant are hidden from the list. Hitting an endpoint with a token that lacks the right scope returns a `403 Forbidden`.
Sending your access token to the API
The Bonusly API has two surfaces, and PATs work on both:
The original REST API at https://bonus.ly/api/v1/
The newer public API at https://bonus.ly/api/public/, which enforces scopes more strictly
Always authenticate API requests with the bearer token in an HTTP header:
Authorization: Bearer 0123456789abcdefghijklmnopqrstuv
If your integration only supports query-string authentication, you can also pass the token as `access_token=...`. We recommend the header form because query parameters can leak into server logs and browser history.
If you make an API request without a token and rely on your browser session/cookies instead, non-GET requests will fail CSRF verification with `403 Forbidden`. Always authenticate with a PAT.
Making a request to the API
You can read about our various endpoints in our API documentation. We have endpoints for analytics, bonuses, company information, redemptions, rewards, and users.
As an example, let's look up the user the token belongs to. Send a GET request to `/users/me` with the token in the `Authorization` header:
-H "Authorization: Bearer 0123456789abcdefghijklmnopqrstuv"
The API returns JSON with the user's profile. You can read the full documentation about the `/users/me` endpoint here.
Next steps: full API documentation and API explorer
You can access our full API documentation and use our API explorer at docs.bonus.ly. For an admin-level overview of how PATs fit together with SCIM, Digital Signage, and other Bonusly integrations, see Bonusly API access for admins. We can't wait to see what you build!
Questions? Send us a note to [email protected]; we'd be happy to help!
Was this article helpful? Let us know by rating it below with an emoji and sharing your feedback!
