Source: https://cli.nylas.com/guides/email-to-trello-cards

# Turn Emails into Trello Cards (CLI)

Trello boards run support queues, bug triage, and content calendars, and the work usually starts as an email. Paid connectors meter every card they create. The Nylas CLI hands you each message as JSON, jq reshapes it, and one POST to the Trello cards API turns it into a card on the list you choose. This guide builds an email-to-Trello pipeline you own, mapping subject to the card name and the body to the description, with de-duplication so a re-run never doubles a card.

Written by [Aaron de Mello](https://cli.nylas.com/authors/aaron-de-mello) Senior Engineering Manager

Reviewed by [Qasim Muhammad](https://cli.nylas.com/authors/qasim-muhammad)

Updated June 9, 2026

> **TL;DR:** Pull messages with `nylas email search --json`, reshape each one with `jq`, then create a card by POSTing to the Trello API `/1/cards` endpoint with your key, token, and a list ID. The CLI handles the inbox across six providers; Trello handles the write. The de-duplication trick at the end is what stops a daily cron from creating the same card twice.

Command references used in this guide: [`nylas email search`](https://cli.nylas.com/docs/commands/email-search), [`nylas email list`](https://cli.nylas.com/docs/commands/email-list), and [`nylas email read`](https://cli.nylas.com/docs/commands/email-read).

## How do I turn an email into a Trello card?

You turn an email into a Trello card by pulling the message as JSON and POSTing one card per message to the Trello REST API. The `nylas email search` command returns structured messages, and a single request to the `/1/cards` endpoint creates a card on the list you name. The card-creation contract is documented in the [Trello REST API reference](https://developer.atlassian.com/cloud/trello/rest/api-group-cards/#api-cards-post).

Two values come first. Every Trello write needs a `key` and a `token` passed as query parameters, plus an `idList` naming the target list. The token-based scheme is described in the [Trello authorization guide](https://developer.atlassian.com/cloud/trello/guides/rest-api/authorization/). Install the tool first with one Homebrew command, or see [getting started](https://cli.nylas.com/guides/getting-started) for the other methods.

```bash
brew install nylas/nylas-cli/nylas

# Pull the messages you want as cards (last 20 by default)
nylas email search "bug report" --json --limit 50 > items.json
```

## How do I shape the email JSON with jq?

You shape the email JSON with `jq`, mapping each message to the three fields the Trello cards endpoint expects: `name`, `desc`, and `idList`. The subject becomes the card name; the sender and snippet become the description. The CLI returns `subject`, `from`, and `snippet` on every message.

Card names are capped at 16,384 characters by Trello, so a subject never overflows, but an empty subject would create a nameless card. Fall back to a placeholder with the `//` alternative operator, documented in the [jq manual](https://jqlang.github.io/jq/manual/). The sender field is an array, so index the first entry. This step transforms the raw inbox dump into a flat array of card-ready objects, one per message.

```bash
LIST_ID="your-list-id"

# Reshape each message into Trello's card fields
jq -c --arg list "$LIST_ID" '.[] | {
  name: (.subject // "(no subject)"),
  desc: ("From: " + (.from[0].email // "unknown") + "\n\n" + (.snippet // "")),
  idList: $list
}' items.json > cards.json
```

## How do I POST the card to the Trello API?

You create the card with one `POST` to `https://api.trello.com/1/cards`, passing your `key` and `token` as query parameters and the reshaped object as a JSON body. Trello replies with the new card's ID and short URL. The endpoint accepts a single card per request, so loop over the array from the previous step.

Trello's default API rate limit is 300 requests per 10 seconds per key and 100 per 10 seconds per token, per the [Trello rate-limit docs](https://developer.atlassian.com/cloud/trello/guides/rest-api/rate-limits/). A batch of 50 messages stays well under that, but add a short sleep if you import thousands. Each loop iteration reads one card object, sends it, and prints the returned URL so you can confirm the write landed on the right list.

```bash
KEY="your-trello-key"
TOKEN="your-trello-token"

# Create one card per reshaped object
jq -c '.' cards.json | while read -r card; do
  curl -s -X POST "https://api.trello.com/1/cards?key=$KEY&token=$TOKEN" \
    -H "Content-Type: application/json" \
    -d "$card" | jq -r '"Created: " + .shortUrl'
done
```

## How do I stop duplicate cards on a re-run?

You stop duplicate cards by de-duplicating on a stable field before the POST. The cleanest key is the Nylas message ID, which never changes for a given message. Write each processed ID to a local file, then skip any message whose ID is already there. A daily cron scoped to `--after` yesterday only ever sees the last day's mail, so the seen-file stays small.

This guards against the common failure mode: a cron runs every 6 hours, the same unread email matches each time, and the board fills with four copies of one card. Carry the message ID through the jq step, check it with `grep -qF` against the seen-file, and append it only after a successful create. The ID-based check is exact, so it survives subject edits and resends.

```bash
SEEN="seen-ids.txt"; touch "$SEEN"

nylas email search "bug report" --json --after 2026-06-08 \
  | jq -c '.[] | {id, name: (.subject // "(no subject)"), idList: $ENV.LIST_ID}' \
  | while read -r card; do
      id=$(echo "$card" | jq -r '.id')
      grep -qF "$id" "$SEEN" && continue
      curl -s -X POST "https://api.trello.com/1/cards?key=$KEY&token=$TOKEN" \
        -H "Content-Type: application/json" \
        -d "$(echo "$card" | jq 'del(.id)')" > /dev/null \
        && echo "$id" >> "$SEEN"
    done
```

## Why use the CLI instead of a paid connector?

Use the CLI because it gives you the email as raw JSON with no per-card fee, where hosted connectors meter every record. A typical no-code automation plan caps free runs at a few hundred tasks per month, then bills per task above that. The `nylas email search --json` path runs on your own cron with zero marginal cost per card.

The CLI also reaches across providers without per-mailbox setup. One grant covers Gmail, Outlook, and four other backends, and OAuth tokens stored in your system keyring refresh automatically every 3,600 seconds. You keep the filtering logic in version control instead of a vendor's visual editor, so a search query like `--from support@example.com` is reviewable in a pull request. Gmail's own query operators are documented in the [Gmail API filtering guide](https://developers.google.com/workspace/gmail/api/guides/filtering), and message address formats follow [RFC 5322](https://datatracker.ietf.org/doc/html/rfc5322).

## Next steps

- [Create Confluence Pages from Email](https://cli.nylas.com/guides/email-to-confluence-pages) — Pull email as JSON with the Nylas CLI and POST to the Confluence…
- [Push Email into a Coda Doc (CLI)](https://cli.nylas.com/guides/email-to-coda) — Pull email as JSON with the Nylas CLI and insert one row per…
- [Email to ClickUp tasks](https://cli.nylas.com/guides/email-to-clickup-tasks) — the same pattern into a ClickUp list
- [Email to Linear issues](https://cli.nylas.com/guides/email-to-linear-issues) — file engineering work instead of cards
- [Send email to a Notion database](https://cli.nylas.com/guides/email-to-notion) — map messages to Notion pages
- [Email to Airtable](https://cli.nylas.com/guides/email-to-airtable) — the same flow into Airtable records
- [Extract email data with jq](https://cli.nylas.com/guides/extract-email-data-jq) — the JSON-shaping toolkit behind this pipeline
- [Full command reference](https://cli.nylas.com/docs/commands) — every flag and subcommand documented
