Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,7 @@ use Lettr\Exceptions\TransporterException;
use Lettr\Exceptions\ValidationException;
use Lettr\Exceptions\NotFoundException;
use Lettr\Exceptions\UnauthorizedException;
use Lettr\Exceptions\ForbiddenException;
use Lettr\Exceptions\ConflictException;
use Lettr\Exceptions\QuotaExceededException;
use Lettr\Exceptions\RateLimitException;
Expand All @@ -534,6 +535,9 @@ try {
} catch (UnauthorizedException $e) {
// Invalid API key (401)
echo "Authentication failed: " . $e->getMessage();
} catch (ForbiddenException $e) {
// Insufficient API key permissions (403)
echo "Forbidden: " . $e->getMessage();
} catch (NotFoundException $e) {
// Resource not found (404)
echo "Not found: " . $e->getMessage();
Expand Down
2 changes: 2 additions & 0 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Lettr\Dto\SendingQuota;
use Lettr\Exceptions\ApiException;
use Lettr\Exceptions\ConflictException;
use Lettr\Exceptions\ForbiddenException;
use Lettr\Exceptions\NotFoundException;
use Lettr\Exceptions\QuotaExceededException;
use Lettr\Exceptions\RateLimitException;
Expand Down Expand Up @@ -158,6 +159,7 @@ private function handleGuzzleException(GuzzleException $e): never

match ($statusCode) {
401 => throw new UnauthorizedException($message, $e),
403 => throw new ForbiddenException($message, $e),
404 => throw new NotFoundException($message, $e),
409 => throw new ConflictException($message, $e),
422 => throw new ValidationException(
Expand Down
3 changes: 3 additions & 0 deletions src/Enums/ErrorCode.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ enum ErrorCode: string
case InvalidRecipient = 'invalid_recipient';
case MessageTooLarge = 'message_too_large';
case AttachmentTooLarge = 'attachment_too_large';
case InsufficientScope = 'insufficient_scope';

/**
* Get a human-readable message for the error code.
Expand All @@ -44,6 +45,7 @@ public function message(): string
self::InvalidRecipient => 'One or more recipients are invalid.',
self::MessageTooLarge => 'The message exceeds the maximum size limit.',
self::AttachmentTooLarge => 'One or more attachments exceed the size limit.',
self::InsufficientScope => 'Your API key does not have the required permissions for this action.',
};
}

Expand All @@ -60,6 +62,7 @@ public function isClientError(): bool
self::DomainAlreadyExists,
self::WebhookNotFound,
self::InvalidApiKey,
self::InsufficientScope,
self::InvalidRecipient,
self::MessageTooLarge,
self::AttachmentTooLarge,
Expand Down
16 changes: 16 additions & 0 deletions src/Exceptions/ForbiddenException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace Lettr\Exceptions;

/**
* Exception thrown when the API key lacks required permissions (insufficient scope).
*/
final class ForbiddenException extends ApiException
{
public function __construct(string $message = 'Your API key does not have the required permissions for this action.', ?\Throwable $previous = null)
{
parent::__construct($message, 403, $previous);
}
}