# How to Integrate Retool with Evernote

- Tool: Retool
- Difficulty: Intermediate
- Time required: 30 minutes
- Last updated: April 2026

## TL;DR

Connect Retool to Evernote using a REST API Resource with OAuth 1.0a authentication to access the Evernote Cloud API. Query notebooks and notes to build knowledge search panels and note management dashboards that combine Evernote content with internal data from other Retool Resources — ideal for teams that document processes in Evernote but need to surface notes alongside operational data.

## Build Evernote Knowledge Search and Note Management Panels in Retool

Evernote's web interface is excellent for individual note management, but operations and support teams often need to search Evernote alongside other tools — looking up documentation while working in a support ticket tool, or surfacing process notes while managing customer records. Retool solves this by connecting to Evernote's API and combining its content with data from other Resources in a unified dashboard.

Evernote's API uses the Thrift-based EDAM (Evernote Data Access and Management) protocol for its native SDK, but also exposes a REST-compatible Cloud API for simpler HTTP integrations. Authentication uses OAuth 1.0a — a legacy protocol compared to modern OAuth 2.0, but one that generates long-lived tokens suitable for server-side integrations without frequent token refresh. The API provides access to notebooks, notes, tags, saved searches, and note content including attachments.

Common Retool apps built on Evernote include: internal knowledge base search panels that let support teams find relevant process notes without switching tools, notebook management dashboards for team wikis that show recently updated notes and popular notebooks, note creation tools that automatically generate structured notes from Retool form data, and content audit dashboards that find notes without tags or with outdated content based on modification dates.

## Before you start

- An Evernote account with API access (Evernote Business or Premium for team notebook access)
- An Evernote API key pair (consumer key and consumer secret) obtained by applying at dev.evernote.com
- A long-lived OAuth 1.0a access token obtained through Evernote's OAuth flow or the developer sandbox
- A Retool account with permission to create Resources
- Basic familiarity with REST API concepts and HTTP headers

## Step-by-step guide

### 1. Obtain an Evernote API key and OAuth access token

Navigate to dev.evernote.com and log in with your Evernote account. Click 'Get an API Key' and fill out the application form describing your integration use case. Evernote reviews all API key requests — for internal Retool integrations, explain that you are building an internal admin tool and select 'Full Access' for the requested permissions. Once approved, you receive a consumer key and consumer secret. For a server-side Retool integration where you control both the client and the Evernote account, the most practical approach is to use Evernote's OAuth 1.0a flow in the developer sandbox first, obtain a long-lived access token, and then use the same flow in production. Alternatively, Evernote provides developer tokens for the sandbox environment directly at dev.evernote.com/get-started/testing.php — these are long-lived tokens that work immediately without the full OAuth flow, useful for testing. For production use, complete the full OAuth 1.0a flow: request a temporary token from oauth.evernote.com/oauth, redirect to oauth.evernote.com/OAuth.action for user authorization, then exchange the verifier for a long-lived access token at oauth.evernote.com/oauth. Store the resulting access token — it does not expire unless the user revokes it.

**Expected result:** You have an Evernote consumer key, consumer secret, and a long-lived OAuth access token for the account you want to connect to Retool.

### 2. Create the Evernote REST API Resource in Retool

In Retool, navigate to the Resources tab and click 'Create New'. Select 'REST API' from the resource type list. Set the Base URL to 'https://www.evernote.com' for production or 'https://sandbox.evernote.com' for testing — do not include a path, as the specific API path varies by endpoint. Under Authentication, select 'Bearer Token' and enter your OAuth access token value, or add it as a custom header with key 'Authorization' and value 'Bearer YOUR_ACCESS_TOKEN' using '{{ retoolContext.configVars.EVERNOTE_TOKEN }}'. Before saving, go to Retool Settings → Configuration Variables and add 'EVERNOTE_TOKEN' with your OAuth access token, marking it as secret. The Evernote Cloud API uses the path '/edam/note/' as the base for NoteStore operations. Save the resource and verify the connection by creating a simple test query. Note that Evernote's EDAM API is Thrift-based, but many operations are accessible via HTTP POST requests with JSON bodies to the REST-compatible endpoints.

```
{
  "Base URL": "https://www.evernote.com",
  "Authentication": "Bearer Token",
  "Headers": {
    "Authorization": "Bearer {{ retoolContext.configVars.EVERNOTE_TOKEN }}",
    "Content-Type": "application/json"
  }
}
```

**Expected result:** The Evernote REST API Resource is saved in Retool with the OAuth token configured as a secret configuration variable.

### 3. Query notebooks to populate filter dropdowns

Create a new query using the Evernote resource to fetch all notebooks available to the authenticated user. Use the Evernote Cloud API's NoteStore endpoint. Set the method to GET and the path to '/edam/note/{noteStoreUrl}/NoteStore/listNotebooks' — you first need to retrieve the user's noteStoreUrl from the UserStore. Make an initial GET request to '/edam/user' to get the NoteStore URL for the authenticated account. The response contains a noteStoreUrl field like 'https://www.evernote.com/shard/s1/notestore'. Use this URL as the base for subsequent NoteStore requests. Once you have the NoteStore URL, configure your notebooks query as a GET to the listNotebooks endpoint. The response is an array of notebook objects each containing guid (the unique ID), name, defaultNotebook flag, updateSequenceNum, and serviceUpdated timestamp. Run this query with 'Run when page loads' enabled so the notebook list is available for dropdown filters from the moment the app loads.

```
// Step 1: GET /edam/user to retrieve noteStoreUrl
// This returns user info including the NoteStore URL

// Step 2: GET {noteStoreUrl}/NoteStore/listNotebooks
// Returns array of notebook objects

// Transformer: format notebooks for Select dropdown
const notebooks = data || [];
return notebooks.map(nb => ({
  label: nb.name,
  value: nb.guid,
  is_default: nb.defaultNotebook || false,
  note_count: nb.stack || 'No stack'
})).sort((a, b) => a.label.localeCompare(b.label));
```

**Expected result:** The notebooks query returns a list of all notebooks for the connected account. A Select dropdown component in your app is populated with notebook names for filtering note searches.

### 4. Implement note search with full-text and notebook filters

Create a query to search notes using Evernote's findNotesMetadata endpoint. This endpoint accepts a NoteFilter object in the request body that supports full-text search via the 'words' field, notebook filtering via 'notebookGuid', tag filtering via 'tagGuids', and date range filtering via 'created' and 'updated' fields (Unix timestamps). The endpoint also accepts 'offset' and 'maxNotes' parameters for pagination. Set the method to POST, the path to '{noteStoreUrl}/NoteStore/findNotesMetadata', and configure the JSON body with a filter object. The response contains a 'notes' array of note metadata objects (not full note content) including guid, title, created, updated, and notebookGuid. To get note content, you need a separate getNoteContent call per note — avoid calling this in a loop for large result sets as it significantly increases API call volume. Add a TextInput component bound to the search filter 'words' parameter, and a Select component bound to 'notebookGuid'. Configure the query to run on component change so search updates dynamically.

```
// POST {noteStoreUrl}/NoteStore/findNotesMetadata
// Body:
{
  "filter": {
    "words": "{{ searchInput.value || '' }}",
    "notebookGuid": "{{ notebookFilter.value || null }}",
    "order": 1,
    "ascending": false
  },
  "offset": {{ (pagination.page - 1) * 20 || 0 }},
  "maxNotes": 20,
  "resultSpec": {
    "includeTitle": true,
    "includeCreated": true,
    "includeUpdated": true,
    "includeNotebookGuid": true,
    "includeTagGuids": true
  }
}
```

**Expected result:** The note search returns up to 20 matching notes with title, creation date, and update date. Typing in the search input dynamically filters results, and selecting a notebook limits results to that notebook.

### 5. Build the note display panel and format results

Add a JavaScript transformer to the findNotesMetadata query to enrich the results with display-friendly formatting and notebook name lookup. The raw API response includes notebookGuid but not the notebook name — use the notebooks list from your earlier query to create a lookup map. Format dates from Unix timestamps (milliseconds) into readable strings using JavaScript's Date API. Add a Retool Table component bound to the transformer output with columns for title, notebook, last updated, and a hyperlink that opens the note in Evernote using the Evernote deep link format: 'evernote:///view/{userId}/{shardId}/{noteGuid}/{noteGuid}/'. Add a Text component below the Table to display note content when a user clicks a row — trigger a getNoteContent query (GET {noteStoreUrl}/NoteStore/getNoteContent?guid={selectedGuid}) bound to the Table's selectedRow.guid. The content returns as ENML (Evernote Markup Language), which is XML-based — strip tags with a simple regex or render safely in a Text component.

```
// Transformer: enrich note metadata with notebook names and formatted dates
const notes = data && data.notes ? data.notes : [];
const notebookMap = {};
(getNotebooks.data || []).forEach(nb => {
  notebookMap[nb.guid] = nb.name;
});

return notes.map(note => ({
  guid: note.guid,
  title: note.title || 'Untitled',
  notebook: notebookMap[note.notebookGuid] || 'Unknown Notebook',
  created: note.created
    ? new Date(note.created).toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' })
    : '',
  updated: note.updated
    ? new Date(note.updated).toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' })
    : '',
  days_since_update: note.updated
    ? Math.floor((Date.now() - note.updated) / 86400000)
    : null
}));
```

**Expected result:** The Table displays a formatted list of notes with notebook names and human-readable dates. Clicking a note row triggers the content query and shows a preview of the note text below the table.

## Best practices

- Store your Evernote OAuth access token in Retool configuration variables as a secret — the token grants full access to the connected Evernote account and should never be exposed in frontend code
- Cache the notebooks list query for at least 5 minutes — notebook structures change infrequently and caching reduces unnecessary API calls on every app load
- Avoid fetching full note content in bulk — the getNoteContent endpoint is rate-limited and retrieving content for dozens of notes in a loop will quickly exhaust your API quota; only fetch content for the note the user selects
- Store the NoteStore URL in a Retool state variable after the first /edam/user call rather than re-fetching it with every query — this URL is stable for an account and does not need to be re-fetched on each interaction
- Use the resultSpec object in findNotesMetadata to request only the fields you need — requesting tagGuids, contentLength, and other optional fields increases response size; omit what you do not display
- Build separate Retool apps for reading versus writing to Evernote — note creation and update operations are more complex and error-prone; keep the read-heavy search panel simple and reliable
- Apply date-range filters in note searches to prevent large result sets — Evernote's findNotesMetadata returns up to 250 notes per request, but performance degrades with large offsets for deep pagination

## Use cases

### Build an internal knowledge base search panel

Create a Retool search panel where support or ops team members can search Evernote notes by keyword and view results alongside customer data from your CRM. The panel lets users type a query, triggers an Evernote note search, and displays matching notes with title, notebook, and last-modified date. Clicking a note title opens it in Evernote via a deep link, keeping the read-heavy interface in Evernote while making discovery faster from within Retool.

Prompt example:

```
Build a Retool knowledge search panel with a text input for search query, a Table showing matching Evernote notes with columns for title, notebook, last updated date, and a link to open in Evernote. Include a notebook filter dropdown populated from the list of available notebooks.
```

### Create a notebook management and content audit dashboard

Query all notebooks and their note counts to give team administrators visibility into how knowledge is organized. Show which notebooks have the most notes, which have notes not updated in over six months, and which notebooks have no tags applied. This audit view helps teams identify outdated documentation and notebooks that need reorganization before content becomes unreliable.

Prompt example:

```
Create a Retool notebook audit dashboard showing all Evernote notebooks with note count, date of most recent note update, and a flag for notebooks containing notes not modified in the last 180 days. Allow admins to sort by note count or last activity.
```

### Build a note creation tool linked to operational workflows

Build a Retool form that creates structured Evernote notes automatically when specific operational events occur — for example, creating a post-mortem note when an incident is resolved, or generating a meeting notes template when a customer call is completed. The form pre-fills content based on data from other Retool Resources (like a support ticket or CRM record), reducing the manual effort of creating structured documentation.

Prompt example:

```
Build a Retool incident post-mortem tool with a form that takes incident title, date, description, root cause, and action items, then creates a formatted Evernote note in the 'Post-Mortems' notebook with all details pre-filled and tagged with the affected service name.
```

## Troubleshooting

### API returns 401 EDAMUserException: AUTH_EXPIRED or invalid token error

Cause: The OAuth access token is no longer valid — either it was revoked by the user, the application's API access was suspended, or you are using a sandbox token against the production API endpoint.

Solution: Verify the token in Evernote: log into evernote.com → Settings → Applications and check that your application is still authorized. If using a sandbox token, ensure the resource base URL is sandbox.evernote.com, not www.evernote.com. If the token has been revoked, complete the OAuth 1.0a flow again to obtain a new access token and update the Retool configuration variable.

### Queries return 'Wrong noteStoreUrl' or 404 not found on NoteStore endpoints

Cause: The NoteStore URL is user-specific and account-specific. Using a hardcoded NoteStore URL from one account on a different account, or using the wrong shard segment in the URL, causes this error.

Solution: Always fetch the NoteStore URL dynamically from the /edam/user endpoint for the authenticated account. The URL looks like 'https://www.evernote.com/shard/s1/notestore' where 's1' is the shard assignment for that account. Store this URL in a Retool state variable and reference it in all NoteStore queries via {{ noteStoreUrl.value }}.

### Note content returns as ENML XML with tags visible in the display

Cause: Evernote returns note content as ENML (Evernote Markup Language), which is a subset of XHTML. Displaying raw ENML in a Retool Text component shows the XML tags directly instead of rendered content.

Solution: Add a transformer to the getNoteContent query that strips XML tags before displaying the content. Use the regex replacement approach to extract plain text, or implement a more sophisticated parser if you need to preserve basic formatting. For rich content display, use a Custom Component with a sandboxed iframe that renders ENML properly.

```
// Strip ENML tags to get plain text preview
const rawContent = data || '';
return rawContent
  .replace(/<!DOCTYPE[^>]*>/g, '')
  .replace(/<[^>]+>/g, ' ')
  .replace(/&amp;/g, '&')
  .replace(/&lt;/g, '<')
  .replace(/&gt;/g, '>')
  .replace(/&nbsp;/g, ' ')
  .replace(/\s+/g, ' ')
  .trim();
```

### Search returns no results even when matching notes exist

Cause: Evernote's full-text search requires the search index to be current. Notes created very recently may not be indexed yet. Additionally, the 'words' filter uses Evernote's search syntax, which may behave differently than expected for multi-word queries.

Solution: For multi-word searches, Evernote treats words as an AND condition by default — all words must appear in the note. Use quotes for exact phrase matching: '"exact phrase"'. If search is returning no results for a query that should match, verify the notes are visible and searchable in Evernote's own web interface first. Also confirm the notebookGuid filter is null or empty if you want to search across all notebooks.

## Frequently asked questions

### Does Retool have a native Evernote connector?

No, Retool does not have a native Evernote connector. You connect using a REST API Resource with an Evernote OAuth 1.0a access token. The integration requires more setup than modern REST APIs due to Evernote's legacy OAuth 1.0a authentication, but once configured, the REST API Resource provides stable access to notebooks, notes, and search functionality.

### Why does Evernote use OAuth 1.0a instead of modern OAuth 2.0?

Evernote's API was designed in the early 2010s when OAuth 1.0a was the standard. The platform has not migrated to OAuth 2.0. For server-side Retool integrations where you control the Evernote account, this means completing the OAuth 1.0a token exchange once to get a long-lived access token, then storing that token in Retool's configuration variables. The token does not expire unless revoked.

### Can I create notes in Evernote from a Retool form?

Yes. Use POST to the NoteStore's createNote endpoint with a note object in the body. The note requires a title, content in ENML format (a subset of XHTML wrapped in the en-note tag), and optionally a notebookGuid. Build an Retool form with title and body fields, then format the content as valid ENML in a JavaScript query before POSTing to the API. The response includes the created note's guid.

### Is it possible to access shared notebooks or team notebooks in Evernote Business?

Yes, with Evernote Business accounts. The API provides a LinkedNotebook object for shared and business notebooks. Use the listLinkedNotebooks endpoint to retrieve shared notebooks, then authenticate with the shared notebook's shareKeyOrGlobalId to access its content. Business notebooks require a business account OAuth token obtained through the authenticateToBusiness endpoint, separate from the personal account token.

### Are there rate limits on the Evernote API?

Yes. Evernote enforces both per-minute and per-day rate limits based on your API key tier. Developer API keys start with lower limits during the review period. Once approved for production, limits increase significantly. If you hit the rate limit, Evernote returns an EDAMUserException with error code RATE_LIMIT_REACHED and a rateLimitDuration indicating how many seconds to wait before retrying.

---

Source: https://www.rapidevelopers.com/retool-integrations/evernote
© RapidDev — https://www.rapidevelopers.com/retool-integrations/evernote
