#
tokens: 48567/50000 70/85 files (page 1/3)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 1 of 3. Use http://codebase.md/nylas-samples/nylas-api-mcp?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTION.md
├── nylas-code-samples
│   ├── Auth
│   │   ├── AdminConsent-Bulk
│   │   │   └── index.md
│   │   ├── AppPermission-Bulk
│   │   │   └── index.md
│   │   ├── auth.md
│   │   ├── connected-accounts.md
│   │   ├── Connectors
│   │   │   ├── ews.md
│   │   │   ├── google.md
│   │   │   ├── icloud.md
│   │   │   ├── imap.md
│   │   │   ├── index.md
│   │   │   ├── ms.md
│   │   │   ├── virtual-cal.md
│   │   │   └── yahoo.md
│   │   ├── Hosted
│   │   │   └── index.md
│   │   ├── Native-Custom
│   │   │   ├── index.md
│   │   │   └── virtual-cals-custom.md
│   │   └── Providers
│   │       ├── google-imported.md
│   │       ├── google-pubsub.md
│   │       ├── google.md
│   │       ├── ms-imported.md
│   │       └── ms.md
│   ├── Calendar
│   │   ├── Availability
│   │   │   └── index.md
│   │   ├── calendar-apis.md
│   │   ├── Calendars
│   │   │   ├── index.md
│   │   │   ├── read.md
│   │   │   ├── webhooks.md
│   │   │   └── write.md
│   │   ├── Events
│   │   │   ├── index.md
│   │   │   ├── read.md
│   │   │   ├── webhooks.md
│   │   │   └── write.md
│   │   ├── google.md
│   │   ├── ms.md
│   │   ├── Recurring
│   │   │   └── index.md
│   │   └── Virtual-Calendars
│   │       └── index.md
│   ├── Coda
│   │   ├── index.md
│   │   ├── testing.md
│   │   └── webhooks.md
│   ├── Contacts
│   │   ├── index.md
│   │   ├── read.md
│   │   ├── webhooks.md
│   │   └── write.md
│   ├── Email
│   │   ├── Drafts
│   │   │   ├── index.md
│   │   │   ├── read.md
│   │   │   └── write.md
│   │   ├── Files-Attachments
│   │   │   ├── index.md
│   │   │   └── read.md
│   │   ├── Labels-Folders
│   │   │   ├── index.md
│   │   │   ├── read.md
│   │   │   ├── webhooks.md
│   │   │   └── write.md
│   │   ├── Messages
│   │   │   ├── index.md
│   │   │   ├── read.md
│   │   │   ├── webhooks.md
│   │   │   └── write.md
│   │   ├── Outbox
│   │   │   ├── index.md
│   │   │   ├── read.md
│   │   │   ├── webhooks.md
│   │   │   └── write.md
│   │   ├── Search
│   │   │   ├── index.md
│   │   │   └── read.md
│   │   ├── Threads
│   │   │   ├── index.md
│   │   │   ├── read.md
│   │   │   ├── webhooks.md
│   │   │   └── write.md
│   │   └── Tracking
│   │       ├── index.md
│   │       └── webhooks.md
│   ├── Start
│   │   ├── api-import.md
│   │   ├── Dashboard-Import
│   │   │   └── index.md
│   │   ├── index.md
│   │   └── manual.md
│   └── Webhooks
│       ├── index.md
│       └── new-pubsub-note.md
├── package-lock.json
├── package.json
├── README.md
├── src
│   ├── index.ts
│   ├── prompts
│   │   └── index.ts
│   ├── resources
│   │   ├── code-samples.ts
│   │   ├── docs.ts
│   │   ├── endpoints.ts
│   │   └── index.ts
│   └── tools
│       └── index.ts
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
 1 | # Dependencies
 2 | node_modules/
 3 | 
 4 | # Build output
 5 | dist/
 6 | 
 7 | # Environment variables
 8 | .env
 9 | .env.local
10 | .env.development.local
11 | .env.test.local
12 | .env.production.local
13 | 
14 | # Logs
15 | npm-debug.log*
16 | yarn-debug.log*
17 | yarn-error.log*
18 | 
19 | # IDE files
20 | .idea/
21 | .vscode/
22 | *.sublime-project
23 | *.sublime-workspace
24 | 
25 | # OS files
26 | .DS_Store
27 | Thumbs.db
28 | 
29 | # Project specific
30 | mcp-llms-full.txt
31 | mcp-typescript-sdk-readme.txt
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
  1 | # Nylas API MCP Server (Experimental)
  2 | 
  3 | > **Note**: This project is experimental and is intended as an exploration of using the Model Context Protocol (MCP) as a guide for Nylas API integrations. It is not official and should be used for learning and experimentation purposes only.
  4 | 
  5 | This project implements a Model Context Protocol (MCP) server for the Nylas API. It provides resources, tools, and prompts to help developers learn about and integrate with the Nylas API for email, calendar, and contacts functionality.
  6 | 
  7 | ## What is MCP?
  8 | 
  9 | The [Model Context Protocol (MCP)](https://modelcontextprotocol.io) is a standard for integrating data, tools, and prompts with AI applications. MCP servers can expose resources, tools, and prompts to AI applications like [Claude Desktop](https://claude.ai/download), [Cursor](https://cursor.sh), and other MCP-compatible applications.
 10 | 
 11 | ## Features
 12 | 
 13 | This MCP server provides:
 14 | 
 15 | - **Documentation Resources**: Comprehensive documentation about Nylas API endpoints, authentication, and best practices
 16 | - **Code Samples**: Ready-to-use code samples for various Nylas API operations in multiple languages (Node.js, Python, Java, Ruby, curl)
 17 | - **Interactive Tools**: Tools to generate authentication code and endpoint-specific implementation code
 18 | - **Prompts**: Pre-built prompts for common Nylas integration scenarios
 19 | 
 20 | ![Screenshot 2025-03-16 at 4 43 38 PM](https://github.com/user-attachments/assets/01436765-2eb8-4d8b-90ab-f0a8544355db)
 21 | 
 22 | ## Getting Started
 23 | 
 24 | ### Prerequisites
 25 | 
 26 | - Node.js 18+
 27 | - npm
 28 | 
 29 | ### Installation
 30 | 
 31 | 1. Clone this repository
 32 | 2. Install dependencies
 33 | 
 34 | ```bash
 35 | npm install
 36 | ```
 37 | 
 38 | 3. Build the project
 39 | 
 40 | ```bash
 41 | npm run build
 42 | ```
 43 | 
 44 | ### Running the MCP Server
 45 | 
 46 | #### Using stdio (for direct integration with MCP clients)
 47 | 
 48 | ```bash
 49 | npm start
 50 | ```
 51 | 
 52 | #### Using HTTP with SSE (for remote connections)
 53 | 
 54 | ```bash
 55 | MCP_MODE=http npm start
 56 | ```
 57 | 
 58 | By default, the HTTP server runs on port 3000. You can change this by setting the `PORT` environment variable:
 59 | 
 60 | ```bash
 61 | MCP_MODE=http PORT=8080 npm start
 62 | ```
 63 | 
 64 | ## Using with MCP Clients
 65 | 
 66 | ### Claude Desktop
 67 | 
 68 | 1. Start the MCP server in stdio mode
 69 | 2. In Claude Desktop, go to Settings > Servers
 70 | 3. Click "Add Server"
 71 | 4. Select "Run a local command" and enter the command to start this server:
 72 | 
 73 | ```bash
 74 | node /path/to/nylas-api-mcp/dist/index.js
 75 | ```
 76 | 
 77 | 5. Give it a name (e.g., "Nylas API")
 78 | 6. After adding, you can use all the Nylas API resources, tools, and prompts in your Claude conversations
 79 | 
 80 | ### Cursor
 81 | 
 82 | 1. Start the MCP server in stdio mode
 83 | 2. In Cursor, add a new MCP server in the settings
 84 | 3. Configure it to use the command:
 85 | 
 86 | ```bash
 87 | node /path/to/nylas-api-mcp/dist/index.js
 88 | ```
 89 | 
 90 | ## Resources
 91 | 
 92 | This MCP server provides the following resources:
 93 | 
 94 | - **General Documentation**: Overview of Nylas API capabilities
 95 | - **Authentication Guide**: How to authenticate with Nylas API
 96 | - **API Endpoints**: Documentation for email, calendar, contacts, and webhook endpoints
 97 | - **Code Samples**: Usage examples in multiple programming languages
 98 | 
 99 | ## Tools
100 | 
101 | Interactive tools for code generation:
102 | 
103 | - **generate-auth-code**: Generates authentication code in your preferred language
104 | - **generate-endpoint-code**: Generates code for specific API endpoints
105 | - **search-api-docs**: Search through the Nylas API documentation
106 | 
107 | ## Prompts
108 | 
109 | Pre-built prompts for common scenarios:
110 | 
111 | - **Getting Started**: Basic intro to Nylas API
112 | - **Authentication Guide**: Understanding OAuth flow
113 | - **Email/Calendar/Contacts Integration**: Feature-specific guidance
114 | - **Integration Scenarios**: Guidance for specific use cases (email client, calendar booking, etc.)
115 | - **SDK Examples**: Example code in various languages
116 | - **Debugging Guide**: Common issues and solutions
117 | 
118 | ## Contributing
119 | 
120 | Contributions are welcome! You can:
121 | 
122 | 1. Add more code samples to the `nylas-code-samples` directory
123 | 2. Improve documentation resources
124 | 3. Add support for additional programming languages
125 | 4. Create new tools and prompts
126 | 
127 | ## Disclaimer
128 | 
129 | This is an experimental project and is not officially supported by Nylas. The information and code provided through this MCP server should be used as a learning resource only. Always refer to the [official Nylas documentation](https://developer.nylas.com/) for the most accurate and up-to-date information on the Nylas API.
130 | 
131 | The sample code provided is for educational purposes and may need additional error handling, security considerations, and testing before being used in production environments.
132 | 
133 | ## License
134 | 
135 | MIT
136 | 
```

--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------

```markdown
 1 | 
 2 | # Nylas Open Source Code of Conduct
 3 | 
 4 | ## Our Pledge
 5 | 
 6 | We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
 7 | We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
 8 | 
 9 | ## Our Standards
10 | 
11 | ### Examples of behavior that contributes to a positive environment for our community include:
12 | 
13 | - Demonstrating empathy and kindness toward other people
14 | - Being respectful of differing opinions, viewpoints, and experiences
15 | - Giving and gracefully accepting constructive feedback
16 | - Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
17 | - Focusing on what is best not just for us as individuals, but for the overall community
18 | 
19 | ## Examples of unacceptable behavior include:
20 | 
21 | - The use of sexualized language or imagery, and sexual attention or advances of any kind
22 | - Trolling, insulting or derogatory comments, and personal or political attacks
23 | - Public or private harassment
24 | - Publishing others’ private information, such as a physical or email address, without their explicit permission
25 | - Other conduct which could reasonably be considered inappropriate in a professional setting
26 | 
27 | ## Enforcement Responsibilities
28 | 
29 | Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
30 | Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
31 | 
32 | ## Scope
33 | 
34 | This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
35 | 
36 | ## Enforcement
37 | 
38 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [email protected]. All complaints will be reviewed and investigated promptly and fairly.
39 | 
40 | All community leaders are obligated to respect the privacy and security of the reporter of any incident.
41 | 
42 | ## Enforcement Guidelines
43 | 
44 | Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
45 | 
46 | ### Correction
47 | **Community Impact:** Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
48 | 
49 | **Consequence:** A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
50 | 
51 | ### Warning
52 | 
53 | **Community Impact:** A violation through a single incident or series of actions.
54 | 
55 | **Consequence:** A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
56 | 
57 | ### Temporary Ban
58 | 
59 | **Community Impact:** A serious violation of community standards, including sustained inappropriate behavior.
60 | 
61 | **Consequence:** A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
62 | 
63 | ### Permanent Ban
64 | 
65 | **Community Impact:** Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
66 | 
67 | **Consequence:** A permanent ban from any sort of public interaction within the community.
68 | 
69 | ## Attribution
70 | 
71 | This Code of Conduct is adapted from the Contributor Covenant, version 2.0, available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
72 | 
73 | Community Impact Guidelines were inspired by Mozilla’s code of conduct enforcement ladder.
74 | 
75 | For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.
```

--------------------------------------------------------------------------------
/nylas-code-samples/Calendar/google.md:
--------------------------------------------------------------------------------

```markdown
1 | ### Changes to Google calendars
2 | 
3 | - Added the `hex_color` property for all Calendar calls.
```

--------------------------------------------------------------------------------
/nylas-code-samples/Email/Labels-Folders/webhooks.md:
--------------------------------------------------------------------------------

```markdown
1 | ## Changes to Folders webhooks
2 | 
3 | Nylas v3 supports the following folders webhook triggers:
4 | 
5 | - `folder.created`
6 | - `folder.updated`
7 | - `folder.deleted`
8 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Email/Tracking/webhooks.md:
--------------------------------------------------------------------------------

```markdown
1 | ## Changes to message tracking webhooks
2 | 
3 | Nylas v3 supports the following webhook triggers from v2:
4 | 
5 | - `message.opened`
6 | - `message.link_clicked`
7 | - `thread.replied`
8 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Calendar/ms.md:
--------------------------------------------------------------------------------

```markdown
1 | ### Changes to Microsoft Graph calendars
2 | 
3 | - Added the `hex_color` property for all Calendar calls.
4 | - Added access to shared calendars using the [Return Calendars endpoint](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/calendars).
```

--------------------------------------------------------------------------------
/nylas-code-samples/Email/Outbox/webhooks.md:
--------------------------------------------------------------------------------

```markdown
1 | ### Scheduled Send webhook notifications
2 | 
3 | Nylas v3 introduces the following Scheduled Send webhook triggers:
4 | 
5 | - `message.send_success`: A scheduled email message was sent successfully.
6 | - `message.send_failed`: A scheduled email message failed to send.
7 | - `message.bounce_detected`: (Gmail and Microsoft Graph only) A scheduled email message bounced.
8 | 
```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "compilerOptions": {
 3 |     "target": "ES2020",
 4 |     "module": "NodeNext",
 5 |     "moduleResolution": "NodeNext",
 6 |     "esModuleInterop": true,
 7 |     "outDir": "./dist",
 8 |     "strict": true,
 9 |     "skipLibCheck": true,
10 |     "forceConsistentCasingInFileNames": true,
11 |     "resolveJsonModule": true
12 |   },
13 |   "include": ["src"],
14 |   "exclude": ["node_modules", "dist"]
15 | }
```

--------------------------------------------------------------------------------
/nylas-code-samples/Auth/Connectors/icloud.md:
--------------------------------------------------------------------------------

```markdown
1 | To create an iCloud connector,  make a [`POST /v3/connectors` request](https://developer.nylas.com/docs/api/v3/admin/#post-/v3/connectors) and set the  `provider` to `icloud`.
2 | 
3 | When you start an authentication request for an iCloud account, use the `Bearer auth` request header with your Nylas application's API key, set `provider_type: "icloud"`, and include any states.
4 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Email/Threads/webhooks.md:
--------------------------------------------------------------------------------

```markdown
1 | ## Threads webhook notifications
2 | 
3 | Nylas v3 doesn't include Threads webhook triggers. Instead, you receive Messages notifications for updates to threads.
4 | 
5 | You can subscribe to the `thread.replied` trigger if you [enable message tracking](https://developer.nylas.com/docs/v3/email/message-tracking/). This allows you to get notifications when a participant replies to an email message in a thread.
6 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Contacts/webhooks.md:
--------------------------------------------------------------------------------

```markdown
 1 | ### Update contacts webhooks
 2 | 
 3 | Nylas v3 supports the following contacts webhook triggers:
 4 | 
 5 | - `contact.updated`
 6 | - `contact.deleted`
 7 | 
 8 | The `contact.created` webhook trigger is deprecated in v3 to maintain provider consistency. Instead, Nylas sends a `contact.updated` notification when an end user creates a contact. Be sure to update your subscriptions.
 9 | 
10 | Nylas does not use the `.truncated` notification suffix for contacts.
11 | 
```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "name": "nylas-api-mcp",
 3 |   "version": "1.0.0",
 4 |   "description": "MCP server for Nylas API Developer Docs",
 5 |   "main": "dist/index.js",
 6 |   "type": "module",
 7 |   "scripts": {
 8 |     "build": "tsc",
 9 |     "start": "node dist/index.js",
10 |     "dev": "tsc && node dist/index.js"
11 |   },
12 |   "dependencies": {
13 |     "@modelcontextprotocol/sdk": "^1.2.1",
14 |     "express": "^4.18.3",
15 |     "zod": "^3.22.4"
16 |   },
17 |   "devDependencies": {
18 |     "@types/express": "^4.17.21",
19 |     "@types/node": "^20.11.24",
20 |     "typescript": "^5.3.3"
21 |   }
22 | }
```

--------------------------------------------------------------------------------
/nylas-code-samples/Coda/testing.md:
--------------------------------------------------------------------------------

```markdown
1 | ## Test your auth settings
2 | 
3 | When you have your provider auth apps and connectors working, you can test them out by creating a grant for each type of auth flow. You can then use these grants to test your upgraded Nylas Email, Calendar, and Contacts API integrations.
4 | 
5 | As you test, you might find that you need to modify your v3 scopes. If you do, remember to change them on both your provider auth apps and in any defaults you set on the associated connectors (and connector credentials, if you're using them).
6 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Auth/Connectors/virtual-cal.md:
--------------------------------------------------------------------------------

```markdown
1 | You need to create a Virtual Calendar connector before you can create or work with Nylas virtual calendars. Each Nylas application that uses Virtual Calendars needs its own Virtual Calendar connector.
2 | 
3 | To create a Virtual Calendar connector, make a [`POST /v3/connectors` request](https://developer.nylas.com/docs/api/v3/admin/#post-/v3/connectors) and set `provider` to `virtual-calendar`.
4 | 
5 | You can also do this from the v3 Dashboard by clicking **Connectors** and then the **+** button next to Virtual Calendars.
6 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Auth/Connectors/google.md:
--------------------------------------------------------------------------------

```markdown
1 | To create a Google connector, make a [`POST /v3/connectors` request](https://developer.nylas.com/docs/api/v3/admin/#post-/v3/connectors) that includes your Google Cloud Platform (GCP) `client_id` and `client_secret`, and a default set of scopes for your project. You can also [configure the default scopes](https://developer.nylas.com/docs/v3/auth/#create-a-connector) for end users who authenticate through the Google connector.
2 | 
3 | Make sure the scopes on the connector exactly match or are a literal subset of the scopes on your GCP app.
4 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Auth/Providers/google-pubsub.md:
--------------------------------------------------------------------------------

```markdown
1 | ### Set up Google Pub/Sub
2 | 
3 | If your project monitors for email message-related webhook notifications from Google services, you must [set up a Pub/Sub topic in your GCP app](https://developer.nylas.com/docs/dev-guide/provider-guides/google/connect-google-pub-sub/) so Google can notify you about changes to email messages in real-time. This is _required_.
4 | 
5 | For complete and detailed information, see [Create a Google authentication application for Nylas v3](https://developer.nylas.com/docs/dev-guide/provider-guides/google/create-google-app/).
6 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Auth/Connectors/yahoo.md:
--------------------------------------------------------------------------------

```markdown
1 | ### (Maybe don't) create a Yahoo connector (right now)
2 | 
3 | A new Yahoo OAuth method is available that _greatly_ improves Yahoo performance and reliability. However, this new method requires that you create a new Yahoo OAuth application - and this might take a week or more.
4 | 
5 | For now, we recommend you use the IMAP connector to authenticate users, but put this on your To Do list post-upgrade.
6 | 
7 | When you've got your Yahoo OAuth app approved, you can make a [`POST /v3/connectors` request](https://developer.nylas.com/docs/api/v3/admin/#post-/v3/connectors) and set the `provider` to `yahoo`.
8 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Email/Tracking/index.md:
--------------------------------------------------------------------------------

```markdown
 1 | ## Changes to message tracking
 2 | 
 3 | In v3, the following message tracking response fields have been updated:
 4 | 
 5 | | **v2**             | **v3**              | **Location**                       |
 6 | | ------------------ | ------------------- | ---------------------------------- |
 7 | | `tracking`         | `tracking_options`  | Request                            |
 8 | | `tracking.payload` | `tracking.label`    | Request and notification           |
 9 | | `recents.id`       | `recents.click_id`  | Link Clicked tracking notification |
10 | | `recents.id`       | `recents.opened_id` | Message Open tracking notification |
11 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Auth/Native-Custom/virtual-cals-custom.md:
--------------------------------------------------------------------------------

```markdown
1 | For _most_ projects migrating from v2.x to v3, the first step is to upgrade authentication. However, since Virtual Calendars use [Custom Authentication](/docs/api/v3/admin/#post-/v3/connect/custom) (previously called "Native Authentication"), you get to skip worrying about scopes and provider auth apps, and just update how you authorize your API calls to the v3 method, and update the Custom auth API calls themselves.
2 | 
3 | In fact, you don't actually need to upgrade to use Custom Authentication until you want to make new virtual accounts. We'll show the instructions for you so you have them for when you get to that point.
4 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Calendar/Calendars/webhooks.md:
--------------------------------------------------------------------------------

```markdown
 1 | ## Calendar webhook triggers
 2 | 
 3 | The webhook triggers for calendar notifications have not changed, however Nylas has changed the webhook notification format and some behavior.
 4 | 
 5 | Nylas now sends webhook notifications enriched with information about the object that changed, and does not send historical webhooks. See the [Webhooks changes in v3](https://developer.nylas.com/docs/new/in-v3/webhooks-changes/) for more information about the changes, and the [Calendar webhook schemas](https://developer.nylas.com/docs/v3/notifications/notification-schemas/#calendar-notifications) for more information.
 6 | 
 7 | Nylas v3 supports the following calendar webhook triggers:
 8 | 
 9 | - `calendar.created`
10 | - `calendar.updated`
11 | - `calendar.deleted`
12 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Auth/Connectors/ms.md:
--------------------------------------------------------------------------------

```markdown
1 | To create a Microsoft connector, make a [`POST /v3/connectors` request](https://developer.nylas.com/docs/api/v3/admin/#post-/v3/connectors) that includes your Azure `client_id` and `client_secret`, and a default set of scopes for your project.
2 | 
3 | When you start an authentication request with Microsoft, you use the `Bearer auth` request header with your Nylas application's API key, set `provider_type: "microsoft"`, and include any non-default scopes and states for the end user.
4 | 
5 | :::warn
6 | ⚠️ **Before you create a Microsoft connector, make sure you've migrated your project's old scopes to the new Microsoft Graph scopes and entered them in your Azure application's Entra ID**. Because the upgrade to Nylas v3 includes this scope update, all Microsoft users must re-authenticate to accept the new v3 scopes.
7 | :::
8 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Calendar/Recurring/index.md:
--------------------------------------------------------------------------------

```markdown
1 | ## Changes to recurring events
2 | 
3 | Recurring events now use an array of `RRULE` and `EXDATE` strings. Recurring Events no longer accept a recurrence timezone, and instead use the timezone specified in your `when` object to calculate the time for event instances. The `when` object is a `time:` in epoch time, and a `timezone:` in [IANA format](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). See the [Recurring events](https://developer.nylas.com//docs/v3/calendar/schedule-recurring-events/) for more details.
4 | 
5 | ### Architecture changes
6 | 
7 | Nylas v3 no longer syncs data from providers, but instead queries them directly. This means that  Nylas now relies on the provider as the source of truth, however some providers may require tuning to best handle their differing behavior. This is especially true for recurring events.
8 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Auth/Connectors/ews.md:
--------------------------------------------------------------------------------

```markdown
1 | The Nylas Microsoft connector (`provider: microsoft`) allows end users to authenticate with several different Microsoft services so they can connect to your project. However, Microsoft no longer supports Exchange servers, and end users cannot auth with them using Nylas v3.
2 | 
3 | To authenticate end users who use Exchange on-premises services for email _and_ calendar, you must [create a separate EWS connector](https://developer.nylas.com/docs/dev-guide/provider-guides/exchange-web-services/).
4 | 
5 | If you use Exchange on-premises services for email _only_ and your project doesn't need to use the Nylas Calendar APIs, you can authenticate using an IMAP connector instead.
6 | 
7 | Nylas no longer supports Exchange on-premises _service_ accounts. Personal accounts on Hotmail, Live, and Outlook must start a new authentication using the Microsoft connector instead of Exchange.
8 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Webhooks/new-pubsub-note.md:
--------------------------------------------------------------------------------

```markdown
1 | If you get lots of Message or Event webhook notifications, you might want to [consider setting up PubSub channel](https://developer.nylas.com/docs/v3/notifications/pubsub-channel/) for these notifications _instead_ of using webhooks. PubSub channels are new in v3, and are ideal for projects where webhook volume, latency, or deliverability are concerns, or where your project requires deliverability guarantees.
2 | 
3 | A PubSub channel is separate from the PubSub topic you set up to get notifications about Google messages. The PubSub _topic_ improves Google's latency sending notifications _to_ your Nylas app, while the PubSub _channel_ allows you to _consume_ notifications.
4 | 
5 | :::info
6 | 🔍 **Good to know**: Although you set up the PubSub notification channel on Google Cloud, it can receive notifications about events on any of the providers Nylas supports - not just Google.
7 | :::
8 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Auth/Connectors/imap.md:
--------------------------------------------------------------------------------

```markdown
1 | To create an IMAP connector,  make a [`POST /v3/connectors` request](https://developer.nylas.com/docs/api/v3/admin/#post-/v3/connectors) and set the `provider` to `imap`.
2 | 
3 | The IMAP connector doesn't take a client ID or secret, or use any scopes. Instead, you pass individual server connection information with each authentication request. You can use the [Detect provider endpoint](https://developer.nylas.com/docs/api/v3/admin/#post-/v3/providers/detect) to help you pre-fill that information for [supported common IMAP providers](https://developer.nylas.com/docs/dev-guide/provider-guides/supported-providers/#supported-imap-providers).
4 | 
5 | When you start an auth request for an IMAP account, use the `Bearer auth` request header with your Nylas application's API key, along with the end user's IMAP username, password, and IMAP host and port.
6 | 
7 | In Nylas v3, IMAP providers can only sync data within a rolling 90 day window.
8 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Calendar/Events/webhooks.md:
--------------------------------------------------------------------------------

```markdown
 1 | ## Event webhook triggers
 2 | 
 3 | The webhook triggers for calendar and events notifications have not changed, however Nylas has changed the webhook notification format and some behavior.
 4 | 
 5 | Nylas now sends webhook notifications enriched with information about the object that changed, and does not send historical webhooks. See the [Webhooks changes in v3](https://developer.nylas.com/docs/new/in-v3/webhooks-changes/) for more information about the changes, and the [Event webhook schemas](https://developer.nylas.com/docs/v3/notifications/notification-schemas/#event-notifications) for more information.
 6 | 
 7 | Nylas v3 supports the following event webhook triggers:
 8 | 
 9 | - `event.created`
10 | - `event.updated`
11 | - `event.deleted`
12 | 
13 | ## Truncated event webhooks
14 | 
15 | The `.truncated` suffix is new in v3. Watch for it, because it indicates a data payload that exceeds a base limit of 1MB. You will want to re-query for additional data in that case only.
16 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Email/Files-Attachments/index.md:
--------------------------------------------------------------------------------

```markdown
1 | **In v3, "Files" are now called "Attachments"**. Be sure to find all instances of the v2 `/files` endpoints in your code and change them to the appropriate v3 endpoints.
2 | 
3 | In Nylas v3, you use the Messages or Drafts APIs to add or remove attachments from a message payload, and use the Attachments APIs to download or get information about the attachments. [Learn more about working with attachments in v3](/docs/v3/email/attachments/).
4 | 
5 | ### Migrated Attachments endpoints
6 | 
7 | - Return attachment metadata: `GET /files/<FILE_ID>` → [`GET /v3/grants/<NYLAS_GRANT_ID>/attachments/<ATTACHMENT_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/attachments/-attachment_id-)
8 | - Download an attachment: `GET /files/<FILE_ID>/download` → [`GET /v3/grants/<NYLAS_GRANT_ID>/attachments/<ATTACHMENT_ID>/download`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/attachments/-attachment_id-/download)
9 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Auth/auth.md:
--------------------------------------------------------------------------------

```markdown
 1 | The first step for every project migrating from Nylas v2.x to v3 is to assess and upgrade your authentication systems. When you have your auth systems working in v3, you can then test and upgrade your other code and systems.
 2 | 
 3 | ### Check for compatibility
 4 | 
 5 | Before you upgrade your authentication systems, check if you're using any of the methods that are no longer supported in Nylas v3:
 6 | 
 7 | - **No support for unsecured HTTP**: Nylas no longer supports unsecured connections over HTTP (port 80). You must now use HTTPS (port 443).
 8 | - **No support for Basic auth**: Nylas no longer supports Basic authentication, and instead uses Bearer auth with either an access token or API key. If you haven't already updated your code to use Bearer auth, you must do that before you can use v3.
 9 | - **No support for server-side hosted auth**: Nylas v3 no longer supports server-side hosted authentication. You must use the new Hosted OAuth method.
10 | 
11 | If you're using any of these methods, you must update them or migrate to a more modern version before you proceed.
12 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Email/Search/index.md:
--------------------------------------------------------------------------------

```markdown
 1 | ## Changes to Search
 2 | 
 3 | - The `/messages/search` and `/threads/search` endpoints are deprecated. Instead, you can now include a URL-encoded provider query string in a [`GET /v3/grants/<NYLAS_GRANT_ID>/messages` request](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/messages) or a [`GET /v3/grants/<NYLAS_GRANT_ID>/threads` request](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/threads).
 4 | - You can search for email messages and threads on IMAP providers using all [standard SEARCH operators](https://datatracker.ietf.org/doc/html/rfc3501#section-6.4.4).
 5 | - You can include the `search_query_native` query parameter to add provider-specific search query strings to your criteria.
 6 | - Metadata is not supported.
 7 | 
 8 | ### Migrated Search endpoints
 9 | 
10 | - Search messages: `/messages/search` → [`GET /v3/grants/<NYLAS_GRANT_ID>/messages` request](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/messages)
11 | - Search threads: `/threads/search` → [`GET /v3/grants/<NYLAS_GRANT_ID>/threads` request](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/threads)
12 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Calendar/Availability/index.md:
--------------------------------------------------------------------------------

```markdown
 1 | 
 2 | ### Changes to Calendar availability
 3 | 
 4 | - Round-robin now uses the value of the Nylas `key5` metadata to indicate Events to consider when calculating the next available time among group members. Set `key5` to a specific string to mark events to consider when calculating a round robin order.
 5 | - Some fields have been renamed for clarity. See [Check calendar availability](https://developer.nylas.com/docs/v3/calendar/calendar-availability/), and the [v3 Availability reference](https://developer.nylas.com/docs/api/v3/ecc/#post-/v3/calendars/availability) for more details.
 6 | - [`POST /v3/calendars/availability` requests](https://developer.nylas.com/docs/api/v3/ecc/#post-/v3/calendars/availability) do not require a grant ID or calendar ID because you can specify multiple participants to check for availability.
 7 | - You can no longer use a `free_busy` object to override or add busy data to an Availability request.
 8 | - `time_slots` and `tentative_busy` parameters are removed for all Availability calls.
 9 | 
10 | #### Deprecated Availability endpoints
11 | 
12 | - Get availability for multiple consecutive meetings: `POST /calendars/availability/consecutive`
13 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Start/manual.md:
--------------------------------------------------------------------------------

```markdown
 1 | Nylas applications are the containers for your project's authentication configuration and general settings, and your end users' grants. Depending on how your project is organized, you might use separate Nylas applications to provide your end users with different experiences.
 2 | 
 3 | Nylas doesn't provide an API endpoint to create applications; you must create them using the v3 Nylas Dashboard. After they're created you can modify and interact with them using the [Administration APIs](https://developer.nylas.com/docs/api/v3/admin/#tag--Applications).
 4 | 
 5 | :::warn
 6 | ⚠️ **Keep in mind**: You can create and manage legacy v2 Nylas applications from the v3 Dashboard, but you can't create or manage v3 applications from the v2 Dashboard.
 7 | :::
 8 | 
 9 | 1. Log in to the v3 Dashboard.
10 | 2. Click **Create new app**.
11 | 3. Add a name for the application, and choose the data residency location.
12 | 4. Optionally, add a description and an environment label.
13 | 5. Click **Create app**.
14 | 
15 | Repeat this for each app you want to re-create.
16 | 
17 | At minimum, you should create a Nylas application for testing, and a separate production application.
18 | 
19 | This guide covers the rest of the upgrade process in the sections below.
20 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Email/Outbox/index.md:
--------------------------------------------------------------------------------

```markdown
 1 | ## Changes to Outbox
 2 | 
 3 | The v3 Email API consolidates several v2 endpoints, and specifically replaces the v2.x `/outbox` endpoints with the `/v3/messages` endpoints.
 4 | 
 5 | To switch from using v2 Instant Send to v3 [Scheduled Send](https://developer.nylas.com/docs/v3/email/scheduled-send/), make a [`POST /v3/grants/<NYLAS_GRANT_ID>/messages/send` request](https://developer.nylas.com/docs/api/v3/ecc/#post-/v3/grants/-grant_id-/messages/send) that includes the time when you want Nylas to send the email message.
 6 | 
 7 | ### New Scheduled Send endpoints
 8 | 
 9 | - Return a specific scheduled email message: [`GET /v3/grants/<NYLAS_GRANT_ID>/messages/schedules/<SCHEDULE_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/messages/schedules/-scheduleId-)
10 | 
11 | ### Migrated Outbox endpoints
12 | 
13 | - Return all scheduled email messages: `GET /outbox` → [`GET /v3/grants/<NYLAS_GRANTID>/messages/schedules`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/messages/schedules)
14 | - Cancel scheduled send instructions: `DELETE /outbox/<SCHEDULE_ID>` → [`DELETE /v3/grants/<NYLAS_GRANT_ID>/messages/schedules/<SCHEDULE_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#delete-/v3/grants/-grant_id-/messages/schedules/-scheduleId-)
15 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Email/Messages/webhooks.md:
--------------------------------------------------------------------------------

```markdown
 1 | ### Changes to Messages webhooks
 2 | 
 3 | Nylas v3 supports the following webhook triggers from v2:
 4 | 
 5 | - `message.created`
 6 | - `message.updated`
 7 | 
 8 | #### Truncated webhook notifications
 9 | 
10 | If the object returned in a `message.created` or `message.updated` notification is larger than 1MB, Nylas v3 omits the large fields and adds the `.truncated` suffix to the notification (for example, `message.created.truncated`). When you get a `.truncated` notification, you might want to re-query if the omitted data is important to your project's workflow.
11 | 
12 | Nylas might send you `.truncated` notifications if you subscribe to `message.created` or `message.updated` triggers, so make sure your webhook processor can handle them. You can't subscribe to `.truncated` triggers separately, and they aren't a subscription option in the v3 Dashboard webhooks page.
13 | 
14 | ### Provider limitations
15 | 
16 | iCloud, Yahoo, and IMAP providers can retrieve data for email messages that's up to 90 days old. For most providers, email message notifications are sent in real-time, but Yahoo and AOL accounts might take up to 5 minutes to deliver those notifications. Nylas does not send webhook notifications for changes to email messages (for example, folder changes) if the email message being updated is older than 90 days.
17 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Calendar/calendar-apis.md:
--------------------------------------------------------------------------------

```markdown
 1 | The Calendar and Events endpoints are available for Google, Microsoft Graph, iCloud, Exchange on-prem, and Virtual Calendars.
 2 | 
 3 | Nylas v3 includes the same basic ability to create, read, update, and delete both Events and Calendars (which contain Events). It also includes the following changes:
 4 | 
 5 | - You now need a `calendar_id` for almost all calls to Events endpoints. You can specify it in one of the following ways:
 6 |   - Using the `primary` parameter to specify the primary calendar for the grant.
 7 |   - Look up and use the ID of the calendar that you want to work with.
 8 | - You can now specify open hours by adding the `default_open_hours` parameter to the `availability_rules` object.
 9 |   - You can override the default settings by specifying a different availability for each participant.
10 | - Round-robin availability now uses the Nylas `key5` metadata to indicate events that Nylas should consider when calculating the next available time amongst a group of participants.
11 | - The format for event start and end times has been simplified.
12 | - The format for recurring events has been simplified.
13 |   - Recurring events no longer accept a recurrence time zone, and instead use the time zone specified in the `when` object to calculate the time for each event instance.
14 | - You can now list all calendars and events for a specific grant.
15 |   
```

--------------------------------------------------------------------------------
/nylas-code-samples/Auth/Connectors/index.md:
--------------------------------------------------------------------------------

```markdown
 1 | **In v3, "integrations" are now called "connectors**. These objects store information about auth providers for each Nylas application. All authentication types, including Custom auth (previously called "Native auth"), require connectors for each provider.
 2 | 
 3 | Each Nylas application can have only one connector per provider. If you're in a multi-tenant environment, you can use connector credentials with Google and Microsoft connectors to override connection information.
 4 | 
 5 | ### New connector endpoints
 6 | 
 7 | - Return all connectors: [`GET /v3/connectors`](https://developer.nylas.com/docs/api/v3/admin/#get-/v3/connectors)
 8 | - Return a specific connector: [`GET /v3/connectors/<PROVIDER>`](https://developer.nylas.com/docs/api/v3/admin/#get-/v3/connectors/-provider-)
 9 | - Create a connector: [`POST /v3/connectors`](https://developer.nylas.com/docs/api/v3/admin/#post-/v3/connectors)
10 | - Update a connector: [`PATCH /v3/connectors/<provider>`](https://developer.nylas.com/docs/api/v3/admin/#patch-/v3/connectors/-provider-)
11 | - Delete a connector: [`DELETE /v3/connectors/<provider>`](https://developer.nylas.com/docs/api/v3/admin/#delete-/v3/connectors/-provider-)
12 | 
13 | ### Migrated integrations endpoints
14 | 
15 | - Detect provider: `POST /connect/detect-provider` → [`POST /v3/providers/detect`](https://developer.nylas.com/docs/api/v3/admin/#post-/v3/providers/detect)
16 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Auth/Providers/google-imported.md:
--------------------------------------------------------------------------------

```markdown
 1 | If you used the Dashboard Migration button, or the [Import application settings endpoint](https://developer.nylas.com/docs/api/v3/migration/#post-/v3/migration-tools/import-v2-app), Nylas created a connector for Google, but left the Scopes blank for you to fill in. Use the Google scopes you calculated in the previous steps.
 2 | 
 3 | To complete the import process, you can make an [Update connector request](https://developer.nylas.com/docs/api/v3/admin/#patch-/v3/connectors/-provider-) to update the scopes.
 4 | 
 5 | ```API
 6 | curl --location --request PATCH 'http://api.us.nylas.com/v3/connectors/google' \
 7 |   --header 'Authorization: Bearer <NYLAS_API_KEY>' \
 8 |   --header 'Content-Type: application/json' \
 9 |   --data '{
10 |     "scope": 
11 |         [
12 |         "https://www.googleapis.com/auth/userinfo.email",
13 |         "https://www.googleapis.com/auth/userinfo.profile"
14 |         ]
15 |   }'
16 | ```
17 | 
18 | If you prefer, you can also update the Microsoft connector from the Dashboard:
19 | 
20 | 1. Navigate to the v3 Dashboard, click **Connectors**, click **...** (the "more" menu) next to the Microsoft connector and select **Edit**.
21 | 2. On the page that appears, double-check that the Client ID and Client secret for the Google connector are correct, and update them if needed.
22 | 3. Next, scroll down to **Authentication scopes** section, and select the scopes your app needs.
23 | 4. Click **Save**.
24 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Email/Labels-Folders/index.md:
--------------------------------------------------------------------------------

```markdown
 1 | **In v3, Folders and Labels are consolidated as Folders**. Be sure to find all instances of the v2 `/labels` endpoints and `labels` objects in your code and update them to `folders`.
 2 | 
 3 | Nylas v3 also includes the following changes to folders and labels:
 4 | 
 5 | - Folders and Labels have been consolidated.
 6 |   - `folder` → `folders` for all Messages and Threads requests.
 7 |   - `labels` → `folders` for all Messages and Threads requests.
 8 | - The `folder` object in all Messages and Threads now contains a list of `folder_id`s instead of an array of Folders.
 9 | 
10 | ### Migrated Folders endpoints
11 | 
12 | - Return all folders/labels: `GET /folders`, `GET /labels` → [`GET /v3/grants/<NYLAS_GRANT_ID>/folders`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/folders)
13 | - Create a folder/label: `POST /folders`, `POST /labels` → [`POST /v3/grants/<NYLAS_GRANT_ID>/folders`](https://developer.nylas.com/docs/api/v3/ecc/#post-/v3/grants/-grant_id-/folders)
14 | - Return a folder/label: `GET /folders/<FOLDER_ID>`, `GET /labels/<LABEL_ID>` → [`GET /v3/grants/<NYLAS_GRANT_ID>/folders/<FOLDER_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/folders/-folder_id-)
15 | - Update a folder/label: `PUT /folders/<FOLDER_ID>`, `PUT /labels/<LABEL_ID>` → [`PUT /v3/grants/<NYLAS_GRANT_ID>/folders/<FOLDER_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#put-/v3/grants/-grant_id-/folders/-folder_id-)
16 | - Delete a folder/label: `DELETE /folders/<FOLDER_ID>`, `DELETE /labels/<LABEL_ID>` → [`DELETE /v3/grants/<NYLAS_GRANT_ID>/folders/<FOLDER_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#delete-/v3/grants/-grant_id-/folders/-folder_id-)
17 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Auth/Providers/google.md:
--------------------------------------------------------------------------------

```markdown
 1 | Nylas v3 includes the following changes to how Google Cloud Platform (GCP) auth apps are handled:
 2 | 
 3 | - The **Authorized redirect URIs** for Hosted Auth have been updated in v3.
 4 |   - **U.S.**: `https://api.us.nylas.com/v3/connect/callback`
 5 |   - **E.U.**: `https://api.eu.nylas.com/v3/connect/callback`
 6 | - Nylas v3 no longer uses "Nylas scopes", and uses Google's scopes instead.
 7 | 
 8 | ### Update authorized redirect URIs in GCP app
 9 | 
10 | For all GCP auth apps that you want to connect to Nylas v3, the authorized redirect URIs for Hosted Auth have been updated. Add one, or both, of the following to the **Authorized redirect URIs** section of your GCP app:
11 | 
12 | - **U.S.**: `https://api.us.nylas.com/v3/connect/callback`
13 | - **E.U.**: `https://api.eu.nylas.com/v3/connect/callback`
14 | 
15 | ### Calculate v3 scopes for GCP app
16 | 
17 | In v3, Nylas no longer uses "Nylas scopes", but directly uses Google's scopes instead. Make a list of the v2 API endpoints your project uses, then read the [v3 scopes documentation](https://developer.nylas.com/docs/v3/auth/v3-scopes/) to determine the scopes you need for v3.
18 | 
19 | When you know what v3 scopes you need, add them to your GCP app.
20 | 
21 | ### Do I need to re-verify my GCP app?
22 | 
23 | _In general_, you shouldn't need to re-verify your GCP app unless you're adding new features to your project. However, two items might require changes if your app doesn't already include their scopes:
24 | 
25 | - **If you use `thread.replied` webhook notifications**, these now use the `email.read` scope in v3, instead of the v2 `email.metadata` scopes.
26 | - **If you use the Contacts APIs and want to use domain-level or inbox contacts**, you might need to add some scopes. If you use address book contacts only, you don't need to make any changes.
27 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Auth/Providers/ms-imported.md:
--------------------------------------------------------------------------------

```markdown
 1 | If you used the Dashboard Migration button, or the [Import application settings endpoint](https://developer.nylas.com/docs/api/v3/migration/#post-/v3/migration-tools/import-v2-app), Nylas created a Microsoft connector in your v3 application, but didn't configure it because of the required Microsoft Graph changes. You can't connect Microsoft users in v3 until you update your application.
 2 | 
 3 | To complete the import process, you can make an [Update connector request](https://developer.nylas.com/docs/api/v3/admin/#patch-/v3/connectors/-provider-) to update the `client_id` and `client_secret` to those used by the Azure auth app you configured with Graph scopes.
 4 | 
 5 | ```API
 6 | curl --location --request PATCH 'http://api.us.nylas.com/v3/connectors/microsoft' \
 7 |   --header 'Authorization: Bearer <NYLAS_API_KEY>' \
 8 |   --header 'Content-Type: application/json' \
 9 |   --data '{
10 |     "settings":
11 |     {
12 |       "client_id": "<AZURE_CLIENT_ID>",
13 |       "client_secret": "<AZURE_CLIENT_SECRET",
14 |       "tenant": "<AZURE_TENANT>" // Optional. Can be tenant ID or common.
15 |     },
16 |     "scope": 
17 |     [
18 |     "Mail.Read",
19 |     "User.Read",
20 |     "offline_access"
21 |     ]
22 |   }'
23 | ```
24 | 
25 | You can also [configure default scopes for users connecting through Microsoft](https://developer.nylas.com/docs/v3/auth/#create-a-connector).
26 | 
27 | If you prefer, you can also update the Microsoft connector from the Dashboard:
28 | 
29 | 1. Navigate to the v3 Dashboard, click **Connectors**, click **...** (the "more" menu) next to the Microsoft connector and select **Edit**.
30 | 2. On the page that appears, update the Client ID and Client secret for the Microsoft connector.
31 | 3. Next, scroll down to **Authentication scopes** section, and select the scopes your app needs.
32 | 4. Click **Save**.
33 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Calendar/Calendars/index.md:
--------------------------------------------------------------------------------

```markdown
 1 | ## Changes to Calendars
 2 | 
 3 | Nylas v3 includes the following changes to the Calendars API:
 4 | 
 5 | - All Calendar call responses now include the `is_owned_by_user` property.
 6 | 
 7 | ### Migrated Calendars endpoints
 8 | 
 9 | - Return all calendars: `GET /calendars` → [`GET /v3/grants/<NYLAS_GRANT_ID>/calendars`](https://developer.nylas.com//docs/api/v3/ecc/#get-/v3/grants/-grant_id-/calendars)
10 | - Create a calendar: `POST /calendars` → [`POST /v3/grants/<NYLAS_GRANT_ID>/calendars`](https://developer.nylas.com//docs/api/v3/ecc/#post-/v3/grants/-grant_id-/calendars)
11 | - Return a calendar: `GET /calendars/<CALENDAR_ID>` → [`GET /v3/grants/<NYLAS_GRANT_ID>/calendars/<CALENDAR_ID>`](https://developer.nylas.com//docs/api/v3/ecc/#get-/v3/grants/-grant_id-/calendars/-calendar_id-)
12 | - Update a calendar: `PUT /calendars/<CALENDAR_ID>` → [`PUT /v3/grants/<NYLAS_GRANT_ID>/calendars/<CALENDAR_ID>`](https://developer.nylas.com//docs/api/v3/ecc/#put-/v3/grants/-grant_id-/calendars/-calendar_id-)
13 | - Delete a calendar: `DELETE /calendars/<CALENDAR_ID>` → [`DELETE /v3/grants/<NYLAS_GRANT_ID>/calendars/<CALENDAR_ID>`](https://developer.nylas.com//docs/api/v3/ecc/#delete-/v3/grants/-grant_id-/calendars/-calendar_id-)
14 | - Check a calendar for availability: `POST /calendars/availability` → [`POST /v3/calendars/availability`](https://developer.nylas.com/docs/api/v3/ecc/#post-/v3/calendars/availability)
15 | - Check a calendar for free/busy status: `POST /calendars/free-busy` → [`POST /v3/grants/<NYLAS_GRANT_ID>/calendars/free-busy`](https://developer.nylas.com/docs/api/v3/ecc/#post-/v3/grants/-grant_id-/calendars/free-busy)
16 | 
17 | ### Deprecated Calendars endpoints
18 | 
19 | - Get availability for multiple consecutive meetings: `POST /calendars/availability/consecutive`
20 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Email/Drafts/index.md:
--------------------------------------------------------------------------------

```markdown
 1 | ## Changes to Drafts
 2 | 
 3 | Nylas v3 includes the following changes to the Drafts API:
 4 | 
 5 | - All Drafts endpoints now require a `grant_id`, an email address, or — if you're using access token authentication — the [`/me/` construction](https://developer.nylas.com/docs/api/v3/ecc/#overview--me-syntax-for-api-calls).
 6 | - You can now send drafts.
 7 | - The `use_draft` parameter is now available for `POST` requests.
 8 | - Updated draft-related response fields in the Threads API:
 9 |   - Added `latest_draft_or_message` field.
10 |   - Added `has_drafts` field.
11 |   - Updated `last_message_timestap` field to be a `date` sub-field in the `latest_draft_or_message` object.
12 | 
13 | ### New Drafts endpoints
14 | 
15 | - Send a draft: [`POST /v3/grants/<NYLAS_GRANT_ID>/drafts/<DRAFT_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#post-/v3/grants/-grant_id-/drafts/-draft_id-)
16 | 
17 | ### Migrated Drafts endpoints
18 | 
19 | - Return all drafts: `GET /drafts` → [`GET /v3/grants/<NYLAS_GRANT_ID>/drafts`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/drafts)
20 | - Create a draft: `POST /drafts` → [`POST /v3/grants/<NYLAS_GRANT_ID>/drafts`](https://developer.nylas.com/docs/api/v3/ecc/#post-/v3/grants/-grant_id-/drafts)
21 | - Return a draft: `GET /drafts/<DRAFT_ID>` → [`GET /v3/grants/<NYLAS_GRANT_ID>/drafts/<DRAFT_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/drafts/-draft_id-)
22 | - Update a draft: `PUT /drafts/<DRAFT_ID>` → [`PUT /v3/grants/<NYLAS_GRANT_ID>/drafts/<DRAFT_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#put-/v3/grants/-grant_id-/drafts/-draft_id-)
23 | - Delete a draft: `DELETE /drafts/<DRAFT_ID>` → [`DELETE /v3/grants/<NYLAS_GRANT_ID>/drafts/<DRAFT_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#delete-/v3/grants/-grant_id-/drafts/-draft_id-)
24 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Email/Threads/index.md:
--------------------------------------------------------------------------------

```markdown
 1 | ## Changes to Threads
 2 | 
 3 | Nylas v3 includes the following changes to the Threads API:
 4 | 
 5 | - All Threads endpoints now require a `grant_id`, an email address, or — if you're using access token authentication — the [`/me/` construction](https://developer.nylas.com/docs/api/v3/ecc/#overview--me-syntax-for-api-calls).
 6 | - You can now soft-delete threads.
 7 | - The `folder` object in all Threads now contains a list of `folder_id`s instead of an array of Folders.
 8 | - Support for the `view=expanded` query parameter is deprecated.
 9 | 
10 | ### New Threads endpoints
11 | 
12 | - Delete a thread: [`DELETE /v3/grants/<NYLAS_GRANT_ID>/threads/<THREAD_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#delete-/v3/grants/-grant_id-/threads/-thread_id-)
13 | 
14 | ### Migrated Threads endpoints
15 | 
16 | - Return all threads: `GET /threads` → [`GET /v3/grants/<NYLAS_GRANT_ID>/threads`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/threads)
17 | - Return a specific thread: `GET /threads/<THREAD_ID>` → [`GET /v3/grants/<NYLAS_GRANT_ID>/threads/<THREAD_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/threads/-thread_id-)
18 | - Update a specific thread: `PUT /threads/<THREAD_ID>` → [`PUT /v3/grants/<NYLAS_GRANT_ID>/threads/<THREAD_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#put-/v3/grants/-grant_id-/threads/-thread_id-)
19 | 
20 | ### Changes to Threads response fields
21 | 
22 | Nylas v3 adds the following response fields for `/threads` requests:
23 | 
24 | - `latest_draft_or_message`: The most recent draft or email message in the thread.
25 | - `has_drafts`: Indicates whether the thread has associated Drafts.
26 | 
27 | The following response fields have also been updated:
28 | 
29 | - `first_message_timestamp` → `earliest_message_date`
30 | - `last_message_received_timestamp` → `latest_message_received_date`
31 | - `last_message_sent_timestamp` → `latest_message_sent_date`
32 | - `last_message_timestamp` → `latest_draft_or_message.date`
33 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Auth/connected-accounts.md:
--------------------------------------------------------------------------------

```markdown
 1 | ### Connected Accounts changed to Grants
 2 | 
 3 | In Nylas v3, the concept of "grants" (as in, "the end user _granted_ you this access") replaces "connected accounts". This name better reflects the new offering and lays the groundwork for future enhancements and features.
 4 | 
 5 | - Nylas APIs now return a `grant_id` instead of an `account_id`.
 6 | - All Email, Calendar, and Contacts APIs include the `/v3/grants/<NYLAS_GRANT_ID>` prefix.
 7 |   - You can refer to an end user's grant using their `grant_id`, their email address, or (if you're using an access token for their grant), the `/me/` construction.
 8 | - The `account.invalid` webhook trigger is deprecated. You should subscribe to `grant.expired` instead.
 9 | 
10 | ### New Grants endpoints
11 | 
12 | - Update a grant: [`PATCH /v3/grants/<NYLAS_GRANT_ID>`](https://developer.nylas.com/docs/api/v3/admin/#patch-/v3/grants/-grantId-)
13 | - Get the current grant: [`GET /v3/grants/me`](https://developer.nylas.com/docs/api/v3/admin/#get-/v3/grants/me)
14 | 
15 | ### Migrated Accounts endpoints
16 | 
17 | - Return all grants: `GET /a/<NYLAS_CLIENT_ID>` → [`GET /v3/grants`](https://developer.nylas.com/docs/api/v3/admin/#get-/v3/grants)
18 | - Return a specific grant: `GET /a/<NYLAS_CLIENT_ID>/accounts/<NYLAS_ACCOUNT_ID>` → [`GET /v3/grants/<NYLAS_GRANT_ID>`](https://developer.nylas.com/docs/api/v3/admin/#get-/v3/grants/-grantId-)
19 | - Delete a grant: `DELETE /a/<NYLAS_CLIENT_ID>/accounts/<NYLAS_ACCOUNT_ID>` → [`DELETE /v3/grants/<NYLAS_GRANT_ID>`](https://developer.nylas.com/docs/api/v3/admin/#delete-/v3/grants/-grantId-)
20 | 
21 | ### Deprecated Accounts endpoints
22 | 
23 | - Cancel an account: `POST /a/<NYLAS_CLIENT_ID>/accounts/<NYLAS_ACCOUNT_ID>/downgrade`
24 | - Reactivate an account: `POST /a/<NYLAS_CLIENT_ID>/accounts/<NYLAS_ACCOUNT_ID>/upgrade`
25 | - Revoke all tokens: `POST /a/<NYLAS_CLIENT_ID>/accounts/<NYLAS_ACCOUNT_ID>/revoke-all`
26 | - Return token information: `POST /a/<NYLAS_CLIENT_ID>/accounts/<NYLAS_ACCOUNT_ID>/token-info`
27 | - Revoke an access token: `POST /oauth/revoke`
28 | - Return account details: `GET /account`
29 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Email/Messages/index.md:
--------------------------------------------------------------------------------

```markdown
 1 | ## Changes to Messages
 2 | 
 3 | Nylas v3 includes the following changes to the Messages API:
 4 | 
 5 | - All Messages endpoints now require a `grant_id`, an email address, or — if you're using access token authentication — the [`/me/` construction](https://developer.nylas.com/docs/api/v3/ecc/#overview--me-syntax-for-api-calls).
 6 | - You can now soft-delete email messages.
 7 | - The `folder` object in all Messages now contains a list of `folder_id`s instead of an array of Folders.
 8 | 
 9 | ### New Messages endpoints
10 | 
11 | - Clean an email message: [`PUT /v3/grants/<NYLAS_GRANT_ID>/messages/clean`](https://developer.nylas.com/docs/api/v3/ecc/#put-/v3/grants/-grant_id-/messages/clean)
12 | - Delete an email message: [`DELETE /v3/grants/<NYLAS_GRANT_ID>/messages/<MESSAGE_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#delete-/v3/grants/-grant_id-/messages/-message_id-)
13 | - Compose an email message: [`POST /v3/grants/<NYLAS_GRANT_ID>/messages/smart-compose`](https://developer.nylas.com/docs/api/v3/ecc/#post-/v3/grants/-grant_id-/messages/smart-compose)
14 | - Compose a reply to a specific email message: [`POST /v3/grants/<NYLAS-GRANT_ID>/messages/<MESSAGE_ID>/smart-compose`](https://developer.nylas.com/docs/api/v3/ecc/#post-/v3/grants/-grant_id-/messages/-message_id-/smart-compose)
15 | 
16 | ### Migrated Messages endpoints
17 | 
18 | - Return all email messages: `GET /messages` → [`GET /v3/grants/<NYLAS_GRANT_ID>/messages`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/messages)
19 | - Return a specific email message: `GET /messages/<MESSAGE_ID>` → [`GET /v3/grants/<NYLAS_GRANT_ID>/messages/<MESSAGE_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/messages/-message_id-)
20 | - Update an email message: `PUT /messages/<MESSAGE_ID>` → [`PUT /v3/grants/<NYLAS_GRANT_ID>/messages/<MESSAGE_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#put-/v3/grants/-grant_id-/messages/-message_id-)
21 | - Send an email message: `POST /send` → [`POST /v3/grants/<NYLAS_GRANT_ID>/messages/send`](https://developer.nylas.com/docs/api/v3/ecc/#post-/v3/grants/-grant_id-/messages/send)
22 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Email/Outbox/write.md:
--------------------------------------------------------------------------------

```markdown
 1 | ### Cancel scheduled send instructions
 2 | 
 3 | `DELETE /outbox/<SCHEDULE_ID>` → [`DELETE /v3/grants/<NYLAS_GRANT_ID>/messages/schedules/<SCHEDULE_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#delete-/v3/grants/-grant_id-/messages/schedules/-scheduleId-)
 4 | 
 5 | ```Node
 6 | import "dotenv/config";
 7 | import Nylas from "nylas";
 8 | 
 9 | const NylasConfig = {
10 |   apiKey: process.env.NYLAS_API_KEY,
11 |   apiUri: process.env.NYLAS_API_URI,
12 | };
13 | 
14 | const nylas = new Nylas(NylasConfig);
15 | 
16 | async function deleteMessageSchedule() {
17 |   try {
18 |     const result = await nylas.messages.stopScheduledMessage({
19 |       identifier: process.env.NYLAS_GRANT_ID,
20 |       scheduleId: process.env.SCHEDULE_ID,
21 |     });
22 | 
23 |     console.log("Result:", result);
24 |   } catch (error) {
25 |     console.error("Error deleting message:", error);
26 |   }
27 | }
28 | 
29 | deleteMessageSchedule();
30 | ```
31 | 
32 | ```Java
33 | import com.nylas.NylasClient;
34 | import com.nylas.models.*;
35 | 
36 | public class ReturnMessage {
37 |   public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
38 |     NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
39 | 
40 |     Response<StopScheduledMessageResponse> message = nylas.messages().stopScheduledMessage(
41 |         "<NYLAS_GRANT_ID>", 
42 |         "SCHEDULED_MESSAGE_ID");
43 |         
44 |     System.out.println(message.getData());
45 |   }
46 | }
47 | ```
48 | 
49 | ```Python
50 | from dotenv import load_dotenv
51 | load_dotenv()
52 | 
53 | import os
54 | import sys
55 | from nylas import Client
56 | 
57 | nylas = Client(
58 |     os.environ.get('NYLAS_API_KEY'),
59 |     os.environ.get('NYLAS_API_URI')
60 | )
61 | 
62 | grant_id = os.environ.get("NYLAS_GRANT_ID")
63 | schedule_id = os.environ.get("SCHEDULE_ID")
64 | 
65 | result = nylas.messages.stop_scheduled_message(
66 |     grant_id,
67 |     schedule_id,
68 | )
69 | 
70 | print(result)
71 | ```
72 | 
73 | ```Ruby
74 | require 'nylas'
75 | 
76 | nylas = Nylas::Client.new(
77 |     api_key: "<NYLAS_API_KEY>"
78 | )
79 | 
80 | messages, _ = nylas.messages.stop_scheduled_messages(
81 |     identifier: ENV["NYLAS_GRANT_ID"], 
82 |     schedule_id: "<SCHEDULE_ID>")
83 | 
84 | messages.each {|message|
85 |   puts message
86 | }
87 | ```
88 | 
89 | ```API
90 | curl --request DELETE \
91 |   --url 'https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/messages/schedules/<SCHEDULE_ID>' \
92 |   --header 'Accept: application/json' \
93 |   --header 'Authorization: Bearer <NYLAS_API_KEY>'
94 | ```
95 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Auth/AppPermission-Bulk/index.md:
--------------------------------------------------------------------------------

```markdown
 1 | You can use connector credentials for bulk authentication with Google's Service Accounts. What are connector credentials, I hear you asking? They're new in v3, read on...
 2 | 
 3 | #### Introducing connector credentials
 4 | 
 5 | Nylas v3 includes "credentials", which are packages of information that you can use when authenticating to override default connector settings and auth methods. You might use this if you're using more than one GCP auth app to authenticate your end users.
 6 | 
 7 | You can create credentials for alternate GCP auth apps, which include the app's `client_id` and `client_secret`, and any other connection settings. Nylas encrypts and stores this information securely in a credential record. You then refer to the record in Custom auth requests using the `credential_id`. This allows you to authenticate end users with the non-default GCP auth app.
 8 | 
 9 | Connector credentials are linked to a specific connector in a specific Nylas application. If you created the connector credential for a specific Google connector, you can't use the `credential_id` for a different connector, or with a different Nylas application.
10 | 
11 | ### Bulk authentication with Google Service Accounts
12 | 
13 | You can use connector credentials for bulk authentication with Google's Service Accounts. To do this, first create a [Google auth app](https://developer.nylas.com/docs/dev-guide/provider-guides/google/create-google-app/) and a [Google connector](https://developer.nylas.com/docs/dev-guide/provider-guides/google/create-google-app/#add-a-connector-to-your-nylas-application). Next, create your connector credential:
14 | 
15 | 1. Make a [`POST /v3/connectors/<PROVIDER>/creds` request](https://developer.nylas.com/docs/api/v3/admin/#post-/v3/connectors/-provider-/creds).
16 | 2. Nylas returns a JSON response with the `id` of the new connector credential. Be sure to save it somewhere secure.
17 | 
18 | Now, you can create an app permission grant:
19 | 
20 | 1. Make a [`POST /v3/connect/custom` request](https://developer.nylas.com/docs/api/v3/admin/#post-/v3/connect/custom) that includes the `credential_id` of the connector credential you created.
21 | 2. Nylas returns a JSON response containing the grant's information.
22 | 
```

--------------------------------------------------------------------------------
/CONTRIBUTION.md:
--------------------------------------------------------------------------------

```markdown
 1 | ## How to Contribute
 2 | 
 3 | First, thanks for taking the time to contribute to our code sample! This guide will tell you everything you need to know about contributing to the Nylas Samples.
 4 | 
 5 | ## Code of Conduct
 6 | 
 7 | We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
 8 | We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
 9 | 
10 | By participating in this project, you agree to abide by the [Nylas Code of Conduct](CODE_OF_CONDUCT.md). If you feel there is a conduct issue related to this project, please raise it per the outlined process, and we will address it.
11 | How to Ask a Question
12 | If you have a question that needs an answer, create an issue, and label it as a question.
13 | 
14 | ## How To Contribute
15 | 
16 | ### Report a Bug or Request a Feature
17 | 
18 | If you encounter any bugs while using this software or request a new feature or enhancement, feel free to create an issue to report it; make sure you add a label to indicate what type of issue it is.
19 | 
20 | ### Contribute Code
21 | 
22 | Pull requests are welcome for bug fixes. If you want to implement something new, please create an issue to request a feature first to discuss it. The earlier you tell us about your intentions, the better.
23 | 
24 | ### Create a Pull Request
25 | 
26 | Please follow best practices for creating git commits. When your code is ready to be submitted, you can submit a pull request to begin the code review process.
27 | 
28 | We can only accept code you are authorized to contribute to the project. This project includes a PR template that includes the line below. This line must be present in your PR for us to accept it:
29 | 
30 | - I confirm that this contribution is made under the terms of the [license](LICENSE) found in the root directory of this repository's source tree and that I have the authority necessary to make this contribution on behalf of its copyright owner.
```

--------------------------------------------------------------------------------
/nylas-code-samples/Email/Search/read.md:
--------------------------------------------------------------------------------

```markdown
  1 | ### Search messages
  2 | 
  3 | `/messages/search` → [`GET /v3/grants/<NYLAS_GRANT_ID>/messages` request](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/messages)
  4 | 
  5 | ```Node
  6 | import 'dotenv/config'
  7 | import Nylas from 'nylas'
  8 | 
  9 | const NylasConfig = {
 10 |   apiKey: process.env.NYLAS_API_KEY,
 11 |   apiUri: process.env.NYLAS_API_URI,
 12 | }
 13 | 
 14 | const nylas = new Nylas(NylasConfig)
 15 | 
 16 | async function searchInbox() {
 17 |   try {
 18 |     const result = await nylas.messages.list({
 19 |       identifier: process.env.NYLAS_GRANT_ID,
 20 |       queryParams: {
 21 |         search_query_native: 'nylas',
 22 |         limit: 5
 23 |       }
 24 |     })
 25 | 
 26 |     console.log('search results:', result)
 27 |   } catch (error) {
 28 |     console.error('Error to complete search:', error)
 29 |   }
 30 | }
 31 | 
 32 | searchInbox()
 33 | ```
 34 | 
 35 | ```Java
 36 | 
 37 | ```
 38 | 
 39 | ```Python
 40 | from dotenv import load_dotenv
 41 | load_dotenv()
 42 | 
 43 | import os
 44 | import sys
 45 | from nylas import Client
 46 | 
 47 | nylas = Client(
 48 |     os.environ.get('NYLAS_API_KEY'),
 49 |     os.environ.get('NYLAS_API_URI')
 50 | )
 51 | 
 52 | grant_id = os.environ.get("NYLAS_GRANT_ID")
 53 | 
 54 | messages = nylas.messages.list(
 55 |     grant_id,
 56 |     query_params={
 57 |       "limit": 5,
 58 |       "search_query_native": 'nylas'
 59 |     }
 60 | )
 61 | 
 62 | print(messages)
 63 | ```
 64 | 
 65 | ```Ruby
 66 | 
 67 | ```
 68 | 
 69 | ```API
 70 | 
 71 | ```
 72 | 
 73 | ### Search threads
 74 | 
 75 | `/threads/search` → [`GET /v3/grants/<NYLAS_GRANT_ID>/threads` request](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/threads)
 76 | 
 77 | ```Node
 78 | import 'dotenv/config'
 79 | import Nylas from 'nylas'
 80 | 
 81 | const NylasConfig = {
 82 |   apiKey: process.env.NYLAS_API_KEY,
 83 |   apiUri: process.env.NYLAS_API_URI,
 84 | }
 85 | 
 86 | const nylas = new Nylas(NylasConfig)
 87 | 
 88 | async function searchInbox() {
 89 |   try {
 90 |     const result = await nylas.threads.list({
 91 |       identifier: process.env.NYLAS_GRANT_ID,
 92 |       queryParams: {
 93 |         search_query_native: 'nylas',
 94 |         limit: 5
 95 |       }
 96 |     })
 97 | 
 98 |     console.log('search results:', result)
 99 |   } catch (error) {
100 |     console.error('Error to complete search:', error)
101 |   }
102 | }
103 | 
104 | searchInbox()
105 | ```
106 | 
107 | ```Java
108 | 
109 | ```
110 | 
111 | ```Python
112 | from dotenv import load_dotenv
113 | load_dotenv()
114 | 
115 | import os
116 | import sys
117 | from nylas import Client
118 | 
119 | nylas = Client(
120 |     os.environ.get('NYLAS_API_KEY'),
121 |     os.environ.get('NYLAS_API_URI')
122 | )
123 | 
124 | grant_id = os.environ.get("NYLAS_GRANT_ID")
125 | 
126 | messages = nylas.threads.list(
127 |     grant_id,
128 |     query_params={
129 |       "limit": 5,
130 |       "search_query_native": 'nylas'
131 |     }
132 | )
133 | 
134 | print(messages)
135 | ```
136 | 
137 | ```Ruby
138 | 
139 | ```
140 | 
141 | ```API
142 | 
143 | ```
144 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Start/Dashboard-Import/index.md:
--------------------------------------------------------------------------------

```markdown
 1 | :::warn
 2 | ⚠️ **You can only import a v2 application into a v3 application in the same data center region**. You cannot use the Import tools to move a v2 application to a different region.
 3 | :::
 4 | 
 5 | 1. Go to the [Nylas v3 Dashboard](https://dashboard-v3.nylas.com/?utm_source=migration-station&utm_medium=devrel-surfaces&utm_campaign=migration-station&utm_content=one-click-migrate) and log in as an admin user.
 6 |    Only administrators can migrate v2 applications.
 7 | 2. Find the v2 app you want to migrate. It'll be marked `Legacy`.
 8 | 3. Click **Migrate app** next to that legacy app to create a new v3 application.
 9 | 4. In the dialog, confirm the title and the environment tag (Development, Stating, Production), and optionally add a description.
10 | 5. Click **Create app**. Nylas copies your v2 connector data to the v3 application and starts migrating connected accounts.
11 | 
12 |    After you start a migration, Nylas brings you back to the application list. The migration process is asynchronous, and you can continue working on other things while Nylas works.
13 | 
14 |    The v3 version of the application appears in the list with a `Migrated` label. The info icon shows the v2 application ID that the v3 app is based on. You can click the v3 application and go to the **Grants** page to see the migration progress.
15 | 
16 | 6. After you start the migration, go to your v3 application, and check the list of migrated connectors to make sure it looks complete. If you need to do additional steps for specific providers, they are covered later in this guide.
17 | 7. Continue following the rest of the instructions in this guide. The account migration might take some time. (If you're already done with the rest of your migration, have a ☕️ and maybe even some 🍰 to celebrate! You're almost done.)
18 | 8. When Nylas finishes migrating accounts to Grants, the Grants page for the new v3 application shows progress as 100%. You can then download a CSV report of the migration details, including any accounts that could not be migrated and the error Nylas encountered.
19 | 
20 | :::success
21 | 👀 **Good to know:** The Nylas migration job marks an account migration as `failed` if it was unable to import and create a grant for that account. However, for many of these cases, the user can still start a completely new authentication on the v3 system to use your application. This is expected in the case of Microsoft accounts that used Exchange, such as personal accounts on Hotmail, Live, and Outlook.
22 | :::
23 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Contacts/index.md:
--------------------------------------------------------------------------------

```markdown
 1 | ## Changes to Contacts
 2 | 
 3 | Nylas v3 includes the following changes to the Contacts API:
 4 | 
 5 | - Contacts are now returned as JSON objects, instead of being listed as comma-separated values.
 6 | - All Contacts endpoints now require a `grant_id`, an email address, or — if you're using access token authentication — the [`/me/` construction](https://developer.nylas.com/docs/api/v3/ecc/#overview--me-syntax-for-api-calls).
 7 | - You might need to add scopes to access domain-level or inbox contacts. If you use only contacts from address books, you don't need to make any changes.
 8 |   - To access contacts parsed from an end user's inbox, use the `inbox` source and request the `contacts.other.readonly` Google scope or `People.Read` Microsoft scope.
 9 |   - To access contacts parsed from an end user's domain address book, use the `domain` source and request the `directory.readonly` Google scope or `People.Read` Microsoft scope.
10 | - Nylas polls for changes to contacts for Google accounts in five-minute intervals.
11 | 
12 | ### Migrated Contacts endpoints
13 | 
14 | - Return all contacts: `GET /contacts` → [`GET /v3/grants/<NYLAS_GRANT_ID>/contacts`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/contacts)
15 | - Create a contact: `POST /contacts` → [`POST /v3/grants/<NYLAS_GRANT_ID>/contacts`](https://developer.nylas.com/docs/api/v3/ecc/#post-/v3/grants/-grant_id-/contacts)
16 | - Return a contact: `GET /contacts/<CONTACT_ID>` → [`GET /v3/grants/<NYLAS_GRANT_ID>/contacts/<CONTACT_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/contacts/-contact_id-)
17 | - Update a contact: `PUT /contacts/<CONTACT_ID>` → [`PUT /v3/grants/<NYLAS_GRANT_ID>/contacts/<CONTACT_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#put-/v3/grants/-grant_id-/contacts/-contact_id-)
18 | - Delete a contact: `DELETE /contacts/<CONTACT_ID>` → [`DELETE /v3/grants/<NYLAS_GRANT_ID>/contacts/<CONTACT_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#delete-/v3/grants/-grant_id-/contacts/-contact_id-)
19 | - Return all contact groups: `GET /contacts/groups` → [`GET /v3/grants/<NYLAS_GRANT_ID>/contacts/groups`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/contacts/groups)
20 | 
21 | ### Deprecated Contacts endpoints
22 | 
23 | The v2 `GET /contacts/<CONTACT_ID>/picture` endpoint has been deprecated. Instead, you can now include the `?profile_picture=true` query parameter in a [Get Contact request](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/contacts/-contact_id-).
24 | 
```

--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
 2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
 3 | import express from "express";
 4 | import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
 5 | 
 6 | // Import resources, tools, and prompts
 7 | import { registerResources } from "./resources/index.js";
 8 | import { registerTools } from "./tools/index.js";
 9 | import { registerPrompts } from "./prompts/index.js";
10 | 
11 | // Create an MCP server
12 | const server = new McpServer({
13 |   name: "Nylas API Docs",
14 |   version: "1.0.0"
15 | });
16 | 
17 | // Register all resources, tools, and prompts
18 | registerResources(server);
19 | registerTools(server);
20 | registerPrompts(server);
21 | 
22 | async function main() {
23 |   // Determine if we're running in stdio or HTTP mode
24 |   const mode = process.env.MCP_MODE || "stdio";
25 | 
26 |   if (mode === "stdio") {
27 |     // Connect using stdio transport
28 |     const transport = new StdioServerTransport();
29 |     await server.connect(transport);
30 |   } else if (mode === "http") {
31 |     // Start HTTP server with SSE
32 |     const app = express();
33 |     const port = parseInt(process.env.PORT || "3000");
34 |     
35 |     // Map to store active connections
36 |     const activeConnections = new Map();
37 |     
38 |     app.get("/sse", async (req, res) => {
39 |       const id = Date.now().toString();
40 |       const transport = new SSEServerTransport("/messages", res);
41 |       
42 |       // Store the transport in our map
43 |       activeConnections.set(id, transport);
44 |       
45 |       // Set headers for SSE
46 |       res.setHeader("Content-Type", "text/event-stream");
47 |       res.setHeader("Cache-Control", "no-cache");
48 |       res.setHeader("Connection", "keep-alive");
49 |       res.setHeader("Access-Control-Allow-Origin", "*");
50 |       
51 |       // Add a query parameter with the connection ID
52 |       res.write(`data: ${JSON.stringify({ id })}\n\n`);
53 |       
54 |       // Connect to the server
55 |       await server.connect(transport);
56 |       
57 |       // Remove the connection when it closes
58 |       req.on("close", () => {
59 |         activeConnections.delete(id);
60 |       });
61 |     });
62 |     
63 |     app.post("/messages", express.json(), async (req, res) => {
64 |       const id = req.query.id as string;
65 |       
66 |       if (!id || !activeConnections.has(id)) {
67 |         return res.status(404).json({ error: "Connection not found" });
68 |       }
69 |       
70 |       const transport = activeConnections.get(id);
71 |       await transport.handlePostMessage(req, res);
72 |     });
73 |     
74 |     app.listen(port, () => {
75 |       console.log(`Nylas API MCP server running on http://localhost:${port}`);
76 |     });
77 |   } else {
78 |     console.error(`Unknown mode: ${mode}. Use 'stdio' or 'http'.`);
79 |     process.exit(1);
80 |   }
81 | }
82 | 
83 | main().catch(err => {
84 |   console.error("Fatal error:", err);
85 |   process.exit(1);
86 | });
```

--------------------------------------------------------------------------------
/nylas-code-samples/Auth/Providers/ms.md:
--------------------------------------------------------------------------------

```markdown
 1 | Nylas v3 includes the following changes that require you modify your Azure auth app before you can re-authenticate your end users:
 2 | 
 3 | - The **Authorized redirect URIs** for Hosted Auth have been updated in v3.
 4 |   - **U.S.**: `https://api.us.nylas.com/v3/connect/callback`
 5 |   - **E.U.**: `https://api.eu.nylas.com/v3/connect/callback`
 6 | - Nylas v3 no longer uses "Nylas scopes", and uses Microsoft's scopes instead.
 7 | 
 8 | ### Update authorized redirect URIs in Azure app
 9 | 
10 | For all Azure auth apps that you want to connect to Nylas v3, the authorized redirect URIs for Hosted Auth have been updated. Add one, or both, of the following to the **Authorized redirect URIs** section of your Azure app:
11 | 
12 | - **U.S.**: `https://api.us.nylas.com/v3/connect/callback`
13 | - **E.U.**: `https://api.eu.nylas.com/v3/connect/callback`
14 | 
15 | ### Calculate v3 scopes for Azure app
16 | 
17 | In v3, Nylas no longer uses "Nylas scopes", but directly uses Microsoft's scopes instead. Make a list of the v2 API endpoints your project uses, then read the [v3 scopes documentation](https://developer.nylas.com/docs/v3/auth/v3-scopes/) to determine the scopes you need for v3.
18 | 
19 | When you know what v3 scopes you need, add them to your Azure auth app's Entra ID system (previously "Azure ID"). For more information, see Microsoft's official [Configure Azure AD Graph permissions for an app registration guide](https://learn.microsoft.com/en-us/graph/migrate-azure-ad-graph-configure-permissions).
20 | 
21 | ### Do I need to re-verify my Azure app?
22 | 
23 | _In general_, you shouldn't need to re-verify your Azure app unless you're adding new features to your project. However, some items might require changes if your app doesn't already include their scopes:
24 | 
25 | - **If you're using Microsoft Hosted OAuth in v2 _without_ Graph scopes**, you might need to re-verify when you migrate to Graph scopes.
26 |   - Nylas recommends you migrate to Graph scopes using a new Azure auth app, so you can switch over without disrupting your end users' workflows.
27 | - **If you use `thread.replied` webhook notifications**, these now use the `email.read` scope in v3, instead of the v2 `email.metadata` scopes.
28 | - **If you use the Contacts APIs and want to use domain-level or inbox contacts**, you might need to add some scopes. If you use address book contacts only, you don't need to make any changes.
29 | 
30 | ### Changes to Microsoft auth features
31 | 
32 | - The only EWS account type that Nylas v3 supports is **Exchange on-premises**. Other EWS accounts (personal accounts on Hotmail, Office 365, Live, and Outlook) must complete a fresh authentication flow using the Microsoft connector, which upgrades them to use Graph scopes.
33 | - Nylas no longer supports Exchange on-premises service accounts.
34 | - Nylas now supports **Account in any organizational directory and personal Microsoft accounts**. This allows end users to authenticate using their personal accounts.
35 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Start/api-import.md:
--------------------------------------------------------------------------------

```markdown
 1 | The [Nylas Migration APIs](https://developer.nylas.com/docs/api/v3/migration/) help you migrate your application and end-user data from Nylas v2 to v3. This section is intended to help you [upgrade the rest of your application](https://developer.nylas.com/docs/v2/upgrade-to-v3/) to Nylas v3.
 2 | 
 3 | :::warn
 4 | ⚠️ **The Migration APIs are for one-time translation of data and objects from v2 to v3**. You can retry API calls if you run into issues, but they will be rate-limited, and you _should not_ use them as part of your project's code or object handling logic.
 5 | :::
 6 | 
 7 | Before you begin...
 8 | 
 9 | - Make sure your v2 and v3 Nylas organizations are linked. If they're correctly linked, you can see all your legacy v2 Nylas applications from both regions in the v3 Dashboard.
10 |   - If you don't see all of your legacy applications on the Dashboard, [contact Nylas Support](https://support.nylas.com/hc/en-us/requests/new?ticket_form_id=360000247971).
11 | - Create a v3 Nylas application for each v2 application you plan to migrate.
12 | 
13 | ### Migrate your Nylas implementation
14 | 
15 | :::warn
16 | ⚠️ **Make sure you use the correct region!** In Nylas v3, you manage both your U.S. and E.U. applications using the same Dashboard. Make sure you select the same region as the corresponding v2 application when you create a v3 application.
17 | :::
18 | 
19 | Now that you're set up, it's time to migrate your data:
20 | 
21 | 1. Make a [`POST /v3/migration-tools/link-v2v3-apps` request](https://developer.nylas.com/docs/api/v3/migration/#post-/v3/migration-tools/link-v2v3-apps) to link a v2 application to its equivalent v3 application.
22 | 2. Make a [`POST /v3/migration-tools/import-v2-app` request](https://developer.nylas.com/docs/api/v3/migration/#post-/v3/migration-tools/link-v2v3-apps) to migrate your v2 Integrations to v3 Connectors, and copy other important application settings.
23 | 3. Make any necessary changes to your provider auth apps. This will be covered later in the guide, but you can return to this section when you complete the process.
24 | 4. Configure your connectors. (This is also covered later in the guide.)
25 | 5. **Subscribe to v3 notification triggers** (using either webhooks or Pub/Sub) so you can keep track of any objects that change while you're migrating.
26 | 6. Make a [`POST /v3/migration-tools/grants/<NYLAS_ACCOUNT_ID>/clone` request](https://developer.nylas.com/docs/api/v3/migration/#post-/v3/migration-tools/grants/-account_id-/clone) to test migrating a single account at a time.
27 |     - You can use this migrated account to do initial testing on your webhooks and other API settings before you migrate more end users.
28 | 7. When you're ready to migrate more end-user information, make a [`POST /v3/migration-tools/snapshot-batch-clone` request](https://developer.nylas.com/docs/api/v3/migration/#post-/v3/migration-tools/snapshot-batch-clone) to migrate all of your v2 Connected Accounts to v3 Grants.
29 |     - Migrated grants are de-duplicated with your v2 connected accounts, so they're counted as one account for billing purposes.
30 | 8. Upgrade your project code to use the Nylas v3 APIs and systems.
31 |     - Make sure you update your login page to use v3 authentication, so end users can seamlessly use v3 when they re-authenticate!
32 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Coda/index.md:
--------------------------------------------------------------------------------

```markdown
 1 | You did it! 🎉 You got through all the migration instructions!
 2 | 
 3 | The info below is some "good to know" information that you don't necessarily need to upgrade and migrate, but that you'll want to know for later.
 4 | 
 5 | ### Tuning your queries
 6 | 
 7 | Service providers like Google and Microsoft implement strict [rate limiting](https://developer.nylas.com/docs/dev-guide/platform/rate-limits/). Because Nylas v3 queries providers directly, it's important that you make sure your API requests limit the amount of data they request so you don't hit these provider rate limits.
 8 | 
 9 | You can use filtering and query selection to limit both the number of objects Nylas queries, and the amount of data Nylas returns about those objects. For example, if you're searching for an event with a specific title, you would ignore other returned fields like the event description. To make an efficient query, you could use a `title=<Your title here>` query parameter, and then use `select=title,id` to make sure Nylas only returns the information you need.
10 | 
11 | ### Changes to metadata
12 | 
13 | In Nylas v2, you could add up to 50 pairs of arbitrary metadata key-pairs to Calendars, Events, and Messages, and use the keys as query parameters to filter data that Nylas returns. This sometimes led to high latency when returning results.
14 | 
15 | In v3, you can still add metadata key-pairs to Calendars and Events, but Nylas only indexes five specific keys: `key1`, `key2`, `key3`, `key4`, and `key5`. To continue using metadata filtering, you must write the values you want to filter by to the keys that Nylas indexes.
16 | 
17 | Nylas uses the `key5` value when calculating round-robin availability for events. If you're using round-robin scheduling, you might want to make a plan for how you distribute queryable metadata among the five keys.
18 | 
19 | You cannot use metadata filters with provider value filters, except for `calendar_id`.
20 | 
21 | ### Terminology updates
22 | 
23 | We've taken the opportunity to clarify some of our language with Nylas v3:
24 | 
25 | - The **integration** object that you create in your Nylas application to store provider details is now called a **connector**.
26 | - **Provider integration applications** are now called **provider auth apps**.
27 | - **Native authentication** is now **Custom authentication**.
28 | - **Service accounts** (sometimes called "app permissions") are now **bulk authentication grants**.
29 | - The `redirect_uri` set in Nylas applications that use Hosted auth is now called the `callback_uri`. This helps to distinguish it from the Nylas `redirect_uri` set in provider auth apps.
30 | - The `callback_uri` used by webhook subscriptions is now called `webhook_url`.
31 | 
32 | ### Do your users need to re-authenticate?
33 | 
34 | When you migrate from Nylas v2 to v3, some end users will be able to log in right away, and some will need to re-authenticate.
35 | 
36 | - When you create a connector for a new provider such as iCloud, Yahoo, or Exchange on-prem.
37 | - When you upgrade a Microsoft account's scopes from Exchange scopes to Graph scopes.
38 |   - If the account used token auth, they just need to refresh their account.
39 |   - If the account used password auth, they must fully re-authenticate.
40 | - When you change the scopes you request for your Google or Microsoft provider auth app.
41 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Start/index.md:
--------------------------------------------------------------------------------

```markdown
 1 | #### Changes to API format and use
 2 | 
 3 | - The Nylas API endpoints have changed for v3:
 4 |   - `api.nylas.com` → `api.us.nylas.com`
 5 |   - `canada.api.nylas.com` → `api.us.nylas.com`
 6 |   - `ireland.api.nylas.com` → `api.eu.nylas.com`
 7 | - All Nylas traffic now goes through HTTPS (port `443`), and Nylas no longer supports HTTP (port `80`).
 8 | - The Nylas API no longer honors the `Nylas-API-Version` header.
 9 | - Endpoint URIs now include the Nylas API version (for example, `GET /v3/applications`).
10 | - URIs for endpoints that act on an end user's data include a `/grants/<NYLAS_GRANT_ID>` prefix that serves as a record locator (for example, `POST /v3/grants/<NYLAS_GRANT_ID>/calendars`).
11 | - Nylas v3 retrieves data directly from the service provider, and references it using the provider's object IDs.
12 |   - Nylas no longer generates a "Nylas ID" for objects. If your project uses Nylas IDs to keep track of objects, you can use the [`POST /v3/migration-tools/translate` endpoint](https://developer.nylas.com/docs/api/v3/migration/#post-/v3/migration-tools/translate) to update object IDs in your database.
13 | 
14 | #### Upgrading to Bearer token authentication
15 | 
16 | Nylas v3 supports `Authorization: Bearer <TOKEN>` only. You can no longer authenticate end users using `Authorization: <TOKEN>` or `Authorization: Basic <BASE64_ENCODED_TOKEN>`.
17 | 
18 | You can authenticate using either the secret from an application-wide API key (generated in the v3 Nylas Dashboard), or the short-lived access token for an individual end user (returned as part of a successful authentication).
19 | 
20 | #### Use API key instead of Client Secret
21 | 
22 | The v3 Nylas Dashboard only displays the `client_id` for Nylas applications.
23 | 
24 | Where you would previously have used the Nylas application's `client_secret` in API requests, you now use an _API key secret_.
25 | 
26 | #### Grants replace Connected Accounts
27 | 
28 | Nylas v3 replaces "connected accounts" with "grants" (as in, "the end user _granted_ you access to their data"). Because of this, Nylas v3 returns a `grant_id` instead of an `account_id` in responses.
29 | 
30 | If you're authorizing requests using an API key, you can reference a specific grant using either its `grant_id` or the associated email address.
31 | If you're authorizing requests using an end user's access token, you can use the [`/me/` construction](https://developer.nylas.com/docs/api/v3/ecc/#overview--me-syntax-for-api-calls) to refer to the grant associated with the token (for example, `GET /v3/grants/me/messages`).
32 | 
33 | #### Provider scopes replace Nylas scopes
34 | 
35 | Nylas v3 removes the [Nylas scopes abstraction](https://developer.nylas.com/docs/v2/developer-guide-v2/authentication/authentication-scopes/), and instead uses provider scopes to control your application's access to end-user data.
36 | 
37 | You can either create a login button for each provider that your application supports, or use the [`POST /v3/providers/detect` endpoint](https://developer.nylas.com/docs/api/v3/admin/#post-/v3/providers/detect) to determine which provider an end user is trying to authenticate with, so you can request the correct set of provider scopes.
38 | 
39 | #### Changes to pagination
40 | 
41 | Nylas v3 replaces the `offset` parameter with the new `cursor` query parameter, and changes the default page size to 50. For more information, see the [Pagination reference](https://developer.nylas.com/docs/api/v3/ecc/#overview--pagination).
42 | 
```

--------------------------------------------------------------------------------
/src/resources/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
  2 | 
  3 | // Import specific resource handlers
  4 | import { registerDocsResources } from "./docs.js";
  5 | import { registerCodeSamplesResources } from "./code-samples.js";
  6 | import { registerEndpointResources } from "./endpoints.js";
  7 | 
  8 | /**
  9 |  * Register all resources with the MCP server
 10 |  */
 11 | export function registerResources(server: McpServer) {
 12 |   // Register overview resources
 13 |   registerOverviewResources(server);
 14 |   
 15 |   // Register documentation resources
 16 |   registerDocsResources(server);
 17 |   
 18 |   // Register code sample resources
 19 |   registerCodeSamplesResources(server);
 20 |   
 21 |   // Register endpoint documentation
 22 |   registerEndpointResources(server);
 23 | }
 24 | 
 25 | /**
 26 |  * Register overview resources that provide general information about the Nylas API
 27 |  */
 28 | function registerOverviewResources(server: McpServer) {
 29 |   // Register a general overview of the Nylas API
 30 |   server.resource(
 31 |     "nylas-overview",
 32 |     "nylas://overview",
 33 |     async (uri) => ({
 34 |       contents: [{
 35 |         uri: uri.href,
 36 |         text: `# Nylas API Overview
 37 |         
 38 | The Nylas Communications Platform is a set of APIs that allows developers to easily integrate email, calendar, and contacts functionality into their applications. The platform provides a unified interface to access data from various providers like Gmail, Office 365, Exchange, and more.
 39 | 
 40 | ## Key Features
 41 | 
 42 | - **Email API**: Read, send, and organize emails
 43 | - **Calendar API**: Create, read, update, and delete calendar events
 44 | - **Contacts API**: Manage contact information
 45 | - **Authentication**: Secure OAuth-based authentication
 46 | - **Webhooks**: Real-time updates when data changes
 47 | - **Provider Agnostic**: Works with Gmail, Office 365, Exchange, and more
 48 | 
 49 | ## Getting Started
 50 | 
 51 | 1. Create a Nylas developer account
 52 | 2. Set up your application
 53 | 3. Authenticate users
 54 | 4. Start making API calls
 55 | 
 56 | For more information, use the resources provided by this MCP server to explore specific parts of the Nylas API.`,
 57 |         mimeType: "text/markdown"
 58 |       }]
 59 |     })
 60 |   );
 61 |   
 62 |   // Register authentication overview
 63 |   server.resource(
 64 |     "nylas-auth",
 65 |     "nylas://auth/overview",
 66 |     async (uri) => ({
 67 |       contents: [{
 68 |         uri: uri.href,
 69 |         text: `# Nylas Authentication Overview
 70 | 
 71 | Nylas uses OAuth 2.0 for authentication. The authentication flow allows your application to obtain an access token that can be used to make API calls on behalf of your users.
 72 | 
 73 | ## Authentication Flow
 74 | 
 75 | 1. **Redirect user**: Direct your user to the Nylas OAuth page
 76 | 2. **User grants access**: User authorizes your application
 77 | 3. **Receive callback**: Nylas redirects back to your application with a code
 78 | 4. **Exchange code**: Your server exchanges the code for an access token
 79 | 5. **Make API calls**: Use the access token to make API requests
 80 | 
 81 | ## Code Example
 82 | 
 83 | \`\`\`typescript
 84 | import { Nylas } from '@nylas/nylas-js';
 85 | 
 86 | // Initialize Nylas client
 87 | Nylas.config({
 88 |   clientId: 'YOUR_CLIENT_ID',
 89 |   clientSecret: 'YOUR_CLIENT_SECRET',
 90 | });
 91 | 
 92 | // Generate OAuth URL
 93 | const authUrl = Nylas.urlForAuthentication({
 94 |   redirectURI: 'YOUR_REDIRECT_URI',
 95 |   scopes: ['email.read_only', 'calendar.read_only', 'contacts.read_only'],
 96 | });
 97 | 
 98 | // Redirect user to authUrl
 99 | 
100 | // After user is redirected back to your redirect URI:
101 | const code = 'CODE_FROM_URL_PARAMETER';
102 | 
103 | // Exchange code for token
104 | Nylas.exchangeCodeForToken(code).then(token => {
105 |   console.log('Access token:', token);
106 | });
107 | \`\`\`
108 | 
109 | For more detailed information on authentication, refer to the specific authentication resources and code samples.`,
110 |         mimeType: "text/markdown"
111 |       }]
112 |     })
113 |   );
114 | }
```

--------------------------------------------------------------------------------
/nylas-code-samples/Calendar/Events/index.md:
--------------------------------------------------------------------------------

```markdown
 1 | ## Changes to Events
 2 | 
 3 | Nylas v3 includes the following changes to the Events API:
 4 | 
 5 | - The format for event start and end times has been simplified.
 6 |   - The `starts_before`, `starts_after`, `ends_before`, and `ends_after` parameters have been simplified to only two variables: `start` and `end`. `start` is equivalent to `ends_after` and `end` is equivalent to `starts_before`. When you use either in a query, an Event is returned if any part of it occurs between the `start` and `end` times.
 7 | - The following are added in v3:
 8 |   - `order_by` query parameter for all Events `GET` calls.
 9 |   - `html_link` property for all Events `GET` calls.
10 |   - `capacity` property for all Events calls.
11 | - The following are removed in v3:
12 |   - `event_id` query parameter for `GET` calls.
13 |   - `updated_at_before` property for `GET` calls.
14 |   - `participants` query parameter for `GET` calls.
15 |   - `customer_event_id` query parameter and property for all calls.
16 |   - `notifications` property for `POST` and `PUT` calls.
17 |   - `original_start_time` property for `GET` calls.
18 |   - `organizer_email` property for `GET` calls.
19 |   - `organizer_name` property for `GET` calls.
20 |   - `owner` property for `GET` calls.
21 |   - `message_id` for property `GET` calls.
22 |   - `recurrence.timezone` property for `GET` calls.
23 | - The Generate ICS file endpoint (`POST /events/to-ics`) is not available.
24 | 
25 | ### Changes to syntax
26 | 
27 | **Nylas v3 requires a calendar ID for almost all Events requests**, but also includes a new endpoint that you can use to return all calendars an end user has access to.
28 | 
29 | This means that you can no longer list all events from all calendars, and you must be able to identify which calendar an event is associated with in order to retrieve, update, or delete it. You can set the `calendar_id` to the end user's email address, or set it to `default` to select the default or main calendar for the end user on the service provider.
30 | 
31 | You can approach finding the calendar ID in the following ways:
32 | 
33 | - Get a list of all calendars for the grant ID, and find the ID of the calendar you want to work with, and use that.
34 | - Use the `primary` parameter to specify the main calendar associated with the Grant on the service provider.
35 |   - For virtual calendars, the `primary` calendar is the first calendar created for a grant, and it cannot be deleted.
36 |   - iCloud calendars do not have a `primary` calendar, so you need to query for the ID first.
37 | 
38 | ### New Events endpoints
39 | 
40 | - Send RSVP: [`POST /v3/grants/<NYLAS_GRANT_ID>/events/<EVENT_ID>/send-rsvp`](https://developer.nylas.com/docs/api/v3/ecc/#post-/v3/grants/-grant_id-/events/-event_id-/send-rsvp)
41 | 
42 | ### Migrated Events endpoints
43 | 
44 | - Return all events: `GET /events` → [`GET /v3/grants/<NYLAS_GRANT_ID>/events`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/events)
45 | - Create an event: `POST /events` → [`POST /v3/grants/<NYLAS_GRANT_ID>/events`](https://developer.nylas.com/docs/api/v3/ecc/#post-/v3/grants/-grant_id-/events)
46 | - Return an event: `GET /events/<EVENT_ID>` → [`GET /v3/grants/<NYLAS_GRANT_ID>/events/<EVENT_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/events/-event_id-)
47 | - Update an event: `PUT /events/<EVENT_ID>` → [`PUT /v3/grants/<NYLAS_GRANT_ID>/events/<EVENT_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#put-/v3/grants/-grant_id-/events/-event_id-)
48 | - Delete an event: `DELETE /events/<EVENT_ID>` → [`DELETE /v3/grants/<NYLAS_GRANT_ID>/events/<EVENT_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#delete-/v3/grants/-grant_id-/events/-event_id-)
49 | - Send RSVP: `POST /send-rsvp` → [`POST /v3/grants/<NYLAS_GRANT_ID>/events/<EVENT_ID>/send-rsvp`](https://developer.nylas.com/docs/api/v3/ecc/#post-/v3/grants/-grant_id-/events/-event_id-/send-rsvp)
50 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Email/Labels-Folders/read.md:
--------------------------------------------------------------------------------

```markdown
  1 | ### Get all folders
  2 | 
  3 | `GET /folders`, `GET /labels` → [`GET /v3/grants/<NYLAS_GRANT_ID>/folders`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/folders)
  4 | 
  5 | ```Node
  6 | import 'dotenv/config'
  7 | import Nylas from 'nylas'
  8 | 
  9 | const NylasConfig = {
 10 |   apiKey: process.env.NYLAS_API_KEY,
 11 |   apiUri: process.env.NYLAS_API_URI,
 12 | }
 13 | 
 14 | const nylas = new Nylas(NylasConfig)
 15 | 
 16 | async function fetchFolders() {
 17 |  try {
 18 |     const folders = await nylas.folders.list({
 19 |       identifier: process.env.NYLAS_GRANT_ID,
 20 |     })
 21 | 
 22 |     console.log('folders:', folders)
 23 |  } catch (error) {
 24 |    console.error('Error fetching folders:', error)
 25 |  }
 26 | }
 27 | 
 28 | fetchFolders()
 29 | ```
 30 | 
 31 | ```Java
 32 | import com.nylas.NylasClient;
 33 | import com.nylas.models.*;
 34 | 
 35 | public class ReturnFolders {
 36 |   public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
 37 |     NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
 38 | 
 39 |     ListResponse<Folder> folders = nylas.folders().list("<NYLAS_GRANT_ID>");
 40 | 
 41 |     for(Folder folder : folders.getData()){
 42 |       System.out.println(folder.getId() + " | " + folder.getName());
 43 |     }
 44 |   }
 45 | }
 46 | ```
 47 | 
 48 | ```Python
 49 | from dotenv import load_dotenv
 50 | load_dotenv()
 51 | 
 52 | import os
 53 | import sys
 54 | from nylas import Client
 55 | 
 56 | nylas = Client(
 57 |     os.environ.get('NYLAS_API_KEY'),
 58 |     os.environ.get('NYLAS_API_URI')
 59 | )
 60 | 
 61 | grant_id = os.environ.get("NYLAS_GRANT_ID")
 62 | folder_id = os.environ.get("FOLDER_ID")
 63 | 
 64 | folder = nylas.folders.list(
 65 |     grant_id
 66 | )
 67 | 
 68 | print(folder)
 69 | ```
 70 | 
 71 | ```Ruby
 72 | require 'nylas'
 73 | 
 74 | nylas = Nylas::Client.new(
 75 |     api_key: "<NYLAS_API_KEY>"
 76 | )
 77 | 
 78 | folders, _ = nylas.folders.list(identifier: "<NYLAS_GRANT_ID>")
 79 | 
 80 | folders.each { |folder|
 81 |   puts "#{folder[:id]} | #{folder[:name]}"
 82 | }
 83 | 
 84 | ```
 85 | 
 86 | ```API
 87 | curl --request GET \
 88 |   --url https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/folders \
 89 |   --header 'Accept: application/json' \
 90 |   --header 'Authorization: Bearer <NYLAS_API_KEY>' \
 91 |   --header 'Content-Type: application/json'
 92 | ```
 93 | 
 94 | ### Get a specific folder
 95 | 
 96 | `GET /folders/<FOLDER_ID>`, `GET /labels/<LABEL_ID>` → [`GET /v3/grants/<NYLAS_GRANT_ID>/folders/<FOLDER_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/folders/-folder_id-)
 97 | 
 98 | ```Node
 99 | import 'dotenv/config'
100 | import Nylas from 'nylas'
101 | 
102 | const NylasConfig = {
103 |   apiKey: process.env.NYLAS_API_KEY,
104 |   apiUri: process.env.NYLAS_API_URI,
105 | }
106 | 
107 | const nylas = new Nylas(NylasConfig)
108 | 
109 | async function fetchFolderById() {
110 |   try {
111 |     const folder = await nylas.folders.find({
112 |       identifier: process.env.NYLAS_GRANT_ID,
113 |       folderId: process.env.FOLDER_ID,
114 |     })
115 | 
116 |     console.log('Folder:', folder)
117 |   } catch (error) {
118 |     console.error('Error fetching folder:', error)
119 |   }
120 | }
121 | 
122 | fetchFolderById()
123 | ```
124 | 
125 | ```Java
126 | import com.nylas.NylasClient;
127 | import com.nylas.models.*;
128 | 
129 | public class GetLabel {
130 |   public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
131 |     Dotenv dotenv = Dotenv.load();
132 |     NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
133 |     Response<Folder> folder = nylas.folders().find(dotenv.get("NYLAS_GRANT_ID"), "<FOLDER_ID>");
134 |     
135 |     System.out.println(folder);
136 |   }
137 | }
138 | ```
139 | 
140 | ```Python
141 | from dotenv import load_dotenv
142 | load_dotenv()
143 | 
144 | import os
145 | import sys
146 | from nylas import Client
147 | 
148 | nylas = Client(
149 |     os.environ.get('NYLAS_API_KEY'),
150 |     os.environ.get('NYLAS_API_URI')
151 | )
152 | 
153 | grant_id = os.environ.get("NYLAS_GRANT_ID")
154 | folder_id = os.environ.get("FOLDER_ID")
155 | 
156 | message = nylas.folders.find(
157 |     grant_id,
158 |     folder_id,
159 | )
160 | 
161 | print(message)
162 | ```
163 | 
164 | ```Ruby
165 | require 'nylas'
166 | 
167 | nylas = Nylas::Client.new(
168 |     api_key: ENV["NYLAS_API_KEY"]
169 | )
170 | 
171 | folder, _ = nylas.folders.find(identifier: ENV["NYLAS_GRANT_ID"], folder_id: "<FOLDER_ID>")
172 | 
173 | puts folder
174 | ```
175 | 
176 | ```API
177 | curl --request GET \
178 |   --url https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/folders/<FOLDER_ID> \
179 |   --header 'Accept: application/json' \
180 |   --header 'Authorization: Bearer <NYLAS_API_KEY>' \
181 |   --header 'Content-Type: application/json'
182 | ```
183 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Email/Outbox/read.md:
--------------------------------------------------------------------------------

```markdown
  1 | ### Get all scheduled messages
  2 | 
  3 | `GET /outbox` → [`GET /v3/grants/{grant_id}/messages/schedules`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/messages/schedules)
  4 | 
  5 | ```Node
  6 | import 'dotenv/config'
  7 | import Nylas from 'nylas'
  8 | const NylasConfig = {
  9 |   apiKey: process.env.NYLAS_API_KEY,
 10 |   apiUri: process.env.NYLAS_API_URI,
 11 | }
 12 | 
 13 | const nylas = new Nylas(NylasConfig)
 14 | 
 15 | async function fetchMessageSchedules() {
 16 |   try {
 17 |     const identifier: string = process.env.NYLAS_GRANT_ID
 18 |     const messageSchedules = await nylas.messages.listScheduledMessages({
 19 |       identifier,
 20 |     })
 21 | 
 22 |     console.log('Message Schedules:', messageSchedules)
 23 |   } catch (error) {
 24 |     console.error('Error fetching message schedules:', error)
 25 |   }
 26 | }
 27 | 
 28 | fetchMessageSchedules()
 29 | ```
 30 | 
 31 | ```Java
 32 | import com.nylas.NylasClient;
 33 | import com.nylas.models.*;
 34 | 
 35 | public class ReturnMessage {
 36 |   public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
 37 |     NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
 38 |     Response<ScheduledMessagesList> message = nylas.messages().listScheduledMessages("<NYLAS_GRANT_ID>");
 39 |     
 40 |     System.out.println(message.getData());
 41 |   }
 42 | }
 43 | ```
 44 | 
 45 | ```Python
 46 | from dotenv import load_dotenv
 47 | load_dotenv()
 48 | 
 49 | import os
 50 | import sys
 51 | from nylas import Client
 52 | 
 53 | nylas = Client(
 54 |     os.environ.get('NYLAS_API_KEY'),
 55 |     os.environ.get('NYLAS_API_URI')
 56 | )
 57 | 
 58 | grant_id = os.environ.get("NYLAS_GRANT_ID")
 59 | 
 60 | messages = nylas.messages.list_scheduled_messages(
 61 |     grant_id
 62 | )
 63 | 
 64 | print(messages)
 65 | ```
 66 | 
 67 | ```Ruby
 68 | require 'nylas'
 69 | 
 70 | nylas = Nylas::Client.new(
 71 |     api_key: "<NYLAS_API_KEY>"
 72 | )
 73 | 
 74 | messages, _ = nylas.messages.list_scheduled_messages(identifier: ENV["NYLAS_GRANT_ID"])
 75 | 
 76 | messages.each {|message|
 77 |   puts message
 78 | }
 79 | ```
 80 | 
 81 | ```API
 82 | curl --request GET \
 83 |   --url 'https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/messages/schedules' \
 84 |   --header 'Accept: application/json' \
 85 |   --header 'Authorization: Bearer <NYLAS_API_KEY>'
 86 | ```
 87 | 
 88 | ### Get a specific scheduled message
 89 | 
 90 | You can use the [`GET /v3/grants/<NYLAS_GRANT_ID>/messages/schedules/<SCHEDULE_ID>` endpoint](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/messages/schedules/-scheduleId-) to get a specific scheduled email message.
 91 | 
 92 | ```Node
 93 | import "dotenv/config";
 94 | import Nylas from "nylas";
 95 | 
 96 | const NylasConfig = {
 97 |   apiKey: process.env.NYLAS_API_KEY,
 98 |   apiUri: process.env.NYLAS_API_URI,
 99 | };
100 | 
101 | const nylas = new Nylas(NylasConfig);
102 | 
103 | async function fetchScheduledMessageById() {
104 |   try {
105 |     const events = await nylas.messages.findScheduledMessage({
106 |       identifier: process.env.NYLAS_GRANT_ID,
107 |       scheduleId: process.env.SCHEDULE_ID,
108 |     });
109 | 
110 |     console.log("Events:", events);
111 |   } catch (error) {
112 |     console.error("Error fetching calendars:", error);
113 |   }
114 | }
115 | 
116 | fetchScheduledMessageById();
117 | ```
118 | 
119 | ```Java
120 | import com.nylas.NylasClient;
121 | import com.nylas.models.*;
122 | 
123 | public class ReturnMessage {
124 |   public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
125 |     NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
126 | 
127 |     Response<ScheduledMessage> message = nylas.messages().findScheduledMessage(
128 |         "<NYLAS_GRANT_ID>", 
129 |         "<SCHEDULED_MESSAGE_ID>");
130 |         
131 |     System.out.println(message.getData());
132 |   }
133 | }
134 | ```
135 | 
136 | ```Python
137 | from dotenv import load_dotenv
138 | load_dotenv()
139 | 
140 | import os
141 | import sys
142 | from nylas import Client
143 | 
144 | nylas = Client(
145 |     os.environ.get('NYLAS_API_KEY'),
146 |     os.environ.get('NYLAS_API_URI')
147 | )
148 | 
149 | grant_id = os.environ.get("NYLAS_GRANT_ID")
150 | schedule_id = os.environ.get("SCHEDULE_ID")
151 | 
152 | event = nylas.messages.find_scheduled_message(
153 |     grant_id,
154 |     schedule_id,
155 | )
156 | 
157 | print(event)
158 | ```
159 | 
160 | ```Ruby
161 | require 'nylas'
162 | 
163 | nylas = Nylas::Client.new(
164 |     api_key: "<NYLAS_API_KEY>"
165 | )
166 | 
167 | messages, _ = nylas.messages.find_scheduled_messages(
168 |     identifier: ENV["NYLAS_GRANT_ID"], 
169 |     schedule_id: "<SCHEDULE_ID>")
170 | 
171 | messages.each {|message|
172 |   puts message
173 | }
174 | ```
175 | 
176 | ```API
177 | curl --request GET \
178 |   --url 'https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/messages/schedules/<SCHEDULE_ID>' \
179 |   --header 'Accept: application/json' \
180 |   --header 'Authorization: Bearer <NYLAS_API_KEY>'
181 | ```
182 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Email/Drafts/read.md:
--------------------------------------------------------------------------------

```markdown
  1 | ### Get all drafts
  2 | 
  3 | `GET /drafts` → [`GET /v3/grants/<NYLAS_GRANT_ID>/drafts`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/drafts)
  4 | 
  5 | ```API
  6 | curl --request GET \
  7 |   --url 'https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/drafts' \
  8 |   --header 'Authorization: Bearer <NYLAS_API_KEY>' \
  9 |   --header 'Content-Type: application/json'
 10 | ```
 11 | 
 12 | ```Node
 13 | import 'dotenv/config'
 14 | import Nylas from 'nylas'
 15 | 
 16 | const NylasConfig = {
 17 |   apiKey: process.env.NYLAS_API_KEY,
 18 |   apiUri: process.env.NYLAS_API_URI,
 19 | }
 20 | 
 21 | const nylas = new Nylas(NylasConfig)
 22 | 
 23 | async function fetchDrafts() {
 24 |   try {
 25 |     const identifier = process.env.NYLAS_GRANT_ID
 26 | 
 27 |     const threads = await nylas.drafts.list({
 28 |       identifier,
 29 |     })
 30 | 
 31 |     console.log('Recent Drafts:', threads)
 32 |   } catch (error) {
 33 |     console.error('Error fetching drafts:', error)
 34 |   }
 35 | }
 36 | 
 37 | fetchDrafts()
 38 | ```
 39 | 
 40 | ```Ruby
 41 | require 'nylas'
 42 | 
 43 | nylas = Nylas::Client.new(
 44 |     api_key: "<NYLAS_API_KEY>"
 45 | )
 46 | 
 47 | drafts, _ = nylas.drafts.list(identifier: "<NYLAS_GRANT_ID>")
 48 | 
 49 | drafts.each {|draft|
 50 |   puts "[#{Time.at(draft[:date]).strftime("%d/%m/%Y at %H:%M:%S")}] | \
 51 |       #{draft[:id]} | \
 52 |       #{draft[:subject]} | \
 53 |       #{draft[:folders]}"
 54 | }
 55 | ```
 56 | 
 57 | ```Python
 58 | from dotenv import load_dotenv
 59 | load_dotenv()
 60 | 
 61 | import os
 62 | import sys
 63 | from nylas import Client
 64 | 
 65 | nylas = Client(
 66 |     os.environ.get('NYLAS_API_KEY'),
 67 |     os.environ.get('NYLAS_API_URI')
 68 | )
 69 | 
 70 | grant_id = os.environ.get("NYLAS_GRANT_ID")
 71 | 
 72 | drafts = nylas.drafts.list(
 73 |     grant_id,
 74 | )
 75 | 
 76 | print(drafts)
 77 | ```
 78 | 
 79 | ```Java
 80 | import com.nylas.NylasClient;
 81 | import com.nylas.models.*;
 82 | import java.text.SimpleDateFormat;
 83 | 
 84 | public class ListDraft {
 85 |   public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
 86 |     NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
 87 |     ListResponse<Draft> drafts = nylas.drafts().list("<NYLAS_GRANT_ID>");
 88 | 
 89 |     for (Draft draft : drafts.getData()){
 90 |       String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date((draft.getDate() * 1000L)));
 91 | 
 92 |       System.out.printf("[ %s] | %s | %s | %s", date, draft.getId(), draft.getSubject(), draft.getFolders());
 93 |     }
 94 |   }
 95 | }
 96 | ```
 97 | 
 98 | ### Get a specific draft
 99 | 
100 | `GET /drafts/<DRAFT_ID>` → [`GET /v3/grants/<NYLAS_GRANT_ID>/drafts/<DRAFT_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/drafts/-draft_id-)
101 | 
102 | ```API
103 | curl --request GET \
104 |   --url https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/drafts/<DRAFT_ID> \
105 |   --header 'Authorization: Bearer <NYLAS_API_KEY>' \
106 |   --header 'Content-Type: application/json'
107 | ```
108 | 
109 | ```Node
110 | import 'dotenv/config'
111 | import Nylas from 'nylas'
112 | 
113 | const NylasConfig = {
114 |   apiKey: process.env.NYLAS_API_KEY,
115 |   apiUri: process.env.NYLAS_API_URI,
116 | }
117 | 
118 | const nylas = new Nylas(NylasConfig)
119 | 
120 | async function fetchDraftById() {
121 |   try {
122 |     const events = await nylas.drafts.find({
123 |       identifier: process.env.NYLAS_GRANT_ID,
124 |       draftId: process.env.DRAFT_ID,
125 |     })
126 | 
127 |     console.log('Events:', events)
128 |   } catch (error) {
129 |     console.error('Error fetching calendars:', error)
130 |   }
131 | }
132 | 
133 | fetchDraftById()
134 | ```
135 | 
136 | ```Ruby
137 | require 'dotenv/load'
138 | require 'nylas'
139 | 
140 | nylas = Nylas::Client.new(
141 |     api_key: "<NYLAS_API_KEY>"
142 | )
143 | 
144 | draft, _ = nylas.drafts.find(identifier: ENV["NYLAS_GRANT_ID"], draft_id: "<DRAFT_ID>")
145 | 
146 | puts draft
147 | ```
148 | 
149 | ```Python
150 | from dotenv import load_dotenv
151 | load_dotenv()
152 | 
153 | import os
154 | import sys
155 | from nylas import Client
156 | 
157 | nylas = Client(
158 |     os.environ.get('NYLAS_API_KEY'),
159 |     os.environ.get('NYLAS_API_URI')
160 | )
161 | 
162 | grant_id = os.environ.get("NYLAS_GRANT_ID")
163 | draft_id = os.environ.get("DRAFT_ID")
164 | 
165 | draft = nylas.drafts.find(
166 |     grant_id,
167 |     draft_id,
168 | )
169 | 
170 | print(draft)
171 | ```
172 | 
173 | ```Java
174 | import com.nylas.NylasClient;
175 | import com.nylas.models.*;
176 | 
177 | public class ListDraft {
178 |   public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
179 |     NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
180 |     Response<Draft> draft = nylas.drafts().find("<NYLAS_GRANT_ID>", "<DRAFT_ID>");
181 | 
182 |     assert draft.getData().getTo() != null;
183 | 
184 |     System.out.printf(" %s | %s | %s",
185 |         draft.getData().getId(),
186 |         draft.getData().getTo().get(0).getEmail(),
187 |         draft.getData().getSubject());
188 |   }
189 | }
190 | ```
191 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Calendar/Virtual-Calendars/index.md:
--------------------------------------------------------------------------------

```markdown
 1 | Virtual Calendars are much the same in Nylas v3, except that virtual calendars can now have a `primary` calendar, and can have up to 10 total calendars per account, and [a few other improvements](#general-changes-to-virtual-calendars).
 2 | 
 3 | Virtual calendars use the new v3 Nylas Calendar and Events APIs, and all Calendar-related endpoint changes in v3 API also apply to virtual calendars. To upgrade these APIs, use the Upgrade Calendar APIs instructions.
 4 | 
 5 | ## Virtual calendar schema changes
 6 | 
 7 | The schema for the underlying virtual account has changed. The client ID is now passed in the API request, the `scopes` and `name` fields have been removed, the `provider` is now `virtual-calendar`, and the `email` string is now inside the `settings`.
 8 | 
 9 | ```
10 | {  //v2 virtual calendar account
11 |   "client_id": "3",
12 |   "provider": "nylas",
13 |   "scopes": "calendar",
14 |   "email": "virtual_account_unique_id",
15 |   "name": "Virtual Calendar",
16 |   "settings": {}
17 | }
18 | ```
19 | 
20 | ```
21 | { //v3 virtual calendar account
22 |   "provider": "virtual-calendar",
23 |   "settings": {
24 |   "email": "virtual_account_unique_id" //a human-readable ID
25 |   }
26 | }
27 | ```
28 | 
29 | When you make new virtual accounts in the future, make sure the `email` string provides a clear description for the virtual account.
30 | 
31 | ## Migrate virtual calendar data to v3
32 | 
33 | You can start by migrating your virtual calendar data to v3 to help you upgrade the rest of your project code. Start with a dev or test application so you don't disturb your production users.
34 | 
35 | Migrated virtual calendar event and calendar object IDs don't change. You can use the same IDs to reference the same events and calendars in your v3 app. Migrated virtual accounts keep the `email` from the v2 version, but are converted to a grant. Use the grant ID for the virtual account's grant to locate its calendar and event data.
36 | 
37 | When you're ready for your users to start switching to the v3 version, you can re-run the migration tool to catch up on any new or changed data since the initial sync.
38 | 
39 | ### Changes to virtual calendar data during migration
40 | 
41 | The migration tool looks at your v2 virtual calendar data, transforms it into the v3 format, and copies it to the v3 systems. You can expect the following changes:
42 | 
43 | - When you migrate virtual calendar data using the [Nylas migration API](/docs/api/v3/migration/), Nylas saves the content of the `name` and `organizer` fields to the grant's metadata. If you need access to this metadata, contact Nylas Support.
44 | - Other metadata from v2 is not migrated to v3.
45 | - The v2 virtual account `name` and v2 event `organizer` are not supported in v3 Virtual Calendars. The v3 equivalent for the `organizer` field is the `email` string that you set when you created the virtual calendar.
46 | - The `created_at` and `updated_at` timestamps are be updated for all events and calendars during migration.
47 | - In v2, when a VC event is deleted, it was marked as `status=cancelled`, considered a soft delete. In v3, however, events are permanently deleted immediately.
48 | - The v2 recurrence timezone is now part of the `when` property of v3 events. Timezones are not available for all-day events in v3, so Nylas drops the timezone when converting v2 all-day events to v3 format.
49 | - The `read_only` field in v3 Virtual Calendars is always set to `null`.
50 | - Reminders are not supported in v3 Virtual Calendars and are not migrated.
51 | 
52 | ## General changes to virtual calendars
53 | 
54 | - Virtual calendars are no longer limited to one calendar per account (now called a grant). You can now have up to 10 calendars per grant, and you can still create as many grants as you need. You are still billed per grant.
55 | - You create new grants using Custom auth and the `virtual-calendar` provider.
56 | - In v3 new virtual accounts are created without any calendars so you can specify the `email` identifier and control which is set as `primary`. Create new virtual calendars for each grant using the `POST /v3/calendars` endpoint.
57 | - You must provide an identifier when you create the Grant for virtual calendars. Previously this was optional. This can be any arbitrary string, and no longer needs to be in email address format.
58 | - In v3 Nylas can set one calendar per account as the "primary" calendar, and you can use the word `primary` instead of a `calendar_id` in Calendar API calls. In virtual calendars, the `primary` calendar is the first calendar created for a grant. Once created, that first calendar cannot be deleted.
59 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Auth/AdminConsent-Bulk/index.md:
--------------------------------------------------------------------------------

```markdown
 1 | You can use connector credentials for bulk authentication with Microsoft's Admin Consent flow. What are connector credentials, I hear you asking? They're new in v3, read on...
 2 | 
 3 | #### Introducing connector credentials
 4 | 
 5 | Nylas v3 includes "credentials", which are packages of information that you can use when authenticating to override default connector settings and auth methods. You might use this if you're using more than one Azure auth app to authenticate your end users.
 6 | 
 7 | You can create credentials for alternate Azure auth apps, which include the app's `client_id` and `client_secret`, and any other connection settings. Nylas encrypts and stores this information securely in a credential record. You then refer to the record in Custom auth requests using the `credential_id`. This allows you to authenticate end users with the non-default Azure auth app.
 8 | 
 9 | Connector credentials are linked to a specific connector in a specific Nylas application. If you created the connector credential for a specific Microsoft connector, you can't use the `credential_id` for a different connector, or with a different Nylas application.
10 | 
11 | ### Bulk authentication with Microsoft Admin Consent
12 | 
13 | You can use connector credentials for bulk authentication with Microsoft's "Admin consent" system. To do this, first [create an Azure auth app](https://developer.nylas.com/docs/dev-guide/provider-guides/microsoft/create-azure-app/), then open the app in the Azure Dashboard and configure it:
14 | 
15 | 1. From the **Authentication** tab, add a platform and set its **redirect URI**.
16 | 2. Select **Certificates & secrets** and create a `client_secret`. Be sure to save it somewhere secure — the Dashboard only shows the value once!
17 | 3. Under **API permissions**, add all Microsoft Graph scopes that your project needs access to.
18 |     - You don't need to select **Grant admin consent**. You add this later using a special Nylas authorization API call.
19 | 4. Select **Manifest** and add the following values:
20 |     - `"accessTokenAcceptedVersion": 2`
21 |     - `"signInAudience": "AzureADandPersonalMicrosoftAccount"`
22 | 
23 | #### Microsoft Service Accounts
24 | 
25 | Nylas v3 supports two versions of Microsoft's Service Accounts:
26 | 
27 | - **Version 1.0**: The _older_ version, where every scope defined in your Azure auth app is required during the authorization step of the Admin Consent flow. The `tenant` definition is optional, and Nylas uses `"tenant": "common"` if it's not defined.
28 | - **Version 2.0**: The _new_ version, where scopes are defined for the Admin Consent flow only. All requested scopes must still be defined in your Azure auth app, and you must specify the exact `tenant` (v2.0 doesn't support `"tenant": "common"`).
29 | 
30 | Nylas automatically determines which version of the Admin Consent flow to use.
31 | 
32 | #### Prepare for Admin Consent flow
33 | 
34 | Before you begin, [set up a Microsoft connector](https://developer.nylas.com/docs/dev-guide/provider-guides/microsoft/create-azure-app/#add-a-microsoft-connector-to-nylas). Then, prepare your Nylas application for the Microsoft Admin Consent flow.
35 | 
36 | 1. Make a [`POST /v3/connectors/<PROVIDER>/creds` request](https://developer.nylas.com/docs/api/v3/admin/#post-/v3/connectors/-provider-/creds) to create a connector credential. The request must include the `client_id` and `client_secret` for your provider auth app, and can include a `tenant`.
37 |     - If you don't define the `client_id` and `client_secret`, Nylas uses the credentials associated with your application's Microsoft connector.
38 |     - If you define the `tenant`, Nylas attempts to use Microsoft's Admin Consent flow v2.0.
39 | 2. Nylas returns a JSON response with the `id` of the new connector credential. Be sure to save it somewhere secure.
40 | 
41 | #### Make an Admin Consent flow request
42 | 
43 | Now you can make a request to use the Microsoft Admin Consent flow with the Nylas APIs.
44 | 
45 | 1. Make a [`GET /v3/connect/auth` request](https://developer.nylas.com/docs/api/v3/admin/#get-/v3/connect/auth) and set `response_type` to `adminconsent`, and `credential_id` to the ID of the connector credential you created.
46 | 2. Nylas redirects the Service Account to the redirect URI. The response URL contains `admin_consent:true` and the contents of the `state`, if defined.
47 |     - If the flow isn't successful, Nylas returns a normal OAuth 2.0 error.
48 | 3. Make a [`POST /v3/connect/custom` request](https://developer.nylas.com/docs/api/v3/admin/#post-/v3/connect/custom) to create a grant for the Service Account.
49 | 4. Nylas returns a JSON response containing the grant's information.
50 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Email/Threads/write.md:
--------------------------------------------------------------------------------

```markdown
  1 | ### Update a specific thread
  2 | 
  3 | `PUT /threads/<THREAD_ID>` → [`PUT /v3/grants/<NYLAS_GRANT_ID>/threads/<THREAD_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#put-/v3/grants/-grant_id-/threads/-thread_id-)
  4 | 
  5 | ```Node
  6 | import 'dotenv/config'
  7 | import Nylas from 'nylas'
  8 | 
  9 | const NylasConfig = {
 10 |   apiKey: process.env.NYLAS_API_KEY,
 11 |   apiUri: process.env.NYLAS_API_URI,
 12 | }
 13 | 
 14 | const nylas = new Nylas(NylasConfig)
 15 | 
 16 | async function updateThread() {
 17 |   try {
 18 |     const calendar = await nylas.threads.update({
 19 |       identifier: process.env.NYLAS_GRANT_ID,
 20 |       threadId: process.env.THREAD_ID,
 21 |       requestBody: {
 22 |         starred: true
 23 |       }
 24 |     })
 25 | 
 26 |     console.log('Updated Thread:', calendar)
 27 |   } catch (error) {
 28 |     console.error('Error to update thread:', error)
 29 |   }
 30 | }
 31 | 
 32 | updateThread()
 33 | ```
 34 | 
 35 | ```Java
 36 | import com.nylas.NylasClient;
 37 | import com.nylas.models.*;
 38 | import com.nylas.models.Thread;
 39 | 
 40 | public class UpdateThread {
 41 |   public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
 42 |     NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
 43 | 
 44 |     UpdateThreadRequest requestBody = new UpdateThreadRequest.
 45 |         Builder().
 46 |         unread(true).
 47 |         starred(true).
 48 |         build();
 49 | 
 50 |     Response<Thread> draft = nylas.threads().update("<NYLAS_GRANT_ID>", "<THREAD_ID>", requestBody);
 51 |     
 52 |     System.out.printf("%s%s%s%n",
 53 |         draft.getData().getId(),
 54 |         draft.getData().getUnread(),
 55 |         draft.getData().getStarred()
 56 |     );
 57 |   }
 58 | }
 59 | ```
 60 | 
 61 | ```Python
 62 | from dotenv import load_dotenv
 63 | load_dotenv()
 64 | 
 65 | import os
 66 | import sys
 67 | from nylas import Client
 68 | 
 69 | nylas = Client(
 70 |     os.environ.get('NYLAS_API_KEY'),
 71 |     os.environ.get('NYLAS_API_URI')
 72 | )
 73 | 
 74 | grant_id = os.environ.get("NYLAS_GRANT_ID")
 75 | 
 76 | thread = nylas.threads.update(
 77 |     grant_id,
 78 |     thread_id=os.environ.get("THREAD_ID"),
 79 |     request_body={
 80 |       "starred": True
 81 |     }
 82 | )
 83 | 
 84 | print(thread)
 85 | ```
 86 | 
 87 | ```Ruby
 88 | require 'nylas' 
 89 | 
 90 | nylas = Nylas::Client.new(
 91 |     api_key: "<NYLAS_API_KEY>"
 92 | )
 93 | 
 94 | request_body = {
 95 |   unread: true,
 96 |   starred: true
 97 | }
 98 | 
 99 | thread, _ = nylas.threads.update(identifier: "<NYLAS_GRANT_ID>", 
100 |     thread_id: "<THREAD_ID>",
101 |     request_body: request_body)
102 | 
103 | puts thread
104 | ```
105 | 
106 | ```API
107 | curl --request PUT \
108 |   --url https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/threads/<THREAD_ID>\
109 |   --header 'Accept: application/json' \
110 |   --header 'Authorization: Bearer <NYLAS_API_KEY>' \
111 |   --header 'Content-Type: application/json' \
112 |   --data '{
113 |     "unread": true,
114 |     "starred": false,
115 |     "folders": [
116 |       "<FOLDER_ID>",
117 |       "<FOLDER_ID>"
118 |     ]
119 |   }'
120 | ```
121 | 
122 | ### Delete a thread
123 | 
124 | [`DELETE /v3/grants/<NYLAS_GRANT_ID>/threads/<THREAD_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#delete-/v3/grants/-grant_id-/threads/-thread_id-)
125 | 
126 | ```Node
127 | import 'dotenv/config'
128 | import Nylas from 'nylas'
129 | 
130 | const NylasConfig = {
131 |   apiKey: process.env.NYLAS_API_KEY,
132 |   apiUri: process.env.NYLAS_API_URI,
133 | }
134 | 
135 | const nylas = new Nylas(NylasConfig)
136 | const identifier = process.env.NYLAS_GRANT_ID
137 | const threadId = process.env.THREAD_ID
138 | 
139 | const deleteThread = async () => {
140 |   try {
141 |     await nylas.threads.destroy({ identifier, threadId })
142 |     console.log(`Thread with ID ${threadId} deleted successfully.`)
143 |   } catch (error) {
144 |     console.error(`Error deleting thread with ID ${threadId}:`, error)
145 |   }
146 | }
147 | 
148 | deleteThread()
149 | ```
150 | 
151 | ```Java
152 | import com.nylas.NylasClient;
153 | import com.nylas.models.*;
154 | import com.nylas.models.Thread;
155 | 
156 | public class ReturnThread {
157 |   public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
158 |     NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
159 |     DeleteResponse thread = nylas.threads().destroy("<NYLAS_GRANT_ID>", "<THREAD_ID>");
160 | 
161 |     System.out.println(thread);
162 |   }
163 | }
164 | ```
165 | 
166 | ```Python
167 | from dotenv import load_dotenv
168 | load_dotenv()
169 | 
170 | import os
171 | import sys
172 | from nylas import Client
173 | 
174 | nylas = Client(
175 |     os.environ.get('NYLAS_API_KEY'),
176 |     os.environ.get('NYLAS_API_URI')
177 | )
178 | 
179 | grant_id = os.environ.get("NYLAS_GRANT_ID")
180 | thread_id = os.environ.get("THREAD_ID")
181 | 
182 | request = nylas.threads.destroy(
183 |     grant_id,
184 |     thread_id,
185 | )
186 | 
187 | print(request)
188 | ```
189 | 
190 | ```Ruby
191 | require 'nylas' 
192 | 
193 | nylas = Nylas::Client.new(
194 |     api_key: "<NYLAS_API_KEY>"
195 | )
196 | 
197 | thread, _ = nylas.threads.destroy(identifier: "<NYLAS_GRANT_ID>", thread_id: "<THREAD_ID>")
198 | 
199 | puts thread
200 | ```
201 | 
202 | ```API
203 | curl --request DELETE \
204 |   --url https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/threads/<THREAD_ID> \
205 |   --header 'Accept: application/json' \
206 |   --header 'Authorization: Bearer <NYLAS_API_KEY>' \
207 |   --header 'Content-Type: application/json'
208 | ```
209 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Auth/Native-Custom/index.md:
--------------------------------------------------------------------------------

```markdown
  1 | Nylas v3 preserves Native authentication ("Bring your own token") almost unchanged, but renames it "Custom authentication". If you already have a refresh token (or credentials, if using IMAP) for your end users from your own authentication implementation, you can use it with the Nylas APIs to create a grant and get the `grant_id`, which you then use in requests to the provider.
  2 | 
  3 | ### Upgrading Native authentication to Custom authentication
  4 | 
  5 | If you used Native auth in Nylas v2.x, the only changes are to the Nylas API URLs, the requirement that you create a connector (previously called an "integration") for your application, and the change from token authentication to bearer-token authentication.
  6 | 
  7 | The v3 requests now go through a connector, which can supply some of the provider details. This makes your [v3 Custom auth requests](https://developer.nylas.com/docs/api/v3/admin/#post-/v3/connect/custom) much simpler: you now pass the provider and request token, and can include scopes overrides and a state.
  8 | 
  9 | See [Creating grants with Custom authentication](https://developer.nylas.com/docs/v3/auth/custom/) for more details.
 10 | 
 11 | ### Migrated endpoints
 12 | 
 13 | - Native auth → Custom auth: `POST /connect/token` → [`POST /v3/connect/custom`](https://developer.nylas.com/docs/api/v3/admin/#post-/v3/connect/custom)
 14 | 
 15 | ### Removed Connect endpoints
 16 | 
 17 | - Native auth - Exchange Token: `POST /connect/token`
 18 | 
 19 | ### Create a grant using a Custom authentication flow
 20 | 
 21 | `POST /auth` → [`POST /v3/connect/custom`](https://developer.nylas.com/docs/api/v3/admin/#post-/v3/connect/custom)
 22 | 
 23 | ```Node
 24 | import 'dotenv/config';
 25 | import Nylas from 'nylas';
 26 | 
 27 | const NylasConfig = {
 28 |   apiKey: process.env.NYLAS_API_KEY as string,
 29 |   apiUri: process.env.NYLAS_API_URI as string,
 30 | };
 31 | 
 32 | // gpt: does not initialize Nylas SDK, was using string
 33 | const nylas = new Nylas(NylasConfig);
 34 | 
 35 | async function customAuthentication() {
 36 |   const auth = await nylas.auth.customAuthentication({
 37 |     requestBody: {
 38 |       provider: "<PROVIDER>",
 39 |       settings: {
 40 |         username: "<USERNAME>",
 41 |         password: "<PASSWORD>"
 42 |       },
 43 |       state: "<STATE>",
 44 |       scope: ["email.read_only", "calendar.read_only", "contacts.read_only"],
 45 |     }
 46 |   })
 47 |   console.log({ auth });
 48 | }
 49 | 
 50 | await customAuthentication();
 51 | ```
 52 | 
 53 | ```Java
 54 | package org.example;
 55 | 
 56 | import com.nylas.NylasClient;
 57 | import com.nylas.models.*;
 58 | import java.util.ArrayList;
 59 | import java.util.HashMap;
 60 | import java.util.List;
 61 | import java.util.Map;
 62 | 
 63 | public class Main {
 64 |     public static void main(String[] args) throws
 65 |             NylasSdkTimeoutError, NylasApiError {
 66 |         NylasClient nylas = new NylasClient.Builder(<NYLAS_API_KEY>).build();
 67 |         AuthProvider provider = AuthProvider.ICLOUD;
 68 |         Map<String, String> settings = new HashMap<String, String>();
 69 |         settings.put("username","<USERNAME>");
 70 |         settings.put("password","<PASSWORD>");
 71 |         List<String> scope = new ArrayList<String>();
 72 |         scope.add("email.read_only");
 73 |         scope.add("calendar.read_only");
 74 |         scope.add("contacts.read_only");
 75 |         CreateGrantRequest request_body = new CreateGrantRequest(provider,settings, "<STATE>", scope);
 76 |         Response<Grant> auth = nylas.auth().customAuthentication(request_body);
 77 |         System.out.println(auth);
 78 |     }
 79 | }
 80 | 
 81 | ```
 82 | 
 83 | ```Python
 84 | import os
 85 | import sys
 86 | from nylas import Client
 87 | from nylas.models.grants import CreateGrantRequest
 88 | from nylas.models.auth import Provider
 89 | 
 90 | nylas = Client(
 91 |   "<NYLAS_API_KEY>",
 92 |   "<NYLAS_API_URI>"
 93 | )
 94 | 
 95 | request_body = CreateGrantRequest(
 96 | {
 97 |   "provider": "<PROVIDER>",
 98 |   "settings": {"username": "<USERNAME>", "password" : "<PASSWORD>"},
 99 |   "scope": ["email.read_only", "calendar.read_only", "contacts.read_only"],
100 |   "state": "<STATE>"
101 | } 
102 | )
103 | 
104 | auth = nylas.auth.custom_authentication(request_body)
105 | print(auth)
106 | 
107 | ```
108 | 
109 | ```Ruby
110 | # Load gems
111 | require 'dotenv/load'
112 | require 'nylas'
113 | 
114 | # Initialize Nylas client
115 | nylas = Nylas::Client.new(
116 |  api_key: "<NYLAS_API_KEY>"
117 | )
118 | 
119 | # Request body
120 | request_body = {
121 |   provider: '<PROVIDER>',
122 |   settings: {'username': '<USERNAME>', 'password': '<PASSWORD>'},
123 |   scope: 'email.read_only,calendar.read_only,contacts.read_only',
124 |   state: '<STATE>'
125 | }
126 | 
127 | # Call Custom Authentication
128 | auth = nylas.auth.custom_authentication(request_body)
129 | puts auth
130 | ```
131 | 
132 | ```API
133 | curl --request POST \
134 |  --url "https://api.us.nylas.com/v3/connect/custom" \
135 |  --header 'Accept: application/json' \
136 |  --header 'Authorization: Bearer <NYLAS_API_KEY>' \
137 |  -H "accept: application/json"\
138 |  -H "content-type: application/json" \
139 |  -d '{"provider":"<PROVIDER>","settings":{"username":"<USERNAME>","password":"<PASSWORD>"},
140 |       "scope":"email.read_only,calendar.read_only,contacts.read_only"}'
141 | ```
142 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Email/Threads/read.md:
--------------------------------------------------------------------------------

```markdown
  1 | ### Get all threads
  2 | 
  3 | `GET /threads` → [`GET /v3/grants/<NYLAS_GRANT_ID>/threads`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/threads)
  4 | 
  5 | ```Node
  6 | import 'dotenv/config'
  7 | import Nylas from 'nylas'
  8 | 
  9 | const NylasConfig = {
 10 |   apiKey: process.env.NYLAS_API_KEY,
 11 |   apiUri: process.env.NYLAS_API_URI,
 12 | }
 13 | 
 14 | const nylas = new Nylas(NylasConfig)
 15 | 
 16 | async function fetchRecentThreads() {
 17 |   try {
 18 |     const identifier = process.env.NYLAS_GRANT_ID
 19 |     const threads = await nylas.threads.list({
 20 |       identifier,
 21 |       queryParams: {
 22 |         limit: 5,
 23 |       }
 24 |     })
 25 | 
 26 |     console.log('Recent Threads:', threads)
 27 |   } catch (error) {
 28 |     console.error('Error fetching threads:', error)
 29 |   }
 30 | }
 31 | 
 32 | fetchRecentThreads()
 33 | ```
 34 | 
 35 | ```Java
 36 | import com.nylas.NylasClient;
 37 | import com.nylas.models.*;
 38 | import com.nylas.models.Thread;
 39 | 
 40 | public class ReadThreadParameters {
 41 |   public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
 42 |     NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
 43 |     ListThreadsQueryParams queryParams = new ListThreadsQueryParams.Builder().limit(5).build();
 44 |     ListResponse<Thread> threads = nylas.threads().list("<NYLAS_GRANT_ID>", queryParams);
 45 |     int index = 0;
 46 | 
 47 |     for(Thread thread : threads.getData()){
 48 |       System.out.printf("%s ", index);
 49 |       
 50 |       List<EmailName> participants = thread.getParticipants();
 51 |       assert participants != null;
 52 | 
 53 |       for(EmailName participant : participants){
 54 |         System.out.printf("  Subject: %s | Participant: %s | Email: %s%n",
 55 |             thread.getSubject(),
 56 |             participant.getName(),
 57 |             participant.getEmail());
 58 |       }
 59 | 
 60 |       index++;
 61 |     }
 62 |   }
 63 | }
 64 | ```
 65 | 
 66 | ```Python
 67 | from dotenv import load_dotenv
 68 | load_dotenv()
 69 | 
 70 | import os
 71 | import sys
 72 | from nylas import Client
 73 | 
 74 | nylas = Client(
 75 |     os.environ.get('NYLAS_API_KEY'),
 76 |     os.environ.get('NYLAS_API_URI')
 77 | )
 78 | 
 79 | grant_id = os.environ.get("NYLAS_GRANT_ID")
 80 | 
 81 | threads = nylas.threads.list(
 82 |     grant_id,
 83 |     query_params={
 84 |       "limit": 5
 85 |     }
 86 | )
 87 | 
 88 | print(threads)
 89 | ```
 90 | 
 91 | ```Ruby
 92 | require 'nylas'
 93 | 
 94 | nylas = Nylas::Client.new(api_key: "<NYLAS_API_KEY>")
 95 | query_params = { limit: 5 }
 96 | threads, _ = nylas.threads.list(identifier: "<NYLAS_GRANT_ID>", query_params: query_params)
 97 | 
 98 | threads.map.with_index { |thread, i|
 99 |   puts("Thread #{i}")
100 |   participants = thread[:participants]
101 | 
102 |   participants.each{ |participant|
103 |     puts(
104 |         "Subject: #{thread[:subject]} | "\
105 |         "Participant: #{participant[:name]} | "\
106 |         "Email: #{participant[:email]}"
107 |     )
108 |   }
109 | }
110 | ```
111 | 
112 | ```API
113 | curl --request GET \
114 |   --url "https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/threads?limit=5" \
115 |   --header 'Accept: application/json' \
116 |   --header "Authorization: Bearer <NYLAS_API_KEY>' \
117 |   --header 'Content-Type: application/json'
118 | ```
119 | 
120 | ### Get a specific thread
121 | 
122 | `GET /threads/<THREAD_ID>` → [`GET /v3/grants/<NYLAS_GRANT_ID>/threads/<THREAD_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/threads/-thread_id-)
123 | 
124 | ```Node
125 | import 'dotenv/config'
126 | import Nylas from 'nylas'
127 | 
128 | const NylasConfig = {
129 |   apiKey: process.env.NYLAS_API_KEY,
130 |   apiUri: process.env.NYLAS_API_URI,
131 | }
132 | 
133 | const nylas = new Nylas(NylasConfig)
134 | 
135 | async function fetchThreadById(): Promise<void> { 
136 |   try {
137 |     const events = await nylas.threads.find({
138 |       identifier: process.env.NYLAS_GRANT_ID,
139 |       threadId: process.env.THREAD_ID,
140 |     })
141 |   
142 |     console.log('Events:', events)
143 |   } catch (error) {
144 |     console.error('Error fetching calendars:', error)
145 |   }
146 | }
147 | 
148 | fetchThreadById()
149 | ```
150 | 
151 | ```Java
152 | import com.nylas.NylasClient;
153 | import com.nylas.models.*;
154 | import com.nylas.models.Thread;
155 | 
156 | public class ReturnThread {
157 |   public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
158 |     NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
159 |     Response<Thread> thread = nylas.threads().find("<NYLAS_GRANT_ID>", "<THREAD_ID>");
160 | 
161 |     System.out.println(thread);
162 |   }
163 | }
164 | ```
165 | 
166 | ```Python
167 | from dotenv import load_dotenv
168 | load_dotenv()
169 | 
170 | import os
171 | import sys
172 | from nylas import Client
173 | 
174 | nylas = Client(
175 |     os.environ.get('NYLAS_API_KEY'),
176 |     os.environ.get('NYLAS_API_URI')
177 | )
178 | 
179 | grant_id = os.environ.get("NYLAS_GRANT_ID")
180 | thread_id = os.environ.get("THREAD_ID")
181 | 
182 | thread = nylas.threads.find(
183 |     grant_id,
184 |     thread_id,
185 | )
186 | 
187 | print(thread)
188 | ```
189 | 
190 | ```Ruby
191 | require 'nylas' 
192 | 
193 | nylas = Nylas::Client.new(
194 |     api_key: "<NYLAS_API_KEY>"
195 | )
196 | 
197 | thread, _ = nylas.threads.find(identifier: "<NYLAS_GRANT_ID>", thread_id: "<THREAD_ID>")
198 | 
199 | participants = thread[:participants]
200 | 
201 | participants.each{ |participant|
202 |   puts("Id: #{thread[:id]} | "\
203 |       "Subject: #{thread[:subject]} | "\
204 |       "Participant: #{participant[:name]} | "\
205 |       "Email: #{participant[:email]}"
206 |   )
207 | }
208 | ```
209 | 
210 | ```API
211 | curl --request GET \
212 |   --url https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/threads/<THREAD_ID> \
213 |   --header 'Accept: application/json' \
214 |   --header 'Authorization: Bearer <NYLAS_API_KEY>' \
215 |   --header 'Content-Type: application/json'
216 | ```
217 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Email/Files-Attachments/read.md:
--------------------------------------------------------------------------------

```markdown
  1 | ### Get metadata for a specific attachment
  2 | 
  3 | `GET /files/<FILE_ID>` → [`GET /v3/grants/<NYLAS_GRANT_ID>/attachments/<ATTACHMENT_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/attachments/-attachment_id-)
  4 | 
  5 | ```Node
  6 | import 'dotenv/config'
  7 | import Nylas from 'nylas'
  8 | 
  9 | const NylasConfig = {
 10 |   apiKey: process.env.NYLAS_API_KEY,
 11 |   apiUri: process.env.NYLAS_API_URI,
 12 | }
 13 | 
 14 | const nylas = new Nylas(NylasConfig)
 15 | 
 16 | async function fetchAttachmentById() {
 17 |   try {
 18 |     const attachment = await nylas.attachments.find({
 19 |       identifier: process.env.NYLAS_GRANT_ID,
 20 |       attachmentId: process.env.ATTACHMENT_ID,
 21 |       queryParams: {
 22 |         messageId: process.env.MESSAGE_ID,
 23 |       }
 24 |     })
 25 | 
 26 |     console.log('Attachment:', attachment)
 27 |   } catch (error) {
 28 |     console.error('Error fetching attachment:', error)
 29 |   }
 30 | }
 31 | 
 32 | fetchAttachmentById()
 33 | ```
 34 | 
 35 | ```Java
 36 | import com.nylas.NylasClient;
 37 | import com.nylas.models.*;
 38 | 
 39 | public class attachment {
 40 |   public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError, NylasOAuthError {
 41 |     NylasClient nylas = new NylasClient.Builder("NYLAS_API_KEY").build();
 42 |     FindAttachmentQueryParams queryParams = new FindAttachmentQueryParams("<MESSAGE_ID>");
 43 |     Attachment attachment = nylas.attachments().find("<NYLAS_GRANT_ID>", "<ATTACHMENT_ID>", queryParams).getData();
 44 | 
 45 |     System.out.println(attachment);
 46 |   }
 47 | }
 48 | ```
 49 | 
 50 | ```Python
 51 | from dotenv import load_dotenv
 52 | load_dotenv()
 53 | 
 54 | import os
 55 | import sys
 56 | from nylas import Client
 57 | 
 58 | nylas = Client(
 59 |     os.environ.get('NYLAS_API_KEY'),
 60 |     os.environ.get('NYLAS_API_URI')
 61 | )
 62 | 
 63 | grant_id = os.environ.get("NYLAS_GRANT_ID")
 64 | folder_id = os.environ.get("FOLDER_ID")
 65 | attachment_id = os.environ.get("ATTACHMENT_ID")
 66 | 
 67 | attachment = nylas.attachments.find(
 68 |     grant_id,
 69 |     attachment_id,
 70 |     query_params= {
 71 |       "message_id": os.environ.get("MESSAGE_ID"),
 72 |     }
 73 | )
 74 | 
 75 | print(attachment)
 76 | ```
 77 | 
 78 | ```Ruby
 79 | require 'dotenv/load'
 80 | require 'nylas'
 81 | 
 82 | nylas = Nylas::Client.new(
 83 |     api_key: "<NYLAS_API_KEY>"
 84 | )
 85 | 
 86 | query_params = {
 87 |   message_id: "<MESSAGE_ID>"
 88 | }
 89 | 
 90 | attachment = nylas.attachments.find(identifier: "<NYLAS_GRANT_ID>",
 91 |     attachment_id: "<ATTACHMENT_ID>", query_params: query_params)
 92 | 
 93 | puts attachment
 94 | ```
 95 | 
 96 | ```API
 97 | curl --request GET \
 98 |   --url https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/attachments/<ATTACHMENT_ID>?message_id=<MESSAGE_ID> \
 99 |   --header 'Accept: application/json' \
100 |   --header 'Authorization: Bearer <NYLAS_API_KEY>'
101 | ```
102 | 
103 | ### Download a specific attachment
104 | 
105 | `GET /files/<FILE_ID>/download` → [`GET /v3/grants/<NYLAS_GRANT_ID>/attachments/<ATTACHMENT_ID>/download`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/attachments/-attachment_id-/download)
106 | 
107 | ```Node
108 | import 'dotenv/config'
109 | import fs from 'fs'
110 | import Nylas from 'nylas'
111 | 
112 | const NylasConfig = {
113 |   apiKey: process.env.NYLAS_API_KEY,
114 |   apiUri: process.env.NYLAS_API_URI,
115 | }
116 | 
117 | const nylas = new Nylas(NylasConfig)
118 | 
119 | async function downloadAttachment() {
120 |   try {
121 |     const attachmentResponse = await nylas.attachments.download({
122 |       identifier: process.env.NYLAS_GRANT_ID,
123 |       attachmentId: process.env.ATTACHMENT_ID,
124 |       queryParams: {
125 |         messageId: process.env.MESSAGE_ID,
126 |       }
127 |     })
128 | 
129 |     const fileName = 'attachment'
130 | 
131 |     const fileStream = fs.createWriteStream(fileName)
132 |       attachmentResponse.pipe(fileStream)
133 |       fileStream.on('finish', () => {
134 |         console.log(`File saved as ${fileName}`)
135 |       })
136 |   } catch (error) {
137 |     console.error('Error fetching attachment:', error)
138 |   }
139 | }
140 | 
141 | downloadAttachment()
142 | ```
143 | 
144 | ```Java
145 | import com.nylas.NylasClient;
146 | import com.nylas.models.*;
147 | import okhttp3.ResponseBody;
148 | import java.io.FileNotFoundException;
149 | import java.io.FileOutputStream;
150 | import java.io.IOException;
151 | 
152 | public class attachment_download {
153 |   public static void main(String[] args) throws NylasSdkTimeoutError, NylasOAuthError, IOException {
154 |     NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
155 |     FindAttachmentQueryParams queryParams = new FindAttachmentQueryParams("<MESSAGE_ID>");
156 |     ResponseBody attachment = nylas.attachments().download("<NYLAS_GRANT_ID>", "<ATTACHMENT_ID>", queryParams);
157 | 
158 |     try {
159 |       FileOutputStream out = new FileOutputStream("src/main/resources/image.png");
160 | 
161 |       out.write(attachment.bytes());
162 |       out.close();
163 |     } catch (FileNotFoundException e) {
164 |       System.out.println("File not found");
165 |     }
166 |   }
167 | }
168 | ```
169 | 
170 | ```Python
171 | from dotenv import load_dotenv
172 | load_dotenv()
173 | 
174 | import os
175 | from nylas import Client
176 | 
177 | nylas = Client(
178 |     os.environ.get('NYLAS_API_KEY'),
179 |     os.environ.get('NYLAS_API_URI')
180 | )
181 | 
182 | grant_id = os.environ.get("NYLAS_GRANT_ID")
183 | attachment_id = os.environ.get("ATTACHMENT_ID")
184 | 
185 | attachment = nylas.attachments.download(
186 |     grant_id,
187 |     attachment_id,
188 |     query_params= {
189 |       "message_id": os.environ.get("MESSAGE_ID"),
190 |     }
191 | )
192 | 
193 | with open("attachment", 'wb') as f:
194 |   f.write(attachment.content)
195 | ```
196 | 
197 | ```Ruby
198 | require 'dotenv/load'
199 | require 'nylas'
200 | 
201 | nylas = Nylas::Client.new(
202 |     api_key: "<NYLAS_API_KEY>"
203 | )
204 | 
205 | query_params = {
206 |   message_id: "<MESSAGE_ID>"
207 | }
208 | 
209 | attachment = nylas.attachments.download(identifier: "<NYLAS_GRANT_ID">,
210 |     attachment_id: "<ATTACHMENT_ID>", query_params: query_params)
211 | 
212 | File.open("./image.png", "wb") do |file|
213 |   file.write(attachment)
214 | end
215 | ```
216 | 
217 | ```API
218 | curl --request GET \
219 |   --url https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/attachments/<ATTACHMENT_ID>/download?message_id=<MESSAGE_ID> \
220 |   --header 'Authorization: Bearer <NYLAS_API_KEY>'
221 | ```
222 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Email/Messages/read.md:
--------------------------------------------------------------------------------

```markdown
  1 | ### Get all messages
  2 | 
  3 | `GET /messages` → [`GET /v3/grants/<NYLAS_GRANT_ID>/messages`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/messages)
  4 | 
  5 | ```Node
  6 | app.get("/nylas/recent-emails", async (req, res) => {
  7 |   try {
  8 |     const identifier = process.env.USER_GRANT_ID;
  9 |     const messages = await nylas.messages.list({
 10 |       identifier,
 11 |       queryParams: {
 12 |         limit: 5,
 13 |       },
 14 |     });
 15 | 
 16 |     res.json(messages);
 17 |   } catch (error) {
 18 |     console.error("Error fetching emails:", error);
 19 |   }
 20 | });
 21 | ```
 22 | 
 23 | ```Java
 24 | import com.nylas.NylasClient;
 25 | import com.nylas.models.*;
 26 | import java.text.SimpleDateFormat;
 27 | 
 28 | public class ReadEmail {
 29 |   public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
 30 |     NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
 31 |     ListResponse<Message> message = nylas.messages().list(dotenv.get("NYLAS_GRANT_ID"));
 32 | 
 33 |     for(Message email : message.getData()){
 34 |       String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").
 35 |           format(new java.util.Date((email.getDate() == null ? 1 : 1000L)));
 36 | 
 37 |       System.out.println(email.getId() + "[" + date + "] | " +
 38 |           email.getSubject() + " | " +
 39 |           email.getFolders());
 40 |     }
 41 |   }
 42 | }
 43 | ```
 44 | 
 45 | ```Python
 46 | from dotenv import load_dotenv
 47 | load_dotenv()
 48 | 
 49 | import os
 50 | import sys
 51 | from nylas import Client
 52 | 
 53 | nylas = Client(
 54 |     os.environ.get('NYLAS_API_KEY'),
 55 |     os.environ.get('NYLAS_API_URI')
 56 | )
 57 | 
 58 | grant_id = os.environ.get("NYLAS_GRANT_ID")
 59 | 
 60 | messages = nylas.messages.list(
 61 |     grant_id,
 62 |     query_params={
 63 |       "limit": 5
 64 |     }
 65 | )
 66 | 
 67 | print(messages)
 68 | ```
 69 | 
 70 | ```Ruby
 71 | require 'nylas'
 72 | 
 73 | # Initialize Nylas client
 74 | nylas = Nylas::Client.new(
 75 |     api_key: "<NYLAS_API_KEY>"
 76 | )
 77 | 
 78 | messages, _ = nylas.messages.list(identifier: "<NYLAS_GRANT_ID>")
 79 | 
 80 | messages.each {|message|
 81 |   puts "[#{Time.at(message[:date]).strftime("%d/%m/%Y at %H:%M:%S")}] | \
 82 |   #{message[:id]} | \
 83 |   #{message[:subject]} | \
 84 |   #{message[:folders]}"
 85 | }
 86 | ```
 87 | 
 88 | ```API
 89 | curl --request GET \
 90 |   --url "https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/messages?limit=5" \
 91 |   --header 'Accept: application/json' \
 92 |   --header 'Authorization: Bearer <NYLAS_API_KEY>' \
 93 |   --header 'Content-Type: application/json'
 94 | ```
 95 | 
 96 | ### Get a specific message
 97 | 
 98 | `GET /messages/<MESSAGE_ID>` → `GET /v3/grants/<NYLAS_GRANT_ID>/messages/<MESSAGE_ID>`
 99 | 
100 | ```Node
101 | import 'dotenv/config'
102 | import Nylas from 'nylas'
103 | 
104 | const NylasConfig = {
105 |   apiKey: process.env.NYLAS_API_KEY,
106 |   apiUri: process.env.NYLAS_API_URI,
107 | }
108 | 
109 | const nylas = new Nylas(NylasConfig)
110 | 
111 | async function fetchMessageById() {
112 |   try {
113 |     const message = await nylas.messages.find({
114 |       identifier: process.env.NYLAS_GRANT_ID,
115 |       messageId: process.env.MESSAGE_ID,
116 |     })
117 | 
118 |     console.log('message:', message)
119 |   } catch (error) {
120 |     console.error('Error fetching message:', error)
121 |   }
122 | }
123 | 
124 | fetchMessageById()
125 | ```
126 | 
127 | ```Java
128 | import com.nylas.NylasClient;
129 | import com.nylas.models.*;
130 | 
131 | public class ReturnMessage {
132 |   public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
133 |     NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
134 |     Response<Message> message = nylas.messages().find("<NYLAS_GRANT_ID>", "<MESSAGE_ID>");
135 | 
136 |     System.out.println(message);
137 |   }
138 | }
139 | ```
140 | 
141 | ```Python
142 | from dotenv import load_dotenv
143 | load_dotenv()
144 | 
145 | import os
146 | import sys
147 | from nylas import Client
148 | 
149 | nylas = Client(
150 |     os.environ.get('NYLAS_API_KEY'),
151 |     os.environ.get('NYLAS_API_URI')
152 | )
153 | 
154 | grant_id = os.environ.get("NYLAS_GRANT_ID")
155 | message_id = os.environ.get("MESSAGE_ID")
156 | 
157 | message = nylas.messages.find(
158 |     grant_id,
159 |     message_id,
160 | )
161 | 
162 | print(message)
163 | ```
164 | 
165 | ```Ruby
166 | require 'nylas'
167 | 
168 | nylas = Nylas::Client.new(
169 |     api_key: "<NYLAS_API_KEY>"
170 | )
171 | 
172 | message, _ = nylas.messages.find(identifier: ENV["NYLAS_GRANT_ID"], message_id: "<MESSAGE_ID>")
173 | 
174 | puts message
175 | ```
176 | 
177 | ```API
178 | curl --request GET \
179 |   --url https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/messages/<MESSAGE_ID> \
180 |   --header 'Accept: application/json' \
181 |   --header 'Authorization: Bearer <NYLAS_API_KEY>' \
182 |   --header 'Content-Type: application/json'
183 | ```
184 | 
185 | ### Clean a message
186 | 
187 | You can use the [`PUT /v3/grants/<NYLAS_GRANT_ID>/messages/clean` endpoint](https://developer.nylas.com/docs/api/v3/ecc/#put-/v3/grants/-grant_id-/messages/clean) to remove extra information from an email message.
188 | 
189 | ```API
190 | curl --location --request PUT 'https://api.us.nylas.com/v3/grants/NYLAS_GRANT_ID/messages/clean' \
191 |   --header 'Content-Type: application/json' \
192 |   --header 'Accept: application/json' \
193 |   --header 'Authorization: Bearer <NYLAS_API_KEY_OR_ACCESS_TOKEN>' \
194 |   --data '{
195 |     "message_id": ["18df98cadcc8534a"],
196 |     "ignore_links": false,
197 |     "ignore_images": false,
198 |     "images_as_markdown": true,
199 |     "ignore_tables": true,
200 |     "remove_conclusion_phrases": true
201 |   }'
202 | ```
203 | 
204 | ```Java
205 | import com.nylas.NylasClient;
206 | import com.nylas.models.*;
207 | import java.util.ArrayList;
208 | import java.util.Arrays;
209 | import java.util.List;
210 | 
211 | public class Clean_Message {
212 |   public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
213 |     NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
214 |     List<String> messagesId = List.of("<MESSAGE_ID>");
215 | 
216 |     CleanMessagesRequest requestBody = new CleanMessagesRequest.Builder(messagesId).
217 |         ignoreImages(true).
218 |         ignoreLinks(true).
219 |         ignoreTables(true).
220 |         imagesAsMarkdown(true).
221 |         removeConclusionPhrases(true).
222 |         build();
223 | 
224 |     ListResponse<CleanMessagesResponse> clean = nylas.messages().cleanMessages("<NYLAS_GRANT_ID>", requestBody);
225 | 
226 |     System.out.println(clean.getData());
227 |   }
228 | }
229 | ```
230 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Contacts/read.md:
--------------------------------------------------------------------------------

```markdown
  1 | ### Get all contacts
  2 | 
  3 | `GET /contacts` → [`GET /v3/grants/<NYLAS_GRANT_ID>/contacts`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/contacts)
  4 | 
  5 | ```API
  6 | curl --request GET \
  7 |   --url https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/contacts \
  8 |   --header 'Accept: application/json' \
  9 |   --header 'Authorization: Bearer <NYLAS_API_KEY>' \
 10 |   --header 'Content-Type: application/json'
 11 | ```
 12 | 
 13 | ```Node
 14 | import 'dotenv/config'
 15 | import Nylas from 'nylas'
 16 | 
 17 | const NylasConfig = {
 18 |   apiKey: process.env.NYLAS_API_KEY,
 19 |   apiUri: process.env.NYLAS_API_URI,
 20 | }
 21 | 
 22 | const nylas = new Nylas(NylasConfig)
 23 | 
 24 | async function fetchContacts() {
 25 |   try {
 26 |     const identifier = process.env.NYLAS_GRANT_ID
 27 |     const contacts = await nylas.contacts.list({
 28 |       identifier,
 29 |       queryParams: {}, 
 30 |     })
 31 | 
 32 |     console.log('Recent Contacts:', contacts)
 33 |   } catch (error) {
 34 |     console.error('Error fetching drafts:', error)
 35 |   }
 36 | }
 37 | 
 38 | fetchContacts()
 39 | ```
 40 | 
 41 | ```Ruby
 42 | require 'nylas' 
 43 | 
 44 | nylas = Nylas::Client.new(api_key: "<NYLAS_API_KEY>")
 45 | contacts, _ = nylas.contacts.list(identifier: ENV["NYLAS_GRANT_ID"])
 46 | 
 47 | contacts.each {|contact|
 48 |   puts "Name: #{contact[:given_name]} #{contact[:surname]} | " \
 49 |       "Email: #{contact[:emails][0][:email]} | ID: #{contact[:id]}"
 50 | }
 51 | ```
 52 | 
 53 | ```Python
 54 | from dotenv import load_dotenv
 55 | load_dotenv()
 56 | 
 57 | import os
 58 | import sys
 59 | from nylas import Client
 60 | 
 61 | nylas = Client(
 62 |     os.environ.get('NYLAS_API_KEY'),
 63 |     os.environ.get('NYLAS_API_URI')
 64 | )
 65 | 
 66 | grant_id = os.environ.get("NYLAS_GRANT_ID")
 67 | 
 68 | contacts = nylas.contacts.list(
 69 |   grant_id,
 70 | )
 71 | 
 72 | print(contacts)
 73 | ```
 74 | 
 75 | ```Java
 76 | import com.nylas.NylasClient;
 77 | import com.nylas.models.*;
 78 | 
 79 | public class ReadAllContacts {
 80 |   public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
 81 |     NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
 82 |     ListResponse<Contact> contacts = nylas.contacts().list("<NYLAS_GRANT_ID>");
 83 | 
 84 |     for(Contact contact : contacts.getData()) {
 85 |       System.out.println(contact);
 86 |       System.out.println("\n");
 87 |     }
 88 |   }
 89 | }
 90 | ```
 91 | 
 92 | ### Get a specific contact
 93 | 
 94 | `GET /contacts/<CONTACT_ID>` → [`GET /v3/grants/<NYLAS_GRANT_ID>/contacts/<CONTACT_ID>`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/contacts/-contact_id-)
 95 | 
 96 | ```API
 97 | curl --request GET \
 98 |   --url https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/contacts/<CONTACT_ID> \
 99 |   --header 'Accept: application/json' \
100 |   --header 'Authorization: Bearer <NYLAS_API_KEY>' \
101 |   --header 'Content-Type: application/json'
102 | ```
103 | 
104 | ```Node
105 | import 'dotenv/config'
106 | import Nylas from 'nylas'
107 | 
108 | const NylasConfig = {
109 |  apiKey: process.env.NYLAS_API_KEY,
110 |  apiUri: process.env.NYLAS_API_URI,
111 | }
112 | 
113 | const nylas = new Nylas(NylasConfig)
114 | 
115 | async function fetchContactById() { 
116 |   try {
117 |     const contact = await nylas.contacts.find({
118 |       identifier: process.env.NYLAS_GRANT_ID,
119 |       contactId: process.env.CONTACT_ID,
120 |       queryParams: {},
121 |     })
122 |   
123 |     console.log('contact:', contact)
124 |   } catch (error) {
125 |     console.error('Error fetching contact:', error)
126 |   }
127 | }
128 | 
129 | fetchContactById()
130 | ```
131 | 
132 | ```Ruby
133 | require 'nylas' 
134 | 
135 | nylas = Nylas::Client.new(api_key: "<NYLAS_API_KEY>")
136 | contact, _ = nylas.contacts.find(identifier: "<NYLAS_GRANT_ID>", contact_id: "<CONTACT_ID>")
137 | 
138 | puts contact
139 | ```
140 | 
141 | ```Python
142 | from dotenv import load_dotenv
143 | load_dotenv()
144 | 
145 | import os
146 | import sys
147 | from nylas import Client
148 | 
149 | nylas = Client(
150 |     os.environ.get('NYLAS_API_KEY'),
151 |     os.environ.get('NYLAS_API_URI')
152 | )
153 | 
154 | grant_id = os.environ.get("NYLAS_GRANT_ID")
155 | contact_id = os.environ.get("CONTACT_ID")
156 | 
157 | contact = nylas.contacts.find(
158 |   grant_id,
159 |   contact_id,
160 | )
161 | 
162 | print(contact)
163 | ```
164 | 
165 | ```Java
166 | import com.nylas.NylasClient;
167 | import com.nylas.models.*;
168 | 
169 | public class ReturnAContact {
170 |   public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
171 |     NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
172 |     Response<Contact> contact = nylas.contacts().find("<NYLAS_GRANT_ID>", "<CONTACT_ID>");
173 | 
174 |     System.out.println(contact);
175 |   }
176 | }
177 | ```
178 | 
179 | ### Return all contact groups
180 | 
181 | `GET /groups` → [`GET /v3/grants/<NYLAS_GRANT_ID>/contacts/groups`](https://developer.nylas.com/docs/api/v3/ecc/#get-/v3/grants/-grant_id-/contacts/groups)
182 | 
183 | ```API
184 | curl --request GET \
185 |   --url https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/contacts/groups \
186 |   --header 'Accept: application/json' \
187 |   --header 'Authorization: Bearer <NYLAS_API_KEY>' \
188 |   --header 'Content-Type: application/json'
189 | ```
190 | 
191 | ```Node
192 | import 'dotenv/config'
193 | import Nylas from 'nylas'
194 | 
195 | const NylasConfig = {
196 |   apiKey: process.env.NYLAS_API_KEY,
197 |   apiUri: process.env.NYLAS_API_URI,
198 | }
199 | 
200 | const nylas = new Nylas(NylasConfig)
201 | 
202 | async function fetchContactGroups() {
203 |   try {
204 |     const identifier = process.env.NYLAS_GRANT_ID
205 |     const contactGroups = await nylas.contacts.groups({
206 |       identifier,
207 |     })
208 | 
209 |     console.log('Contacts Groups:', contactGroups)
210 |   } catch (error) {
211 |     console.error('Error fetching contact groups:', error)
212 |   }
213 | }
214 | 
215 | fetchContactGroups()
216 | ```
217 | 
218 | ```Ruby
219 | require 'nylas' 
220 | 
221 | nylas = Nylas::Client.new(api_key: "<NYLAS_API_KEY>")
222 | groups = nylas.contacts.list_groups(identifier: "<NYLAS_GRANT_ID>")
223 | 
224 | puts groups
225 | ```
226 | 
227 | ```Python
228 | from dotenv import load_dotenv
229 | load_dotenv()
230 | 
231 | import os
232 | import sys
233 | from nylas import Client
234 | 
235 | nylas = Client(
236 |     os.environ.get('NYLAS_API_KEY'),
237 |     os.environ.get('NYLAS_API_URI')
238 | )
239 | 
240 | grant_id = os.environ.get("NYLAS_GRANT_ID")
241 | 
242 | contact_groups = nylas.contacts.list_groups(
243 |   grant_id,
244 | )
245 | 
246 | print(contact_groups)
247 | ```
248 | 
249 | ```Java
250 | import com.nylas.NylasClient;
251 | import com.nylas.models.*;
252 | 
253 | public class ReadContactGroups {
254 |   public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
255 |     NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
256 |     ListResponse<ContactGroup> groups = nylas.contacts().listGroups("<NYLAS_GRANT_ID>");
257 |     
258 |     System.out.println(groups);
259 |   }
260 | }
261 | ```
262 | 
```

--------------------------------------------------------------------------------
/nylas-code-samples/Calendar/Calendars/read.md:
--------------------------------------------------------------------------------

```markdown
  1 | ### Get all calendars
  2 | 
  3 | GET /calendars → /v3/grants/{grant_id}/calendars
  4 | 
  5 | ```Node
  6 | import 'dotenv/config'
  7 | import Nylas from 'nylas'
  8 | 
  9 | const NylasConfig = {
 10 |   apiKey: process.env.NYLAS_API_KEY,
 11 |   apiUri: process.env.NYLAS_API_URI,
 12 | }
 13 | 
 14 | const nylas = new Nylas(NylasConfig);
 15 | 
 16 | async function fetchFiveAvailableCalendars() {
 17 |   try {
 18 |     const calendars = await nylas.calendars.list({
 19 |       identifier: process.env.NYLAS_GRANT_ID,
 20 |       limit: 5
 21 |   })
 22 | 
 23 |   console.log('Available Calendars:', calendars);
 24 |   } catch (error) {
 25 |     console.error('Error fetching calendars:', error)
 26 |   }
 27 | }
 28 | 
 29 | fetchFiveAvailableCalendars()
 30 | ```
 31 | 
 32 | ```Java
 33 | import com.nylas.NylasClient;
 34 | import com.nylas.models.*;
 35 | import java.util.List;
 36 | import java.util.Map;
 37 | 
 38 | public class ReturnCalendars {
 39 |     public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
 40 |         NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
 41 | 
 42 |         ListCalendersQueryParams listCalendersQueryParams = 
 43 |                                  new ListCalendersQueryParams();
 44 | 
 45 |         ListCalendersQueryParams returnFiveCalendars = new ListCalendersQueryParams.
 46 |                                                       Builder().limit(5).build();
 47 | 
 48 |         List<Calendar> calendars = nylas.calendars().
 49 |                        list("<NYLAS_GRANT_ID>", listCalendersQueryParams).getData();
 50 | 
 51 |         for (Calendar calendar : calendars){
 52 |             System.out.println("Id: " + calendar.getId() +
 53 |                                " | Name: " + calendar.getName() +
 54 |                                " | Description: " + calendar.getDescription() +
 55 |                                " | Is Read Only?: " + calendar.getReadOnly() +
 56 |                                " | Metadata: " + calendar.getMetadata());
 57 |         }
 58 | 
 59 |         ListCalendersQueryParams CalendarsMetadata = new ListCalendersQueryParams.
 60 |                                                          Builder().
 61 |                                                          metadataPair(
 62 |                                                          Map.of("key1", 
 63 |                                                                 "This is my metadata")
 64 |                                                          ).
 65 |                                                          build();
 66 |                                                          
 67 |         List<Calendar> metaCalendars = nylas.calendars().
 68 |                                        list("<NYLAS_GRANT_ID>", CalendarsMetadata).
 69 |                                        getData();
 70 |                                        
 71 |         System.out.println();
 72 |         System.out.println(metaCalendars);
 73 |     }
 74 | }
 75 | ```
 76 | 
 77 | ```Python
 78 | from dotenv import load_dotenv
 79 | load_dotenv()
 80 | 
 81 | import os
 82 | import sys
 83 | from nylas import Client
 84 | 
 85 | nylas = Client(
 86 |     os.environ.get('NYLAS_API_KEY'),
 87 |     os.environ.get('NYLAS_API_URI')
 88 | )
 89 | 
 90 | grant_id = os.environ.get("NYLAS_GRANT_ID")
 91 | calendars = nylas.calendars.list(grant_id)
 92 | 
 93 | print(calendars)
 94 | ```
 95 | 
 96 | ```Ruby
 97 | # Load gems
 98 | require 'nylas'
 99 | 
100 | # Initialize Nylas client
101 | nylas = Nylas::Client.new(
102 |   api_key: "<NYLAS_API_KEY>"
103 | )
104 | 
105 | # Build the query without parameters
106 | listCalendersQueryParams = {}
107 | 
108 | # Build the query with parameters
109 | returnFiveCalendars = {
110 |  limit: 5
111 | }
112 | 
113 | # Get a list of calendars
114 | calendars, _request_ids = nylas.calendars.list(identifier: "<NYLAS_GRANT_ID>", 
115 |   query_params: listCalendersQueryParams)
116 | 
117 | # Loop the calendars
118 | calendars.each {|calendar|
119 |  puts("Name: #{calendar[:name]} | " \
120 |    "Description: #{calendar[:description]} | " \
121 |    "Is Read Only?: #{calendar[:read_only]} | " \
122 |    "Metadata: #{calendar[:metadata]}")
123 | }
124 | 
125 | # Build the event parameters with metadata
126 | CalendarsMetadata = {
127 |  metadata_pair: {"key1":"This is my metadata"}
128 | }
129 | 
130 | # Get a list of calendars
131 | calendars, _request_ids = nylas.calendars.list(identifier: ENV["NYLAS_GRANT_ID"], 
132 |   query_params: CalendarsMetadata)
133 | 
134 | puts ""                          
135 | calendars.each {|calendar|
136 |  puts calendar
137 | }
138 | ```
139 | 
140 | ```API
141 | curl --request GET \
142 |   --url 'https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/calendars' \
143 |   --header 'Authorization: Bearer <NYLAS_API_KEY>' \
144 |   --header 'Content-Type: application/json'
145 | ```
146 | 
147 | ### Get a specific calendar
148 | 
149 | GET /calendars/{id} → /v3/grants/{grant_id}/calendars/{calendar_id}
150 | 
151 | ```Node
152 | import 'dotenv/config'
153 | import Nylas from 'nylas'
154 | 
155 | const NylasConfig = {
156 |   apiKey: process.env.NYLAS_API_KEY,
157 |   apiUri: process.env.NYLAS_API_URI,
158 | }
159 | 
160 | const nylas = new Nylas(NylasConfig);
161 | 
162 | async function fetchCalendar() {
163 |   try {
164 |     const calendar = await nylas.calendars.find({
165 |       identifier: process.env.NYLAS_GRANT_ID,
166 |       calendarId: process.env.CALENDAR_ID,
167 |     })
168 | 
169 |     console.log('Calendar:', calendar)
170 |   } catch (error) {
171 |     console.error('Error fetching calendars:', error)
172 |   }
173 | }
174 | 
175 | fetchCalendar()
176 | ```
177 | 
178 | ```Java
179 | import com.nylas.NylasClient;
180 | import com.nylas.models.*;
181 | 
182 | public class GetCalendar {
183 |   public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
184 |   NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
185 |   Response<Calendar> calendar = nylas.calendars().find("<NYLAS_GRANT_ID>", "<CALENDAR_ID>");
186 | 
187 |   System.out.println("Id: " + calendar.getData().getId() +
188 |       " | Name: " + calendar.getData().getName() +
189 |       " | Description: " + calendar.getData().getDescription());
190 |   }
191 | }
192 | ```
193 | 
194 | ```Python
195 | from dotenv import load_dotenv
196 | load_dotenv()
197 | 
198 | import os
199 | import sys
200 | from nylas import Client
201 | 
202 | nylas = Client(
203 |     os.environ.get('NYLAS_API_KEY'),
204 |     os.environ.get('NYLAS_API_URI')
205 | )
206 | 
207 | grant_id = os.environ.get("NYLAS_GRANT_ID")
208 | 
209 | calendar = nylas.calendars.find(
210 |     grant_id,
211 |     os.environ.get("CALENDAR_ID")
212 | )
213 | 
214 | print(calendar)
215 | ```
216 | 
217 | ```Ruby
218 | require 'nylas' 
219 | 
220 | nylas = Nylas::Client.new(api_key: "<NYLAS_API_KEY>")
221 | 
222 | calendar, _request_ids = nylas.calendars.find(
223 |   identifier: "<NYLAS_GRANT_ID>", 
224 |   calendar_id: "<CALENDAR_ID>"
225 | )
226 | 
227 | puts calendar
228 | ```
229 | 
230 | ```API
231 | curl --request GET \
232 |   --url https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/calendars/<CALENDAR_ID> \
233 |   --header 'Accept: application/json' \
234 |   --header 'Authorization: Bearer <NYLAS_API_KEY>' \
235 |   --header 'Content-Type: application/json'
236 | ```
237 | 
```
Page 1/3FirstPrevNextLast