REDCap projects routinely hold PHI and other sensitive data, and an API token is a bearer credential for a user's entire set of project rights.
All API traffic must go over HTTPS, and the client must validate the server's SSL certificate on every request. Without validation, a machine-in-the-middle can present a fake certificate, receive the request — token included — and then replay that token against the real server as the token's owner.
Validation is a one-line setting in every ecosystem, and usually the default:
| Client | Setting |
|---|---|
| cURL / PHP / R / SAS via cURL | CURLOPT_SSL_VERIFYPEER = TRUE (never set it to false) |
Python requests |
Verifies by default — never pass verify=False |
curl CLI |
Verifies by default — never use -k / --insecure |
If verification fails, the certificate chain is broken (see Errors & Troubleshooting, rung 2). Fix the chain; disabling verification converts a configuration problem into a token-disclosure vulnerability.
A token functions as a standalone password. Handle it accordingly:
-
Never hard-code or commit tokens. Load them at runtime from an environment variable, a secrets manager, or an OS keyring:
export REDCAP_TOKEN="..." # e.g. from your shell profile or a .env NOT in git
import os token = os.environ["REDCAP_TOKEN"] # or keyring.get_password("redcap", "myproject")
Add
.envand credential files to.gitignorebefore the first commit. A token that ever landed in git history is exposed — rewriting history does not un-expose it. -
One token per user per project — no sharing. Each user requests their own token on the project's API page. Shared tokens destroy the audit trail (every action logs as one person) and force revocation to affect every consumer of the token.
-
Rotate on exposure. If a token appears in a repo, log, chat message, or URL, regenerate it immediately on the project's API page; the old one stops working the moment a new one is issued.
-
Keep tokens out of URLs and logs. The API is POST-only partly for this reason — never move the token into a query string, and scrub request bodies from debug logs.
The token inherits everything its user can do, so restrict the user account rather than the token:
- Create a dedicated account (or use the institution's service-account mechanism) for each automated integration, rather than using an individual's personal token.
- Give it a role with the minimum rights the job needs: an export-only pipeline gets API Export and the relevant Data Export rights and nothing else — no API Import/Update, no Delete Record, no User Rights. Import User Roles supports defining such roles reproducibly.
- Review rights when the integration's job changes, and expire the account when it ends (user rows support an
expirationdate).
Read-only tokens are also an effective guardrail against automation accidents — see Safety.
- Prefer de-identified rights when identifiers aren't needed. Data Export rights come in four levels — Full Data Set, Remove Identifier Fields, De-Identified, No Access. A dashboard or stats pipeline that never needs names or dates should run as a user with reduced export rights, so identifiers physically cannot leave REDCap through that token.
- The filtering is silent. Reduced export rights return a successful response with identifier fields absent — intended when configured deliberately, easily mistaken for data loss otherwise. Document which rights each integration runs with.
- Identifier-tagged file fields are similarly blocked for reduced-rights users on file export.
- Exported data must be stored with equivalent access controls. Do not let PHI accumulate in scratch directories, notebooks, or CI logs.
Every API action — exports included — is written to the project's logging. Use Export Logging to review who did what and when (logtype=export for data exports, user for rights changes, beginTime/endTime to window it). Audit API activity periodically to verify the controls above are in effect; recipe (e) in Recipes shows the call.
- HTTPS with certificate validation on (the default; do not disable)
- Tokens in env vars / secret store / keyring;
.gitignorecovers credential files - One token per user per project; dedicated least-privilege accounts for automation
- Export rights set to the minimum level each integration needs
- Rotation procedure known and tested; logging reviewed periodically