Sign in to fill these examples with your own keys. Sign in Start free trial

Send emails with Laravel

Set the mailer to postshiba and call Mail::raw.

What you'll build

A Laravel mailer named postshiba that sends through the PostShiba API. Mail::raw, Mailables, and queued mail all use it once it is the default.

Before you start

  • An API key with Send only access. Full access also works. See Create an API key. Support keys cannot send.
  • A verified sending domain. See Add and verify a domain. from must be an address on it.
  • A cluster that is ready to send (sending_ready is true). See Clusters.
  • PHP 8.1 or later.

Install

The package is on GitHub, not Packagist. Add the repository, then require it. Laravel auto-discovers PostShiba\Laravel\PostShibaServiceProvider, which registers the postshiba transport.

install.sh
1composer config repositories.postshiba vcs https://github.com/postshiba/postshiba-php 2composer require postshiba/postshiba:dev-main

Send your first email

  1. Set the default mailer and your API key in .env.
.env
1MAIL_MAILER=postshiba 2POSTSHIBA_API_KEY=YOUR_API_KEY
  1. Add a postshiba entry to config/services.php. The provider reads key from it.
services.php
1'postshiba' => [ 2 'key' => env('POSTSHIBA_API_KEY'), 3],
  1. Add a postshiba mailer to the mailers array in config/mail.php.
mail.php
1'postshiba' => [ 2 'transport' => 'postshiba', 3],
  1. Send a message.
send.php
1use Illuminate\Support\Facades\Mail; 2 3Mail::raw('Thanks for your order.', function ($message) { 4 $message->from('hello@mail.example.com') 5 ->to('you@example.com') 6 ->replyTo('support@example.com') 7 ->subject('Your receipt'); 8});

Try it in php artisan tinker. The message then shows under Events in the dashboard. The transport posts to POST /api/v1/emails and does not return the API response.

To pass unique args, set an X-Capsule-Unique-Args header with a JSON object. The transport sends it as unique_args. The transport always uses your first cluster that is ready to send.

Attachments and templates

Attach a file

Use Laravel's attach. The transport base64-encodes each file for the API. Up to 10 files, 18 MB in total. See Attachments for allowed types.

attachment.php
1Mail::raw('Your invoice is attached.', function ($message) { 2 $message->from('hello@mail.example.com') 3 ->to('you@example.com') 4 ->subject('Your invoice') 5 ->attach(storage_path('app/invoice.pdf')); 6});

Mailables and Blade views work as usual. Hosted PostShiba templates go through the PHP client with template, not through the mailer.

Keep the key safe

Use a Send only key in your app. It can send email and call GET /api/v1/users/me. Every other request returns 403 forbidden.

If this key leaks Send only Full access
Send mail from your verified domains Yes Yes
Read events, recipients, templates, and sent messages No Yes
See SMTP passwords and webhook secrets No Yes
Change clusters, domains, credentials, webhooks, and suppressions No Yes
  • Keep Full access keys for setup scripts, the CLI, and MCP. Don't deploy one with your app.
  • Keep the key in POSTSHIBA_API_KEY in .env and read it through config/services.php, as in the setup. Don't commit .env, log the key, or put it in a URL.
  • Send from your server. Never put a key, even a Send only key, in a Blade view, a VITE_ variable, or mobile code.
  • Create one key per app and environment, each in that environment's .env. If a key leaks, delete it on API keys and create a new one. Deleting stops it straight away. Run php artisan config:clear after you put the new key in .env.

Troubleshooting

A failed send throws PostShiba\Error with error, field, and status. getMessage() holds the explanation.

Status error What to do
401 Invalid token or no user signed in The API key is missing, mistyped, or deleted. Check POSTSHIBA_API_KEY, then run php artisan config:clear.
403 forbidden Support keys cannot send. Use a Send only or Full access key. A Send only key gets this on any call other than sending.
403 domain_unverified from is not on a verified domain.
403 kyc_required Your team is pending production approval. Until then, send only to team members, live inbox addresses, and inbox forward-to addresses.
422 invalid field names the problem, such as a missing to or a rejected attachment.
429 throttled The cluster hit its hourly throttle or 24-hour cap. Retrying right away hits the same cap. For queued mail, release the job until after the hour. See What happens at your cap.
429 rate_limited More than 300 send requests in one minute on one API key. Slow down.

Every other status is on Errors.

Next steps