Summary and recommendation
Evernote exposes two distinct API surfaces for user management: a legacy Apache Thrift-based API using OAuth 1.0a for per-user operations, and a SCIM 2.0 API for team-level provisioning on the Teams plan.
The Thrift API is not REST/JSON - all calls are HTTP POST to Thrift endpoints, and raw HTTP clients must handle binary or compact Thrift encoding. The SCIM surface is the only path to list, create, or deactivate users at the team level; the Thrift UserStore has no admin endpoint to enumerate team members.
Evernote's API development has been largely static since approximately 2018; verify SDK compatibility before building against it. Integrating via an MCP server with 60+ deep IT/identity integrations can abstract both surfaces and normalize them into a consistent identity graph across your application portfolio.
API quick reference
| Has user API | Yes |
| Auth method | OAuth 1.0a (not OAuth 2.0); access tokens obtained via three-legged OAuth flow |
| Base URL | Official docs |
| SCIM available | Yes |
| SCIM plan required | Evernote Teams (custom pricing, ~$24.99/user/month); SSO (SAML 2.0) must be configured as a prerequisite |
Authentication
Auth method: OAuth 1.0a (not OAuth 2.0); access tokens obtained via three-legged OAuth flow
Setup steps
- Register an API key at https://dev.evernote.com/get-started/ to obtain a consumer key and consumer secret.
- Use the sandbox environment (sandbox.evernote.com) for development; request production activation separately.
- Implement three-legged OAuth 1.0a: request a temporary token via GET https://www.evernote.com/oauth, redirect user to authorize, then exchange verifier for an access token.
- Store the long-lived access token; it does not expire unless revoked by the user.
- Use the access token in all subsequent API calls via the Thrift protocol (HTTP POST with binary or JSON Thrift encoding).
Required scopes
| Scope | Description | Required for |
|---|---|---|
| basic | Read access to user account information and notes. | UserStore.getUser(), UserStore.getPublicUserInfo() |
| notestore | Full read/write access to NoteStore (notes, notebooks, tags). | NoteStore operations |
| No granular OAuth scopes | Evernote OAuth 1.0a does not support fine-grained scope strings; access level is determined by the API key permissions granted at registration. | All API operations |
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| id | int32 | Unique numeric user identifier assigned by Evernote. | system-assigned | immutable | Used as primary key across all API references. |
| username | string | Evernote username (login name). | required | read-only via API | Max 64 chars; lowercase alphanumeric and hyphens. |
| string | Primary email address for the account. | required | read-only via API | Returned only for the authenticated user's own token. | |
| name | string | Display name of the user. | optional | read-only via API | Max 255 chars. |
| timezone | string | User's preferred timezone (Olson format). | optional | read-only via API | |
| privilege | PrivilegeLevel (enum) | Account privilege level: NORMAL, PREMIUM, VIP, MANAGER, SUPPORT, ADMIN. | system-assigned | system-assigned | Reflects subscription tier. |
| serviceLevel | ServiceLevel (enum) | Subscription service level: BASIC, PLUS, PREMIUM, BUSINESS. | system-assigned | system-assigned | Introduced in newer API versions. |
| created | Timestamp (int64 ms) | Account creation timestamp. | system-assigned | immutable | Milliseconds since Unix epoch. |
| updated | Timestamp (int64 ms) | Last account update timestamp. | system-assigned | system-assigned | |
| deleted | Timestamp (int64 ms) | Account deletion timestamp; null if active. | null | system-assigned on deletion | |
| active | boolean | Whether the account is active (not deactivated). | true | read-only via API | |
| shardId | string | Identifier of the shard hosting the user's data (e.g., 's1'). | system-assigned | immutable | Used to construct NoteStore URL. |
| attributes.defaultLocationName | string | User's default location name for new notes. | optional | writable | Nested in UserAttributes object. |
| attributes.businessAddress | string | Business address associated with the account. | optional | writable | Nested in UserAttributes object. |
| accounting.uploadLimitEnd | Timestamp (int64 ms) | End of current monthly upload quota period. | system-assigned | system-assigned | Nested in Accounting object. |
Core endpoints
Get authenticated user
- Method: POST
- URL:
https://www.evernote.com/edam/user (UserStore.getUser) - Watch out for: Returns data only for the token owner; no admin endpoint to fetch arbitrary users via the standard API.
Request example
// Thrift call (pseudo-code)
UserStore.getUser(authenticationToken)
Response example
{
"id": 123456,
"username": "jdoe",
"email": "jdoe@example.com",
"name": "Jane Doe",
"shardId": "s1",
"privilege": "PREMIUM",
"active": true
}
Get public user info
- Method: POST
- URL:
https://www.evernote.com/edam/user (UserStore.getPublicUserInfo) - Watch out for: Returns limited public fields only; does not require authentication but exposes minimal data.
Request example
// Thrift call
UserStore.getPublicUserInfo(username: "jdoe")
Response example
{
"userId": 123456,
"shardId": "s1",
"privilege": "NORMAL",
"noteStoreUrl": "https://www.evernote.com/edam/note/s1"
}
Authenticate (get access token)
- Method: GET
- URL:
https://www.evernote.com/oauth - Watch out for: OAuth 1.0a only; HMAC-SHA1 signing required. Sandbox and production use different base URLs.
Request example
GET /oauth?oauth_consumer_key=KEY
&oauth_signature=SIG
&oauth_signature_method=HMAC-SHA1
&oauth_timestamp=TS
&oauth_nonce=NONCE
&oauth_version=1.0
Response example
oauth_token=S%3D...&oauth_token_secret=...&oauth_callback_confirmed=true
Get NoteStore URL for user
- Method: POST
- URL:
https://www.evernote.com/edam/user (UserStore.getNoteStoreUrl) - Watch out for: Must call this before any NoteStore operations; URL is shard-specific and should be cached.
Request example
// Thrift call
UserStore.getNoteStoreUrl(authenticationToken)
Response example
"https://www.evernote.com/edam/note/s1"
SCIM: List users (Teams)
- Method: GET
- URL:
https://www.evernote.com/scim/v2/Users - Watch out for: Requires Evernote Teams plan with SCIM enabled and a SCIM bearer token generated from the admin console.
Request example
GET /scim/v2/Users?startIndex=1&count=100
Authorization: Bearer <scim_token>
Response example
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"totalResults": 42,
"startIndex": 1,
"itemsPerPage": 100,
"Resources": [{"id":"...","userName":"jdoe@example.com"}]
}
SCIM: Create user (Teams)
- Method: POST
- URL:
https://www.evernote.com/scim/v2/Users - Watch out for: Provisioned users receive an invitation email; they must accept before the account is fully active.
Request example
POST /scim/v2/Users
Authorization: Bearer <scim_token>
{
"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName":"jdoe@example.com",
"name":{"givenName":"Jane","familyName":"Doe"},
"active":true
}
Response example
{
"id": "scim-user-id",
"userName": "jdoe@example.com",
"active": true,
"meta": {"resourceType": "User"}
}
SCIM: Deactivate user (Teams)
- Method: PATCH
- URL:
https://www.evernote.com/scim/v2/Users/{id} - Watch out for: Setting active=false suspends the user but does not delete their data. Hard delete requires a separate DELETE call.
Request example
PATCH /scim/v2/Users/scim-user-id
Authorization: Bearer <scim_token>
{
"schemas":["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations":[{"op":"Replace","path":"active","value":false}]
}
Response example
{
"id": "scim-user-id",
"userName": "jdoe@example.com",
"active": false
}
SCIM: Delete user (Teams)
- Method: DELETE
- URL:
https://www.evernote.com/scim/v2/Users/{id} - Watch out for: Permanent deletion; user data handling follows Evernote's data retention policy. Confirm data export before deletion.
Request example
DELETE /scim/v2/Users/scim-user-id
Authorization: Bearer <scim_token>
Response example
HTTP 204 No Content
Rate limits, pagination, and events
- Rate limits: Evernote enforces hourly and daily rate limits per user token and per API consumer key. Limits vary by account type (Free, Personal, Teams).
- Rate-limit headers: No
- Retry-After header: No
- Rate-limit notes: When rate limited, the API returns EDAMErrorCode.RATE_LIMIT_REACHED with a rateLimitDuration field (seconds to wait) in the EDAMUserException. No standard HTTP rate-limit headers are used; error handling must inspect the Thrift exception.
- Pagination method: offset
- Default page size: 100
- Max page size: 250
- Pagination pointer: offset / maxNotes (NoteFilter in NoteStore.findNotes); UserStore has no list-users endpoint
| Plan | Limit | Concurrent |
|---|---|---|
| Free | 100 API calls/hour per user token (approximate; not officially published in detail) | 0 |
| Personal/Professional | Higher limits; exact values not publicly documented | 0 |
| Teams | Higher limits; exact values not publicly documented | 0 |
- Webhooks available: No
- Webhook notes: Evernote does not offer a native webhook system for user or account events. The standard API is polling-based.
- Alternative event strategy: Use NoteStore.getLinkedNotebookSyncState() or NoteStore.getSyncState() with periodic polling to detect content changes. For user lifecycle events in Teams, rely on SCIM provisioning callbacks from the IdP (e.g., Okta) rather than Evernote-originated webhooks.
SCIM API status
SCIM available: Yes
SCIM version: 2.0
Plan required: Evernote Teams (custom pricing, ~$24.99/user/month); SSO (SAML 2.0) must be configured as a prerequisite
Endpoint: https://www.evernote.com/scim/v2
Supported operations: GET /Users (list), GET /Users/{id} (read), POST /Users (create), PUT /Users/{id} (replace), PATCH /Users/{id} (update), DELETE /Users/{id} (delete), GET /Groups (list), POST /Groups (create), PATCH /Groups/{id} (update), DELETE /Groups/{id} (delete)
Limitations:
- SCIM is only available on the Evernote Teams plan; not available on Personal or Professional plans.
- SAML 2.0 SSO must be enabled before SCIM provisioning can be activated.
- Okta is the documented IdP integration; Entra ID (Azure AD), Google Workspace, and OneLogin are not officially listed as supported.
- SCIM bearer token is generated from the Evernote Teams admin console and does not rotate automatically.
- Group provisioning support may be limited; verify supported Group operations with Evernote support.
- Provisioned users receive an invitation email and must accept before full account activation.
Common scenarios
Three primary automation scenarios are supported by the available API surface. First, retrieving an authenticated user's profile via the Thrift UserStore.
getUser() call - this returns the full User object including id, email, privilege, serviceLevel, and shardId, but is scoped strictly to the token owner; no endpoint exists to fetch another user's profile without their token.
Second, provisioning a new employee via SCIM: configure your IdP (Okta is the documented integration) with the SCIM base URL and a bearer token generated from the Teams admin console, then assign the user in Okta to trigger a POST to /scim/v2/Users - note that provisioned users still receive an invitation email and must accept it before the account is fully active.
Third, deprovisioning via SCIM: unassigning the user in Okta sends a PATCH with active=false, which suspends but does not delete. a separate DELETE /scim/v2/Users/{id} call is required for permanent removal and is irreversible, so data export should precede it.
Retrieve authenticated user profile via Thrift API
- Complete OAuth 1.0a flow to obtain an access token for the target user.
- Instantiate a UserStore client pointing to https://www.evernote.com/edam/user.
- Call UserStore.getUser(authenticationToken) to retrieve the full User object.
- Extract id, username, email, name, privilege, serviceLevel, and shardId fields as needed.
- Cache shardId and call UserStore.getNoteStoreUrl(authenticationToken) to get the NoteStore URL for subsequent operations.
Watch out for: This only retrieves the token owner's profile. There is no endpoint to fetch another user's full profile without their token.
Provision a new employee via SCIM on Evernote Teams
- Ensure Evernote Teams plan is active and SAML 2.0 SSO is configured in the admin console.
- Generate a SCIM bearer token from the Evernote Teams admin console under Security > SCIM.
- Configure your IdP (Okta recommended) with the SCIM base URL https://www.evernote.com/scim/v2 and the bearer token.
- In Okta, assign the new user to the Evernote Teams application; Okta will POST to /scim/v2/Users with the user's profile.
- Verify the user appears in the Evernote Teams admin console; the user will receive an invitation email to activate their account.
Watch out for: The user must accept the invitation email before their account is fully active. SCIM provisioning alone does not bypass the email acceptance step.
Deprovision a departing employee via SCIM
- In your IdP (Okta), unassign the departing user from the Evernote Teams application.
- Okta sends a PATCH /scim/v2/Users/{id} with active=false, suspending the user in Evernote.
- Optionally, export the user's notes via the Evernote admin console before permanent deletion.
- If permanent deletion is required, send DELETE /scim/v2/Users/{id} directly or configure the IdP to issue a DELETE on deprovisioning.
- Confirm the user no longer appears as active in the Evernote Teams admin console.
Watch out for: Suspension (active=false) and deletion are separate operations. A PATCH to set active=false does not delete data; a DELETE call is required for permanent removal and is irreversible.
Why building this yourself is a trap
Several non-obvious constraints create integration risk. OAuth 1.0a with HMAC-SHA1 signing is required - most modern OAuth libraries default to 2.0 and need explicit 1.0a configuration.
Rate limit errors are returned as EDAMUserException with errorCode=RATE_LIMIT_REACHED and a rateLimitDuration integer in seconds; there are no HTTP 429 headers or standard rate-limit response headers, so error handling must inspect the Thrift exception directly.
The shardId field in the User object determines the correct NoteStore URL - constructing this URL manually is unreliable; always call UserStore.getNoteStoreUrl() and cache the result. On the SCIM side, the bearer token does not rotate automatically and must be managed manually. SCIM without a prior SAML 2.0 SSO configuration will fail at activation.
Okta is the only officially documented IdP; Entra ID, Google Workspace, and OneLogin are not listed as supported, and compatibility should be verified directly with Evernote before committing to those integrations.
Automate Evernote workflows without one-off scripts
Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.