Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Trello Laravel Package

laravel-notification-channels/trello

Laravel Notification Channels Trello is a lightweight channel for sending Laravel notifications directly to Trello as cards. Configure API credentials and a target list ID, then route app events into your board workflow with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is a thin notification channel: it turns a TrelloMessage value object into a POST /1/cards call against the Trello REST API. Everything you need to know lives in two files — src/TrelloChannel.php (how the route is resolved and the request is built) and src/TrelloMessage.php (the fluent payload builder). Read those before the README; they are short and they are the source of truth for method names, since the package has not had a release since September 2020.

1. Install and publish config

composer require laravel-notification-channels/trello
php artisan vendor:publish --provider="NotificationChannels\Trello\TrelloServiceProvider"

This gives you config/trello.php with api_key and token keys. Confirm the actual key names in the published file — don't assume.

2. Get credentials

  • API key: https://trello.com/app-key
  • Token: the "Token" link on that same page (manually generate, with read,write scope)

3. Get the target list ID

A card must be created in a list (a column), not a board. Open the board, add .json to the URL, or hit GET /1/boards/{id}/lists?key=…&token=… and copy the id of the list you want. Store it in config, not inline in code.

4. Wire up a notification

class NewLeadCreated extends Notification implements ShouldQueue
{
    public function __construct(public Lead $lead) {}

    public function via($notifiable): array
    {
        return [TrelloChannel::class];
    }

    public function toTrello($notifiable)
    {
        return TrelloMessage::create()
            ->to(config('services.trello.leads_list_id'))
            ->title("New lead: {$this->lead->company}")
            ->description($this->lead->summary);
    }
}

5. Route it

The notifiable must expose routeNotificationForTrello(). Returning a plain string list ID works in the common case; returning an array lets you pass multiple parameters (list + board + members) that the channel folds into the payload. Verify which shape your version accepts by reading TrelloChannel::send().

First use case that pays for itself immediately: an internal "ops board" card whenever a job exhausts retries, a webhook signature fails, or a payment webhook errors. It is a shared, zero-setup incident log that non-engineers can read, and it costs ~15 lines of code.

Implementation Patterns

Per-notifiable routing instead of hardcoded lists. Let the model decide its destination, so one notification class can fan out to different lists:

// On the Team model
public function routeNotificationForTrello(): array
{
    return ['idList' => $this->trello_list_id];
}

This keeps list IDs in your database (editable by admins) rather than in config/, which is the right trade-off once you have more than one board.

On-demand notifications for anonymous events. For things with no model (a contact form, a failed login spike), skip the notifiable entirely and use the Notification facade's route method:

Notification::route('Trello', ['idList' => config('services.trello.intake_list')])
    ->notify(new ContactFormSubmitted($payload));

This is the highest-leverage pattern in the package — it means the channel is useful even when nothing in your domain is notifiable. Confirm your version supports array routes before relying on it; if it only accepts strings, wrap the destination in a small TrelloRoute value object and resolve it in a subclassed channel.

Wrap the payload in a DTO, not a notification. Build the card content in the model or a dedicated TrelloCardData class, then have the notification map that to TrelloMessage. Notifications are hard to unit test for content; DTOs are trivial.

Always queue. Trello is an external HTTP dependency in your request path. implements ShouldQueue plus a dedicated queue (onQueue('trello')) isolates Trello outages and rate limits from user-facing latency. Set $tries = 3 and $backoff = [10, 60].

Link back to your app. Put a deep link to the source record in the description, and use urlSource/source-URL on the card if the message class exposes it. Someone reading the board should be one click from the record.

Gate by environment. Sending real cards from local dev and CI pollutes the board. Either guard with a config flag inside via():

public function via($notifiable): array
{
    return config('services.trello.enabled') ? [TrelloChannel::class] : [];
}

or route dev traffic to a separate sandbox board/list ID.

Testing. Use Notification::fake() and assert on the notification class — that's cheap and stable. Only drop to Http::fake() if you genuinely want to assert the outbound JSON payload, and if you do, pin the expected endpoint (api.trello.com/1/cards) so a package upgrade that changes the client is caught.

Two-way sync. If you need cards updated when they move, use Trello webhooks (POST /1/tokens/{token}/webhooks) pointing at a Laravel route, not polling. The channel is write-only — it will never tell you a card was completed.

Gotchas and Tips

The package is effectively unmaintained. Last release 2020-09-09, 25 stars, zero dependents. It predates Laravel's Http client being the norm and may pull an older Guzzle or use env() outside config. Two consequences: (a) pin it and run your test suite on every Laravel minor upgrade, and (b) budget for the fallback — writing your own channel is genuinely ~40 lines:

Http::post('https://api.trello.com/1/cards', [
    'key' => config('services.trello.key'),
    'token' => config('services.trello.token'),
    'idList' => $route['idList'],
    'name' => $message->title,
    'desc' => $message->description,
])->throw();

If the package breaks on Laravel 10/11, that's the migration path, and the message class is a plain DTO so you can keep your notification signatures unchanged.

The token is a full-account credential. A Trello token is user-scoped and does not expire on its own. It can read and write every board that member can see. Use a dedicated bot member invited only to the relevant boards, store the token in config/services.php + .env (never config/trello.php directly committed), and know how to revoke it at trello.com/app-key. This is the single biggest operational risk with this package.

Rate limits are per key and per token. Trello allows roughly 300 requests / 10s per key and 100 requests / 10s per token. Individual card creation never trips this, but a batch job or a foreach over 500 records will. Use Redis::throttle('trello')->allow(50)->every(10) or Laravel's RateLimited job middleware on the queue.

Retries create duplicate cards. Trello's create-card endpoint has no idempotency key, so a queued notification that times out after the card was created will produce a second card. Mitigations: encode a stable fingerprint (order:8421) in the description and check for it, or accept the duplicates and dedupe in a scheduled sweep.

idList vs idBoard is the most common 400. Cards cannot be created on a board; they must go in a list. "Invalid value for idList" almost always means you pasted a board ID, or you're pointing at a list on a board the bot member isn't a member of.

Errors are easy to miss on queued notifications. Exceptions land in failed_jobs, not your logs, and Notification::send() is fire-and-forget in the request cycle. Register a listener for Illuminate\Notifications\Events\NotificationFailed and log/alert on it, otherwise silent failures go unnoticed for weeks.

You cannot get the created card's ID back through the channel. The response is discarded, so you can't post a follow-up comment or attachment to the card it just made. If you need that, subclass TrelloChannel, override send() to capture the response, and fire your own event — or bypass the channel at that point.

Description is markdown-flavored, not HTML. Trello renders a subset (headings, lists, bold/italic, links, fenced code). HTML tags appear literally. This is fine for alert text and stack traces, but escape user-supplied content or a lead's name containing ** will mangle the card.

Mentions need board membership. @username in a description notifies only if that member is on the board; otherwise it's inert text and you'll think the notification was sent when nobody saw it.

Config caching bites. If the package reads env('TRELLO_TOKEN') directly rather than through config(), php artisan config:cache in production silently yields null and you get 401s. Grep the package for env( and, if present, copy the needed values into your own config file and override.

Attachments, checklists, labels, and due dates are extra API calls. The message class covers the POST /cards field set; anything beyond that (attachments, checklists, moving a card later) is PUT/POST to /cards/{id}/… and must be done outside the channel. Don't expect the fluent builder to cover them.

Extension point: because via() just returns a class string, you can drop in App\Notifications\Channels\TrelloChannel at any time without touching notification classes — make that your escape hatch if the upstream package rots.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource