emeq / moneybird
Laravel package for Moneybird integration with OAuth token management
Fund package maintenance!
:vendor_name
Installs: 7
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/emeq/moneybird
Requires
- php: ^8.3
- illuminate/contracts: ^12.0
- picqer/moneybird-php-client: ^0.42.0
- spatie/laravel-package-tools: ^1.19
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/framework: ^12.25
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^10.0
- pestphp/pest: ^4.0
- pestphp/pest-plugin-arch: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
- spatie/laravel-ray: ^1.35
This package is auto-updated.
Last update: 2025-11-23 22:13:43 UTC
README
Laravel package for Moneybird integration with OAuth token management and extended API features.
Installation
You can install the package via composer:
composer require emeq/moneybird
The package will automatically publish the config file and migration to your application during installation. If you need to republish them manually:
# Publish config file php artisan vendor:publish --tag="moneybird-config" # Publish migrations php artisan vendor:publish --tag="moneybird-migrations"
After installation, run the migrations:
php artisan migrate
Configuration
Add the following environment variables to your .env file:
MONEYBIRD_CLIENT_ID=your_client_id MONEYBIRD_CLIENT_SECRET=your_client_secret MONEYBIRD_REDIRECT_URI=https://your-app.com/moneybird/callback MONEYBIRD_WEBHOOK_SECRET=your_webhook_secret MONEYBIRD_API_TIMEOUT=30
OAuth Setup
- Create a Moneybird application at https://moneybird.com/oauth/applications
- Set your redirect URI to match
MONEYBIRD_REDIRECT_URI(e.g.,https://your-app.com/moneybird/auth/callback) - Copy the Client ID and Client Secret to your
.envfile
Usage
Connecting to Moneybird
Via Routes (Recommended for Web Applications)
The package provides web routes for easy OAuth connection:
-
Start the connection: Visit
/moneybird/connectwhile authenticated- This route requires authentication (
authmiddleware) - It will redirect you to Moneybird's authorization page
- This route requires authentication (
-
Handle the callback: After authorization, Moneybird redirects to
/moneybird/auth/callback- The callback route automatically exchanges the authorization code for tokens
- On success, you'll be redirected to your dashboard with a success message
- On error, you'll be redirected with an error message
Example in your Blade template:
<a href="{{ route('moneybird.connect') }}" class="btn btn-primary"> Connect to Moneybird </a>
Example redirect in your controller:
return redirect()->route('moneybird.connect');
Via Artisan Command
Use the artisan command for CLI-based connections:
php artisan moneybird:connect --user-id=1
Programmatically
use Emeq\Moneybird\Services\OAuthService; $oauthService = app(OAuthService::class); $authorizationUrl = $oauthService->getAuthorizationUrl(); // Redirect user to $authorizationUrl // After authorization, exchange the code: $connection = $oauthService->exchangeCodeForTokens($authorizationCode, $userId);
Testing the Connection
Via Routes
After connecting, you can test the connection by accessing any route that uses the Moneybird service. The package will automatically handle token refresh if needed.
Example test route in your application:
Route::middleware('auth')->get('/moneybird/test', function () { $userId = auth()->id(); $service = \Emeq\Moneybird\Facades\Moneybird::connection($userId); try { $administrations = $service->administrations()->list(); return response()->json([ 'success' => true, 'message' => 'Connection successful!', 'administrations' => $administrations, ]); } catch (\Exception $e) { return response()->json([ 'success' => false, 'message' => 'Connection failed: ' . $e->getMessage(), ], 500); } });
Via Artisan Command
php artisan moneybird:test-connection --user-id=1
Using the Moneybird Service
use Emeq\Moneybird\Facades\Moneybird; // Get connection for a user $service = Moneybird::connection($userId); // Or for a specific connection $service = Moneybird::connection(connectionId: $connectionId); // List administrations $administrations = $service->administrations()->list(); // Work with contacts $contacts = $service->contacts()->list(); $contact = $service->contacts()->create([ 'company_name' => 'Example Company', 'email' => 'contact@example.com', ]); // Work with sales invoices $invoices = $service->salesInvoices()->list(); $invoice = $service->salesInvoices()->create([ 'contact_id' => $contact->id, 'invoice_date' => now()->format('Y-m-d'), 'details' => [ [ 'description' => 'Product 1', 'price' => 100.00, 'amount' => 1, ], ], ]); // Find invoice by invoice ID (invoice number) $invoice = $service->salesInvoices()->findByInvoiceId('2023-001'); // Send invoice $service->salesInvoices()->send($invoice->id); // Work with webhooks $webhooks = $service->webhooks()->list(); $webhook = $service->webhooks()->create([ 'url' => 'https://your-app.com/moneybird/webhook', 'enabled_events' => ['sales_invoice.created', 'contact.updated'], ]);
API Routes
The package provides RESTful API routes for accessing Moneybird data. All routes are prefixed with /api/moneybird and require Laravel Sanctum authentication.
Authentication
All API routes require authentication via Laravel Sanctum. Include the Bearer token in the Authorization header:
Authorization: Bearer {your-sanctum-token}
Connection Parameters
You can specify which Moneybird connection to use by including one of these query parameters:
connection_id- Use a specific connection by IDuser_id- Use the first active connection for a usertenant_id- Use the first active connection for a tenant- If none provided, uses the first active connection
Example:
GET /api/moneybird/administrations?connection_id=1
GET /api/moneybird/contacts?user_id=5&tenant_id=tenant1
Response Format
All endpoints return JSON with the following structure:
Success:
{
"success": true,
"data": { ... }
}
Error:
{
"success": false,
"message": "Error message"
}
Available Endpoints
Administrations
GET /api/moneybird/administrations- List all administrationsGET /api/moneybird/administrations/{id}- Get a specific administration
Example:
curl -X GET "https://your-app.com/api/moneybird/administrations" \ -H "Authorization: Bearer {token}" \ -H "Accept: application/json"
Contacts
GET /api/moneybird/contacts- List all contacts (supports filters:firstname,lastname,company_name,email)GET /api/moneybird/contacts/search?q={query}- Search contactsGET /api/moneybird/contacts/{id}- Get a specific contactPOST /api/moneybird/contacts- Create a new contactPUT /api/moneybird/contacts/{id}- Update a contactDELETE /api/moneybird/contacts/{id}- Delete a contact
Examples:
# List contacts with filters curl -X GET "https://your-app.com/api/moneybird/contacts?firstname=John&lastname=Doe" \ -H "Authorization: Bearer {token}" # Search contacts curl -X GET "https://your-app.com/api/moneybird/contacts/search?q=john" \ -H "Authorization: Bearer {token}" # Create a contact curl -X POST "https://your-app.com/api/moneybird/contacts" \ -H "Authorization: Bearer {token}" \ -H "Content-Type: application/json" \ -d '{ "firstname": "John", "lastname": "Doe", "email": "john@example.com" }' # Update a contact curl -X PUT "https://your-app.com/api/moneybird/contacts/123456" \ -H "Authorization: Bearer {token}" \ -H "Content-Type: application/json" \ -d '{ "firstname": "Jane", "lastname": "Doe" }'
Sales Invoices
GET /api/moneybird/sales-invoices- List all sales invoices (supports filters:contact_id,state,invoice_id)GET /api/moneybird/sales-invoices/by-invoice-id/{invoiceId}- Find invoice by invoice numberGET /api/moneybird/sales-invoices/{id}- Get a specific sales invoicePOST /api/moneybird/sales-invoices- Create a new sales invoicePUT /api/moneybird/sales-invoices/{id}- Update a sales invoiceDELETE /api/moneybird/sales-invoices/{id}- Delete a sales invoicePOST /api/moneybird/sales-invoices/{id}/send- Send a sales invoiceGET /api/moneybird/sales-invoices/{id}/download/pdf- Download invoice as PDFGET /api/moneybird/sales-invoices/{id}/download/ubl- Download invoice as UBL
Examples:
# List invoices with filters curl -X GET "https://your-app.com/api/moneybird/sales-invoices?contact_id=123456&state=open" \ -H "Authorization: Bearer {token}" # Find by invoice ID curl -X GET "https://your-app.com/api/moneybird/sales-invoices/by-invoice-id/INV-2024-001" \ -H "Authorization: Bearer {token}" # Create an invoice curl -X POST "https://your-app.com/api/moneybird/sales-invoices" \ -H "Authorization: Bearer {token}" \ -H "Content-Type: application/json" \ -d '{ "contact_id": "123456", "invoice_id": "INV-2024-001", "details": [ { "description": "Product 1", "price": 100.00, "amount": 1 } ] }' # Send an invoice curl -X POST "https://your-app.com/api/moneybird/sales-invoices/123456/send" \ -H "Authorization: Bearer {token}" \ -H "Content-Type: application/json" \ -d '{ "delivery_method": "Email", "email_address": "customer@example.com" }' # Download PDF curl -X GET "https://your-app.com/api/moneybird/sales-invoices/123456/download/pdf" \ -H "Authorization: Bearer {token}" \ --output invoice.pdf
Webhooks
GET /api/moneybird/webhooks- List all webhooksPOST /api/moneybird/webhooks- Create a new webhookDELETE /api/moneybird/webhooks/{id}- Delete a webhook
Examples:
# List webhooks curl -X GET "https://your-app.com/api/moneybird/webhooks" \ -H "Authorization: Bearer {token}" # Create a webhook curl -X POST "https://your-app.com/api/moneybird/webhooks" \ -H "Authorization: Bearer {token}" \ -H "Content-Type: application/json" \ -d '{ "url": "https://your-app.com/moneybird/webhook", "events": ["sales_invoice.created", "contact.updated"] }' # Delete a webhook curl -X DELETE "https://your-app.com/api/moneybird/webhooks/123456" \ -H "Authorization: Bearer {token}"
Webhooks
The package automatically registers a webhook route at /moneybird/webhook (configurable in config/moneybird.php).
Listen to webhook events:
use Emeq\Moneybird\Events\SalesInvoiceCreated; use Emeq\Moneybird\Events\ContactUpdated; Event::listen(SalesInvoiceCreated::class, function ($event) { // Handle sales invoice created $invoiceData = $event->payload; }); Event::listen(ContactUpdated::class, function ($event) { // Handle contact updated $contactData = $event->payload; });
Commands
php artisan moneybird:connect- Connect to Moneybird via OAuthphp artisan moneybird:test-connection- Test an existing connectionphp artisan moneybird:refresh-tokens- Refresh expired tokens
Features
- OAuth 2.0 authentication with automatic token refresh
- Database-backed token storage
- Support for multiple administrations
- Extended API features:
- Contacts (CRUD operations)
- Sales Invoices (create, update, send, download, findByInvoiceId)
- Webhooks (create, list, delete)
- Administrations (list, get)
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
License
The MIT License (MIT). Please see License File for more information. EMEQ