diff --git a/composer.json b/composer.json
index b221f9d..b24cf97 100644
--- a/composer.json
+++ b/composer.json
@@ -19,9 +19,7 @@
         "php": "^8.4",
         "ext-curl": "*",
         "ext-json": "*",
-        "guzzlehttp/guzzle": "7.x",
         "illuminate/contracts": "^10.0||^11.0||^12.0",
-        "league/oauth2-client": "^2",
         "spatie/laravel-data": "^4.15",
         "spatie/laravel-package-tools": "^1.16"
     },
diff --git a/src/Concerns/InteractsWithHttpRequests.php b/src/Concerns/InteractsWithHttpRequests.php
new file mode 100644
index 0000000..8469568
--- /dev/null
+++ b/src/Concerns/InteractsWithHttpRequests.php
@@ -0,0 +1,82 @@
+<?php
+
+namespace Coderflex\LaravelSendy\Concerns;
+
+use Coderflex\LaravelSendy\Exceptions\InvalidApiKeyException;
+use Coderflex\LaravelSendy\Exceptions\InvalidApiUrlException;
+use Exception;
+use Illuminate\Support\Facades\Http;
+
+/**
+ * @method static \Illuminate\Http\Client\Response get(string $path, array $data = [], bool $async = false, array $headers = [])
+ * @method static \Illuminate\Http\Client\Response post(string $path, array $data = [], bool $async = false, array $headers = [])
+ * @method static \Illuminate\Http\Client\Response put(string $path, array $data = [], bool $async = false, array $headers = [])
+ * @method static \Illuminate\Http\Client\Response delete(string $path, array $data = [], bool $async = false, array $headers = [])
+ * @method static \Illuminate\Http\Client\Response patch(string $path, array $data = [], bool $async = false, array $headers = [])
+ */
+trait InteractsWithHttpRequests
+{
+    public function __call(string $function, array $args): mixed
+    {
+        $options = ['get', 'post', 'put', 'delete', 'patch'];
+        $path = $args[0] ?? null;
+        $data = $args[1] ?? [];
+        $async = $args[2] ?? false;
+        $headers = $args[3] ?? [];
+
+        if (! in_array($function, $options)) {
+            throw new Exception("Method {$function} not found.");
+        }
+
+        return self::sendRequest(
+            type: $function,
+            request: $path,
+            data: $data,
+            headers: $headers,
+            async: $async
+        );
+    }
+
+    /**
+     * @throws \Exception
+     */
+    protected function sendRequest(string $type, string $request, array $data = [], array $headers = [], bool $async = false): mixed
+    {
+        try {
+            $apiKey = config('laravel-sendy.api_key');
+            $apiUrl = config('laravel-sendy.api_url');
+
+            throw_if(
+                blank($apiKey),
+                InvalidApiKeyException::class,
+            );
+
+            throw_if(
+                blank($apiUrl),
+                InvalidApiUrlException::class,
+            );
+
+            $payload = array_merge($data, [
+                'api_key' => $apiKey,
+            ]);
+
+            $url = rtrim($apiUrl, '/').'/'.ltrim($request, '/');
+
+            $client = Http::withHeaders(array_merge([
+                'Content-Type' => 'application/json',
+                'Accept' => 'application/json',
+            ], $headers ?? []));
+
+            return $async
+                ? $client->async()->{$type}($url, $payload)
+                : $client->{$type}($url, $payload);
+
+        } catch (InvalidApiKeyException $th) {
+            throw new InvalidApiKeyException('Error: '.$th->getMessage());
+        } catch (InvalidApiUrlException $th) {
+            throw new InvalidApiUrlException('Error: '.$th->getMessage());
+        } catch (Exception $th) {
+            throw new Exception('Error: '.$th->getMessage());
+        }
+    }
+}
diff --git a/src/DTOs/CompaignDTO.php b/src/DTOs/Campaigns/CampaignDTO.php
similarity index 75%
rename from src/DTOs/CompaignDTO.php
rename to src/DTOs/Campaigns/CampaignDTO.php
index 9ec47e1..a2cf8cd 100644
--- a/src/DTOs/CompaignDTO.php
+++ b/src/DTOs/Campaigns/CampaignDTO.php
@@ -1,11 +1,11 @@
 <?php
 
-namespace Coderflex\LaravelSendy\DTOs;
+namespace Coderflex\LaravelSendy\DTOs\Campaigns;
 
 use Spatie\LaravelData\Data;
 use Spatie\LaravelData\Support\Validation\ValidationContext;
 
-class CompaignDTO extends Data
+class CampaignDTO extends Data
 {
     public function __construct(
         public string $from_name,
@@ -15,15 +15,15 @@ public function __construct(
         public string $subject,
         public ?string $plain_text,
         public string $html_text,
-        public string $list_ids,
-        public string $segment_ids,
+        public ?string $list_ids,
+        public ?string $segment_ids,
         public ?string $exclude_list_ids,
         public ?string $exclude_segment_ids,
-        public string $brand_id,
+        public ?string $brand_id,
         public ?string $query_string,
         public ?int $track_opens,
         public ?int $track_clicks,
-        public ?int $send_compaign,
+        public ?int $send_campaign,
         public ?string $schedule_date_time,
         public ?string $schedule_timezone,
     ) {}
@@ -38,15 +38,15 @@ public static function rules(ValidationContext $context): array
             'subject' => ['required', 'string'],
             'plain_text' => ['string', 'nullable'],
             'html_text' => ['required', 'string'],
-            'list_ids' => ['required', 'string'],
-            'segment_ids' => ['required', 'string'],
+            'list_ids' => ['required_if:send_campaign,1', 'string'],
+            'segment_ids' => ['required_if:send_campaign,1', 'string'],
             'exclude_list_ids' => ['string', 'nullable'],
             'exclude_segment_ids' => ['string', 'nullable'],
-            'brand_id' => ['required', 'string'],
+            'brand_id' => ['required_if:send_campaign,0', 'string'],
             'query_string' => ['string', 'nullable'],
             'track_opens' => ['integer', 'nullable', 'in:0,1,2'],
             'track_clicks' => ['integer', 'nullable', 'in:0,1,2'],
-            'send_compaign' => ['integer', 'nullable', 'in:0,1'],
+            'send_campaign' => ['integer', 'nullable', 'in:0,1'],
             'schedule_date_time' => ['date', 'nullable'],
             'schedule_timezone' => ['date', 'nullable'],
         ];
diff --git a/src/DTOs/Lists/ListsDTO.php b/src/DTOs/Lists/ListsDTO.php
new file mode 100644
index 0000000..0c99256
--- /dev/null
+++ b/src/DTOs/Lists/ListsDTO.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace Coderflex\LaravelSendy\DTOs\Lists;
+
+use Spatie\LaravelData\Data;
+use Spatie\LaravelData\Support\Validation\ValidationContext;
+
+class ListsDTO extends Data
+{
+    public function __construct(
+        public string $brand_id,
+        public ?string $include_hidden = 'no',
+    ) {}
+
+    public static function rules(ValidationContext $context): array
+    {
+        return [
+            'include_hidden' => ['in:yes,no'],
+        ];
+    }
+}
diff --git a/src/DTOs/Subscribers/DeleteSubscriberDTO.php b/src/DTOs/Subscribers/DeleteSubscriberDTO.php
new file mode 100644
index 0000000..a679be0
--- /dev/null
+++ b/src/DTOs/Subscribers/DeleteSubscriberDTO.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Coderflex\LaravelSendy\DTOs\Subscribers;
+
+use Spatie\LaravelData\Attributes\MergeValidationRules;
+use Spatie\LaravelData\Data;
+use Spatie\LaravelData\Support\Validation\ValidationContext;
+
+#[MergeValidationRules]
+class DeleteSubscriberDTO extends Data
+{
+    public function __construct(
+        public string $list_id,
+        public string $email,
+    ) {}
+
+    public static function rules(ValidationContext $context): array
+    {
+        return [
+            'email' => ['email'],
+        ];
+    }
+}
diff --git a/src/DTOs/SubscribersDTO.php b/src/DTOs/Subscribers/SubscribeDTO.php
similarity index 50%
rename from src/DTOs/SubscribersDTO.php
rename to src/DTOs/Subscribers/SubscribeDTO.php
index 0ba3734..ed32fdf 100644
--- a/src/DTOs/SubscribersDTO.php
+++ b/src/DTOs/Subscribers/SubscribeDTO.php
@@ -1,11 +1,13 @@
 <?php
 
-namespace Coderflex\LaravelSendy\DTOs;
+namespace Coderflex\LaravelSendy\DTOs\Subscribers;
 
+use Spatie\LaravelData\Attributes\MergeValidationRules;
 use Spatie\LaravelData\Data;
 use Spatie\LaravelData\Support\Validation\ValidationContext;
 
-class SubscribersDTO extends Data
+#[MergeValidationRules]
+class SubscribeDTO extends Data
 {
     public function __construct(
         public ?string $name,
@@ -22,15 +24,8 @@ public function __construct(
     public static function rules(ValidationContext $context): array
     {
         return [
-            'name' => ['string', 'nullable'],
-            'email' => ['required', 'string', 'email'],
-            'list' => ['required', 'string'],
-            'country' => ['string', 'nullable'],
-            'ipaddress' => ['string', 'nullable', 'ip'],
-            'referrer' => ['string', 'nullable'],
-            'gdpr' => ['boolean', 'nullable'],
-            'silent' => ['boolean', 'nullable'],
-            'boolean' => ['boolean', 'nullable'],
+            'email' => ['email'],
+            'ipaddress' => ['ip'],
         ];
     }
 }
diff --git a/src/DTOs/Subscribers/SubscriberStatusDTO.php b/src/DTOs/Subscribers/SubscriberStatusDTO.php
new file mode 100644
index 0000000..4c23a2b
--- /dev/null
+++ b/src/DTOs/Subscribers/SubscriberStatusDTO.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Coderflex\LaravelSendy\DTOs\Subscribers;
+
+use Spatie\LaravelData\Attributes\MergeValidationRules;
+use Spatie\LaravelData\Data;
+use Spatie\LaravelData\Support\Validation\ValidationContext;
+
+#[MergeValidationRules]
+class SubscriberStatusDTO extends Data
+{
+    public function __construct(
+        public string $list_id,
+        public string $email,
+    ) {}
+
+    public static function rules(ValidationContext $context): array
+    {
+        return [
+            'email' => ['email'],
+        ];
+    }
+}
diff --git a/src/DTOs/Subscribers/UnsubscribeDTO.php b/src/DTOs/Subscribers/UnsubscribeDTO.php
new file mode 100644
index 0000000..cb69897
--- /dev/null
+++ b/src/DTOs/Subscribers/UnsubscribeDTO.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Coderflex\LaravelSendy\DTOs\Subscribers;
+
+use Spatie\LaravelData\Attributes\MergeValidationRules;
+use Spatie\LaravelData\Data;
+use Spatie\LaravelData\Support\Validation\ValidationContext;
+
+#[MergeValidationRules]
+class UnsubscribeDTO extends Data
+{
+    public function __construct(
+        public string $list,
+        public string $email,
+        public ?bool $boolean = false, // plain text response
+    ) {}
+
+    public static function rules(ValidationContext $context): array
+    {
+        return [
+            'email' => ['email'],
+        ];
+    }
+}
diff --git a/src/Exceptions/CompaingException.php b/src/Exceptions/CompaingException.php
deleted file mode 100644
index f2aa4df..0000000
--- a/src/Exceptions/CompaingException.php
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-
-namespace Coderflex\LaravelSendy\DTOs;
-
-class CompaingException extends \Exception
-{
-    //
-}
diff --git a/src/Exceptions/InvalidApiKeyException.php b/src/Exceptions/InvalidApiKeyException.php
new file mode 100644
index 0000000..302f2e2
--- /dev/null
+++ b/src/Exceptions/InvalidApiKeyException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Coderflex\LaravelSendy\Exceptions;
+
+class InvalidApiKeyException extends \Exception
+{
+    protected $message = 'The API key is invalid. Please check your configuration and try again.';
+
+    protected $code = 401;
+}
diff --git a/src/Exceptions/InvalidApiUrlException.php b/src/Exceptions/InvalidApiUrlException.php
new file mode 100644
index 0000000..cc31a54
--- /dev/null
+++ b/src/Exceptions/InvalidApiUrlException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Coderflex\LaravelSendy\Exceptions;
+
+class InvalidApiUrlException extends \Exception
+{
+    protected $message = 'The API URL is invalid. Please check your configuration and try again.';
+
+    protected $code = 401;
+}
diff --git a/src/Exceptions/SubscribersException.php b/src/Exceptions/SubscribersException.php
deleted file mode 100644
index fbb1591..0000000
--- a/src/Exceptions/SubscribersException.php
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-
-namespace Coderflex\LaravelSendy\DTOs;
-
-class SubscribersException extends \Exception
-{
-    //
-}
diff --git a/src/Facades/LaravelSendy.php b/src/Facades/LaravelSendy.php
index 702b104..f98ecbc 100644
--- a/src/Facades/LaravelSendy.php
+++ b/src/Facades/LaravelSendy.php
@@ -6,6 +6,11 @@
 
 /**
  * @see \Coderflex\LaravelSendy\LaravelSendy
+ *
+ * @method static \Coderflex\LaravelSendy\Resources\Subscribers subscribers()
+ * @method static \Coderflex\LaravelSendy\Resources\Lists lists()
+ * @method static \Coderflex\LaravelSendy\Resources\Brands brands()
+ * @method static \Coderflex\LaravelSendy\Resources\Campaigns campaigns()
  */
 class LaravelSendy extends Facade
 {
diff --git a/src/LaravelSendy.php b/src/LaravelSendy.php
index 5dd50c2..59e7257 100644
--- a/src/LaravelSendy.php
+++ b/src/LaravelSendy.php
@@ -2,113 +2,29 @@
 
 namespace Coderflex\LaravelSendy;
 
-use Coderflex\LaravelSendy\Resources\Resources\Brands;
-use Coderflex\LaravelSendy\Resources\Resources\Campaigns;
-use Coderflex\LaravelSendy\Resources\Resources\Lists;
-use Coderflex\LaravelSendy\Resources\Resources\Subscribers;
-use Exception;
-use GuzzleHttp\Client;
-use GuzzleHttp\Exception\ClientException;
+use Coderflex\LaravelSendy\Concerns\InteractsWithHttpRequests;
 
 class LaravelSendy
 {
-    protected string $apiKey;
+    use InteractsWithHttpRequests;
 
-    protected string $apiUrl;
-
-    public function __construct()
-    {
-        if (blank(config('laravel-sendy.api_key'))) {
-            throw new Exception('API Key is not set in the config file.');
-        }
-
-        if (blank(config('laravel-sendy.api_url'))) {
-            throw new Exception('API URL is not set in the config file.');
-        }
-
-        $this->apiKey = config('laravel-sendy.api_key');
-        $this->apiUrl = config('laravel-sendy.api_url');
-    }
-
-    public function subscribers(): Subscribers
-    {
-        return new Subscribers;
-    }
-
-    public function lists(): Lists
-    {
-        return new Lists;
-    }
-
-    public function brands(): Brands
+    public function subscribers(): Resources\Subscribers
     {
-        return new Brands;
+        return new Resources\Subscribers;
     }
 
-    public function campaigns(): Campaigns
+    public function lists(): Resources\Lists
     {
-        return new Campaigns;
+        return new Resources\Lists;
     }
 
-    public function __call(string $function, array $args)
+    public function brands(): Resources\Brands
     {
-        $options = ['get', 'post', 'put', 'delete', 'patch'];
-        $path = (isset($args[0])) ? $args[0] : null;
-        $data = (isset($args[1])) ? $args[1] : [];
-        $headers = (isset($args[2])) ? $args[2] : [];
-
-        if (! in_array($function, $options)) {
-            throw new Exception("Method {$function} not found.");
-        }
-
-        return self::guzzle(
-            type: $function,
-            request: $path,
-            data: $data,
-            headers: $headers
-        );
-    }
-
-    /**
-     * @throws \Exception
-     */
-    protected function guzzle(string $type, string $request, array $data = [], array $headers = []): mixed
-    {
-        try {
-            $client = new Client;
-
-            $mainHeaders = [
-                'Content-Type' => 'application/json',
-                'Accept' => 'application/json',
-            ];
-
-            $headers = is_array($headers) && count($headers) > 0
-                ? array_merge($mainHeaders, $headers)
-                : $mainHeaders;
-
-            $response = $client->{$type}($this->apiUrl.$request, [
-                'headers' => $headers,
-                'body' => json_encode(array_merge($data, [
-                    'api_key' => $this->apiKey,
-                ])),
-            ]);
-
-            $responseObject = $response->getBody()->getContents();
-
-            return $this->isJson($responseObject)
-                ? json_decode($responseObject, true)
-                : $responseObject;
-
-        } catch (ClientException $th) {
-            throw new Exception('Error: '.$th->getMessage());
-        } catch (Exception $th) {
-            throw new Exception('Error: '.$th->getMessage());
-        }
+        return new Resources\Brands;
     }
 
-    protected function isJson(string $string): bool
+    public function campaigns(): Resources\Campaigns
     {
-        return is_array(json_decode($string)) &&
-            (json_last_error() === JSON_ERROR_NONE);
+        return new Resources\Campaigns;
     }
 }
diff --git a/src/Resources/Brands.php b/src/Resources/Brands.php
index 03da1af..ba94cf1 100644
--- a/src/Resources/Brands.php
+++ b/src/Resources/Brands.php
@@ -1,6 +1,6 @@
 <?php
 
-namespace Coderflex\LaravelSendy\Resources\Resources;
+namespace Coderflex\LaravelSendy\Resources;
 
 use Coderflex\LaravelSendy\Facades\LaravelSendy;
 
@@ -8,6 +8,6 @@ class Brands
 {
     public function get()
     {
-        return LaravelSendy::get('/api/brands/get-brands.php');
+        return LaravelSendy::post('/api/brands/get-brands.php');
     }
 }
diff --git a/src/Resources/Campaigns.php b/src/Resources/Campaigns.php
index 3d2f861..b3fb387 100644
--- a/src/Resources/Campaigns.php
+++ b/src/Resources/Campaigns.php
@@ -1,15 +1,15 @@
 <?php
 
-namespace Coderflex\LaravelSendy\Resources\Resources;
+namespace Coderflex\LaravelSendy\Resources;
 
-use Coderflex\LaravelSendy\DTOs\CompaignDTO;
+use Coderflex\LaravelSendy\DTOs\Campaigns\CampaignDTO;
 use Coderflex\LaravelSendy\Facades\LaravelSendy;
 
 class Campaigns
 {
     public function create(array $data)
     {
-        $data = CompaignDTO::validateAndCreate($data)->toArray();
+        $data = CampaignDTO::validate($data);
 
         return LaravelSendy::post('/api/campaigns/create.php', $data);
     }
diff --git a/src/Resources/Lists.php b/src/Resources/Lists.php
index 82a5f78..dde78e3 100644
--- a/src/Resources/Lists.php
+++ b/src/Resources/Lists.php
@@ -1,7 +1,8 @@
 <?php
 
-namespace Coderflex\LaravelSendy\Resources\Resources;
+namespace Coderflex\LaravelSendy\Resources;
 
+use Coderflex\LaravelSendy\DTOs\Lists\ListsDTO;
 use Coderflex\LaravelSendy\Facades\LaravelSendy;
 
 class Lists
@@ -11,13 +12,10 @@ class Lists
      *
      * @return array
      */
-    public function get(int $brandId, bool $includeHidden = false)
+    public function get(array $data, bool $async = false)
     {
-        $params = http_build_query([
-            'brand_id' => $brandId,
-            'include_hidden' => $includeHidden,
-        ]);
+        $data = ListsDTO::validate($data);
 
-        return LaravelSendy::get('/api/lists/get-lists.php', $params);
+        return LaravelSendy::post('/api/lists/get-lists.php', $data, $async);
     }
 }
diff --git a/src/Resources/Subscribers.php b/src/Resources/Subscribers.php
index 10879de..61500b1 100644
--- a/src/Resources/Subscribers.php
+++ b/src/Resources/Subscribers.php
@@ -1,56 +1,49 @@
 <?php
 
-namespace Coderflex\LaravelSendy\Resources\Resources;
+namespace Coderflex\LaravelSendy\Resources;
 
-use Coderflex\LaravelSendy\DTOs\SubscribersDTO;
+use Coderflex\LaravelSendy\DTOs\Subscribers\DeleteSubscriberDTO;
+use Coderflex\LaravelSendy\DTOs\Subscribers\SubscribeDTO;
+use Coderflex\LaravelSendy\DTOs\Subscribers\SubscriberStatusDTO;
+use Coderflex\LaravelSendy\DTOs\Subscribers\UnsubscribeDTO;
 use Coderflex\LaravelSendy\Facades\LaravelSendy;
 
 class Subscribers
 {
-    public function subscribe(array $data)
+    public function subscribe(array $data, bool $async = false)
     {
-        $data = SubscribersDTO::validateAndCreate($data)->toArray();
+        $data = SubscribeDTO::validate($data);
 
-        return LaravelSendy::post('subscribe', $data);
+        return LaravelSendy::post('subscribe', $data, $async);
     }
 
-    public function unsubscribe(int $listId, string $email, bool $plainTextResponse)
+    public function unsubscribe(array $data, bool $async = false)
     {
-        $data = http_build_query([
-            'list' => $listId,
-            'email' => $email,
-            'boolean' => $plainTextResponse,
-        ]);
+        $data = UnsubscribeDTO::validate($data);
 
-        return LaravelSendy::post('/api/subscribers/unsubscribe.php', $data);
+        return LaravelSendy::post('api/subscribers/unsubscribe.php', $data, $async);
     }
 
-    public function delete(int $listId, string $email)
+    public function delete(array $data, bool $async = false)
     {
-        $data = http_build_query([
-            'list_id' => $listId,
-            'email' => $email,
-        ]);
+        $data = DeleteSubscriberDTO::validate($data);
 
-        return LaravelSendy::post('/api/subscribers/delete.php', $data);
+        return LaravelSendy::post('api/subscribers/delete.php', $data, $async);
     }
 
-    public function status(int $listId, string $email)
+    public function status(array $data, bool $async = false)
     {
-        $data = http_build_query([
-            'list_id' => $listId,
-            'email' => $email,
-        ]);
+        $data = SubscriberStatusDTO::validate($data);
 
-        return LaravelSendy::post('/api/subscribers/subscription-status.php', $data);
+        return LaravelSendy::post('api/subscribers/subscription-status.php', $data, $async);
     }
 
-    public function count(int $listId)
+    public function count(int $listId, bool $async = false)
     {
-        $data = http_build_query([
+        $data = [
             'list_id' => $listId,
-        ]);
+        ];
 
-        return LaravelSendy::post('/api/subscribers/active-subscriber-count.php', $data);
+        return LaravelSendy::post('api/subscribers/subscriber-count.php', $data, $async);
     }
 }
diff --git a/tests/ExampleTest.php b/tests/ExampleTest.php
deleted file mode 100644
index 5d36321..0000000
--- a/tests/ExampleTest.php
+++ /dev/null
@@ -1,5 +0,0 @@
-<?php
-
-it('can test', function () {
-    expect(true)->toBeTrue();
-});
diff --git a/tests/Resources/BrandsTest.php b/tests/Resources/BrandsTest.php
new file mode 100644
index 0000000..3e98357
--- /dev/null
+++ b/tests/Resources/BrandsTest.php
@@ -0,0 +1,26 @@
+<?php
+
+use Coderflex\LaravelSendy\Facades\LaravelSendy;
+use Illuminate\Support\Facades\Http;
+
+beforeEach(function () {
+    config([
+        'laravel-sendy.api_key' => 'test_api_key',
+        'laravel-sendy.api_url' => 'https://sendy.test/',
+    ]);
+});
+
+it('can get subscriber brands', function () {
+    Http::fake([
+        'https://sendy.test/api/brands/get-brands.php' => Http::response([123 => 'Brand Name'], 200),
+    ]);
+
+    $response = LaravelSendy::brands()->get();
+
+    expect($response->json())->toBe([123 => 'Brand Name']);
+
+    Http::assertSent(function ($request) {
+        return $request->url() === 'https://sendy.test/api/brands/get-brands.php' &&
+               $request['api_key'] === 'test_api_key';
+    });
+});
diff --git a/tests/Resources/CompaignsTest.php b/tests/Resources/CompaignsTest.php
new file mode 100644
index 0000000..cd83292
--- /dev/null
+++ b/tests/Resources/CompaignsTest.php
@@ -0,0 +1,47 @@
+<?php
+
+use Coderflex\LaravelSendy\Facades\LaravelSendy;
+use Illuminate\Support\Facades\Http;
+
+beforeEach(function () {
+    config([
+        'laravel-sendy.api_key' => 'test_api_key',
+        'laravel-sendy.api_url' => 'https://sendy.test/',
+    ]);
+});
+
+it('can create and send a campaigns', function () {
+    Http::fake([
+        'https://sendy.test/api/campaigns/create.php' => Http::response(['status' => 'Campaign created and now sending'], 200),
+    ]);
+
+    $response = LaravelSendy::campaigns()->create([
+        'subject' => 'Test Subject',
+        'from_name' => 'John Doe',
+        'from_email' => 'john@example.com',
+        'reply_to' => 'alex@example.com',
+        'title' => 'Test Title',
+        'plain_text' => 'This is a plain text version of the email.',
+        'html_text' => '<h1>This is a HTML version of the email.</h1>',
+        'list_ids' => 'abc123',
+        'segment_ids' => 'xyz456',
+        'exclude_list_ids' => null,
+        'exclude_segment_ids' => null,
+        'brand_id' => 'brand123',
+        'query_string' => null,
+        'track_opens' => 1,
+        'track_clicks' => 1,
+        'send_campaign' => 1,
+        'schedule_date_time' => null,
+        'schedule_timezone' => null,
+    ]);
+
+    expect($response->json())->toBe(['status' => 'Campaign created and now sending']);
+
+    Http::assertSent(function ($request) {
+        return $request->url() === 'https://sendy.test/api/campaigns/create.php' &&
+               $request['from_email'] === 'john@example.com' &&
+               $request['from_name'] === 'John Doe' &&
+               $request['api_key'] === 'test_api_key';
+    });
+});
diff --git a/tests/Resources/EndpointsTest.php b/tests/Resources/EndpointsTest.php
new file mode 100644
index 0000000..e0a72b2
--- /dev/null
+++ b/tests/Resources/EndpointsTest.php
@@ -0,0 +1,32 @@
+<?php
+
+use Coderflex\LaravelSendy\Facades\LaravelSendy;
+use Illuminate\Support\Facades\Http;
+
+it('throw and exception if the api key not defined', function () {
+    config([
+        'laravel-sendy.api_key' => null,
+        'laravel-sendy.api_url' => 'https://sendy.test',
+    ]);
+
+    Http::fake([
+        'https://sendy.test/api/brands/get-brands.php' => Http::response(true, 200),
+    ]);
+
+    $response = LaravelSendy::brands()->get();
+
+})->throws(\Coderflex\LaravelSendy\Exceptions\InvalidApiKeyException::class);
+
+it('throw and exception if the api url not defined', function () {
+    Http::fake([
+        'https://sendy.test/api/brands/get-brands.php' => Http::response(true, 200),
+    ]);
+
+    config([
+        'laravel-sendy.api_key' => 'test_api_key',
+        'laravel-sendy.api_url' => null,
+    ]);
+
+    $response = LaravelSendy::brands()->get();
+
+})->throws(\Coderflex\LaravelSendy\Exceptions\InvalidApiUrlException::class);
diff --git a/tests/Resources/ListsTest.php b/tests/Resources/ListsTest.php
new file mode 100644
index 0000000..87a7b6d
--- /dev/null
+++ b/tests/Resources/ListsTest.php
@@ -0,0 +1,31 @@
+<?php
+
+use Coderflex\LaravelSendy\Facades\LaravelSendy;
+use Illuminate\Support\Facades\Http;
+
+beforeEach(function () {
+    config([
+        'laravel-sendy.api_key' => 'test_api_key',
+        'laravel-sendy.api_url' => 'https://sendy.test/',
+    ]);
+});
+
+it('can get subscriber lists', function () {
+    Http::fake([
+        'https://sendy.test/api/lists/get-lists.php' => Http::response([123 => 'Custom List'], 200),
+    ]);
+
+    $response = LaravelSendy::lists()->get([
+        'brand_id' => 123,
+        'include_hidden' => 'yes',
+    ]);
+
+    expect($response->json())->toBe([123 => 'Custom List']);
+
+    Http::assertSent(function ($request) {
+        return $request->url() === 'https://sendy.test/api/lists/get-lists.php' &&
+               $request['brand_id'] === 123 &&
+               $request['include_hidden'] === 'yes' &&
+               $request['api_key'] === 'test_api_key';
+    });
+});
diff --git a/tests/Resources/SubscribersTest.php b/tests/Resources/SubscribersTest.php
new file mode 100644
index 0000000..7d7ba94
--- /dev/null
+++ b/tests/Resources/SubscribersTest.php
@@ -0,0 +1,93 @@
+<?php
+
+use Coderflex\LaravelSendy\Facades\LaravelSendy;
+use Illuminate\Support\Facades\Http;
+
+beforeEach(function () {
+    config([
+        'laravel-sendy.api_key' => 'test_api_key',
+        'laravel-sendy.api_url' => 'https://sendy.test/',
+    ]);
+});
+
+it('can subscribe a user', function () {
+    Http::fake([
+        'https://sendy.test/subscribe' => Http::response(true, 200),
+    ]);
+
+    $response = LaravelSendy::subscribers()->subscribe([
+        'name' => 'John Doe',
+        'email' => 'john@example.com',
+        'list' => 'abc123',
+        'country' => 'UAE',
+    ]);
+
+    expect($response->json())->toBe(1);
+
+    Http::assertSent(function ($request) {
+        return $request->url() === 'https://sendy.test/subscribe' &&
+               $request['email'] === 'john@example.com' &&
+               $request['list'] === 'abc123' &&
+               $request['api_key'] === 'test_api_key';
+    });
+});
+
+it('can unsubscribe a user', function () {
+    Http::fake([
+        'https://sendy.test/api/subscribers/unsubscribe.php' => Http::response(true, 200),
+    ]);
+
+    $response = LaravelSendy::subscribers()->unsubscribe([
+        'list' => 123,
+        'email' => 'jane@example.com',
+        'boolean' => true,
+    ]);
+
+    expect($response->json())->toBe(1);
+
+    Http::assertSent(function ($request) {
+        return $request->url() === 'https://sendy.test/api/subscribers/unsubscribe.php' &&
+               $request['email'] === 'jane@example.com' &&
+               $request['list'] === 123;
+    });
+});
+
+it('can delete a subscriber', function () {
+    Http::fake([
+        'https://sendy.test/api/subscribers/delete.php' => Http::response(true, 200),
+    ]);
+
+    $response = LaravelSendy::subscribers()->delete([
+        'list_id' => 123,
+        'email' => 'john@example.com',
+    ]);
+
+    expect($response->json())->toBe(1);
+
+    Http::assertSent(fn ($request) => $request['email'] === 'john@example.com' &&
+        $request['list_id'] === 123
+    );
+});
+
+it('can get subscriber status', function () {
+    Http::fake([
+        'https://sendy.test/api/subscribers/subscription-status.php' => Http::response(['status' => 'Subscribed'], 200),
+    ]);
+
+    $response = LaravelSendy::subscribers()->status([
+        'list_id' => 123,
+        'email' => 'john@example.com',
+    ]);
+
+    expect($response->json())->toBe(['status' => 'Subscribed']);
+});
+
+it('can get subscriber count', function () {
+    Http::fake([
+        'https://sendy.test/api/subscribers/subscriber-count.php' => Http::response(25, 200),
+    ]);
+
+    $response = LaravelSendy::subscribers()->count(123);
+
+    expect($response->json())->toBe(25);
+});