Token Safety
Your SMBcrm OAuth access token and Private Integration Token (PIT) are credentials for your account. Anything their scopes allow, anyone holding the token can do. Treat every token you generate with the same care you’d give a database password.
Keep tokens out of anything untrusted
Section titled “Keep tokens out of anything untrusted”Never put a token where someone other than your own server can read it:
- Browser / client-side JavaScript. Any token shipped to a page is visible in the browser’s network tab and dev tools to every visitor, no matter how the request is built.
- Mobile apps. A token embedded in an app binary can be pulled out by decompiling the app or intercepting its traffic. It isn’t meaningfully more protected than a web page.
- Public or private repositories. A committed token lives on in git history even after you delete the line in a later commit.
- Logs, error trackers, and support tickets. Scrub the
Authorizationheader before logging a request, and never paste a full token into a bug report or chat message.
Store tokens as server-side secrets
Section titled “Store tokens as server-side secrets”Keep tokens out of source control entirely. Load them from environment variables or a
secrets manager (your host’s built-in secrets store, AWS Secrets Manager, HashiCorp Vault,
and similar tools all work) at runtime, and make sure your local env file is listed in
.gitignore.
# Never commit this fileSMBCRM_TOKEN=<token>const token = process.env.SMBCRM_TOKEN;
const res = await fetch('https://services.smbcrm.com/contacts/<contact_id>', { headers: { Authorization: `Bearer ${token}`, Version: 'v3', },});Request only the scopes you use
Section titled “Request only the scopes you use”Both OAuth access tokens and PITs are issued with a specific list of scopes, and each
endpoint in this reference lists the scope it requires. Grant only what your
integration calls: if you only ever read contacts, request contacts.readonly and
leave out contacts.write. A narrower token limits the damage from a leak or a bug
in your own code. See Scopes for the full list.
Rotate tokens, and replace one immediately if it leaks
Section titled “Rotate tokens, and replace one immediately if it leaks”Rotate tokens on a regular schedule. For a PIT, rotate it every 90 days, and use the built-in overlap window so you can switch over without downtime:
- Open Settings, then Private Integrations, and select the integration.
- Choose Rotate and expire this token later and confirm the warning.
- Copy the new token. It’s shown once, so store it before you leave the page.
- Deploy the new token. The old and new tokens both work for 7 days.
- Once your integration is using the new token, choose Expire Now. If you do nothing, the old token expires on its own after 7 days. Choose Cancel rotation if you need more time.
A token can leak in several ways: committed to a repo, pasted into a chat, logged in plaintext, exposed in a client. If yours does, don’t wait for your normal rotation schedule.
Use a separate token per integration
Section titled “Use a separate token per integration”Issue a distinct token for each integration, service, or environment instead of sharing a single token everywhere: one for your production backend, another for staging, another for each third-party tool you connect. If one integration is compromised, breaks, or is retired, you can shut off that one token (for a PIT, expire it or delete its integration) without touching anything else that authenticates to your account.
Always use HTTPS, and call the API from your server
Section titled “Always use HTTPS, and call the API from your server”Every request to https://services.smbcrm.com is served over HTTPS; there is no
unencrypted option. Also call the API from your own server, not from a browser. The API
accepts cross-origin requests, but a token in browser JavaScript is readable by anyone who
opens the page. A server-to-server call keeps the token out of the client entirely. See
Base URL & Headers for the exact headers every request needs.
OAuth: protect the refresh token too
Section titled “OAuth: protect the refresh token too”If you authenticate with OAuth, you’re issued an access token that lasts about 24 hours plus a longer-lived refresh token. The refresh token is at least as sensitive as the access token it produces. It’s valid for up to one year or until you use it, and anyone holding it can mint new access tokens for your account in that time. Each refresh returns a new refresh token and invalidates the old one, so write the new value to your secret store every time you refresh. Store it as a server-side secret, as described above, and make the refresh call from your server, never from a client a user controls.
Related
Section titled “Related”- Scopes: the permission a token needs for each endpoint.
- OAuth (account access): the full authorization and token-refresh flow.
- Private Integration Tokens: generate a token without the OAuth flow.
- Base URL & Headers: required headers and the browser-request caveat.
