PHPackages                             nusii/nusii-php - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. nusii/nusii-php

ActiveLibrary[API Development](/categories/api)

nusii/nusii-php
===============

PHP client library for the Nusii proposal software API

v1.1.0(3mo ago)00MITPHPPHP ^8.3

Since Mar 10Pushed 3mo agoCompare

[ Source](https://github.com/Nusii/nusii-php)[ Packagist](https://packagist.org/packages/nusii/nusii-php)[ Docs](https://github.com/Nusii/nusii-php)[ RSS](/packages/nusii-nusii-php/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (1)Dependencies (2)Versions (3)Used By (0)

Nusii PHP
=========

[](#nusii-php)

A PHP client library for the [Nusii](https://nusii.com) proposal software API.

Requires **PHP 8.3+** and uses [Guzzle](https://docs.guzzlephp.org/) for HTTP requests.

Installation
------------

[](#installation)

Install via Composer:

```
composer require nusii/nusii-php
```

Quick Start
-----------

[](#quick-start)

```
use Nusii\Nusii;

$nusii = new Nusii('your-api-key');

// List your clients
$clients = $nusii->clients()->list();

foreach ($clients as $client) {
    echo $client['name'] . "\n";
}
```

### Custom Base URL

[](#custom-base-url)

For self-hosted or development environments:

```
$nusii = new Nusii('your-api-key', baseUrl: 'http://localhost:3000');
```

Resources
---------

[](#resources)

### Account

[](#account)

```
// Get current account
$account = $nusii->accounts()->me();

echo $account['name'];       // "Acme Corp"
echo $account['email'];      // "owner@acme.com"
echo $account['currency'];   // "USD"
echo $account['subdomain'];  // "acme"
```

### Clients

[](#clients)

```
// List clients (paginated)
$clients = $nusii->clients()->list(page: 1, perPage: 10);

echo $clients->totalCount;   // 42
echo $clients->currentPage;  // 1
echo $clients->totalPages;   // 5

foreach ($clients as $client) {
    echo $client['name'];
}

// Get a single client
$client = $nusii->clients()->get(id: 123);

// Create a client
$client = $nusii->clients()->create([
    'name' => 'John',
    'surname' => 'Doe',
    'email' => 'john@example.com',
    'business' => 'Acme Inc',
    'telephone' => '555-1234',
    'address' => '123 Main St',
    'city' => 'New York',
    'postcode' => '10001',
    'country' => 'US',
    'state' => 'NY',
    'web' => 'https://acme.com',
    'currency' => 'USD',
    'locale' => 'en',
]);

// Update a client
$client = $nusii->clients()->update(123, [
    'name' => 'Jane',
    'business' => 'Updated Corp',
]);

// Delete a client
$nusii->clients()->delete(123);
```

### Proposals

[](#proposals)

```
// List proposals
$proposals = $nusii->proposals()->list();

// Filter by status: draft, pending, accepted, rejected
$drafts = $nusii->proposals()->list(status: 'draft');

// Filter archived proposals
$archived = $nusii->proposals()->list(archived: true);

// Get a single proposal
$proposal = $nusii->proposals()->get(456);

// Create a proposal
$proposal = $nusii->proposals()->create([
    'title' => 'Website Redesign',
    'client_id' => 123,
    'expires_at' => '2025-12-31',
    'currency' => 'EUR',
    'theme' => 'clean',
]);

// Update a proposal
$proposal = $nusii->proposals()->update(456, [
    'title' => 'Updated Proposal Title',
]);

// Send a proposal
$result = $nusii->proposals()->send(
    id: 456,
    email: 'client@example.com',
    subject: 'Your Proposal',            // optional
    message: 'Please review attached.',   // optional
    cc: 'manager@example.com',            // optional
    bcc: 'archive@example.com',           // optional
);

// Archive a proposal
$proposal = $nusii->proposals()->archive(456);

// Delete a proposal
$nusii->proposals()->delete(456);
```

### Sections

[](#sections)

```
// List all sections
$sections = $nusii->sections()->list();

// List sections for a specific proposal
$sections = $nusii->sections()->list(proposalId: 456);

// List sections for a specific template
$sections = $nusii->sections()->list(templateId: 789);

// Include line items in the response
$sections = $nusii->sections()->list(proposalId: 456, includeLineItems: true);

// Get a single section
$section = $nusii->sections()->get(10);

// Create a section
$section = $nusii->sections()->create([
    'proposal_id' => 456,
    'title' => 'Project Scope',
    'body' => 'Detailed project scope description.',
    'position' => 1,
    'section_type' => 'cost',    // "cost" or "text"
    'optional' => false,
    'include_total' => true,
    'page_break' => false,
]);

// Update a section
$section = $nusii->sections()->update(10, [
    'title' => 'Updated Section Title',
    'body' => 'Updated content.',
]);

// Delete a section
$nusii->sections()->delete(10);
```

### Line Items

[](#line-items)

Line items belong to sections. They must be created under a section.

```
// List line items for a section
$items = $nusii->lineItems()->listBySection(sectionId: 10);

// Get a single line item
$item = $nusii->lineItems()->get(50);

// Create a line item for a section
$item = $nusii->lineItems()->createForSection(sectionId: 10, attributes: [
    'name' => 'Design Work',
    'quantity' => 10,
    'amount' => 7500,          // in cents
    'cost_type' => 'fixed',    // "fixed" or "hourly"
    'per_type' => 'hour',
    'position' => 1,
]);

// Update a line item
$item = $nusii->lineItems()->update(50, [
    'name' => 'Updated Design Work',
    'quantity' => 20,
]);

// Delete a line item
$nusii->lineItems()->delete(50);
```

### Templates

[](#templates)

Templates are read-only.

```
// List templates
$templates = $nusii->templates()->list();

// Get a single template
$template = $nusii->templates()->get(5);

echo $template['name'];  // "Web Project Template"
```

### Proposal Activities

[](#proposal-activities)

Proposal activities are read-only and track events like views, accepts, and rejections.

```
// List all activities
$activities = $nusii->proposalActivities()->list();

// Filter by proposal
$activities = $nusii->proposalActivities()->list(proposalId: 456);

// Filter by client
$activities = $nusii->proposalActivities()->list(clientId: 123);

// Get a single activity
$activity = $nusii->proposalActivities()->get(1);

echo $activity['activity_type'];    // "viewed", "accepted", "rejected"
echo $activity['proposal_title'];   // "Website Redesign"
echo $activity['client_email'];     // "john@example.com"
```

### Users

[](#users)

Users are read-only.

```
// List users on the account
$users = $nusii->users()->list();

foreach ($users as $user) {
    echo $user['email'];
    echo $user['name'];
}
```

### Themes

[](#themes)

Themes are read-only. Note: this endpoint returns a plain array, not a paginated response.

```
// List available themes
$themes = $nusii->themes()->list();

foreach ($themes as $theme) {
    echo $theme['id'];
    echo $theme['name'];  // "Classic", "Modern", etc.
}
```

### Webhook Endpoints

[](#webhook-endpoints)

```
// List webhook endpoints
$webhooks = $nusii->webhookEndpoints()->list();

// Get a single webhook endpoint
$webhook = $nusii->webhookEndpoints()->get(1);

// Create a webhook endpoint
$webhook = $nusii->webhookEndpoints()->create([
    'target_url' => 'https://example.com/webhooks/nusii',
    'events' => [
        'proposal_created',
        'proposal_accepted',
        'proposal_rejected',
        'proposal_sent',
    ],
]);

// Delete a webhook endpoint
$nusii->webhookEndpoints()->delete(1);
```

**Available webhook events:**

EventDescription`proposal_created`A proposal was created`proposal_updated`A proposal was updated`proposal_destroyed`A proposal was deleted`proposal_accepted`A proposal was accepted by the client`proposal_rejected`A proposal was rejected by the client`proposal_sent`A proposal was sent to the client`client_created`A client was created`client_updated`A client was updated`client_destroyed`A client was deleted`proposal_activity_client_viewed`A client viewed something`proposal_activity_client_viewed_proposal`A client viewed a proposalPagination
----------

[](#pagination)

All list endpoints return a `PaginatedResponse` object that is both countable and iterable:

```
$response = $nusii->clients()->list(page: 1, perPage: 10);

// Pagination metadata
$response->currentPage;   // 1
$response->nextPage;      // 2 (or null)
$response->prevPage;      // null (or int)
$response->totalPages;    // 5
$response->totalCount;    // 42

// Navigation helpers
$response->hasNextPage(); // true
$response->hasPrevPage(); // false

// Iterate directly
foreach ($response as $item) {
    echo $item['name'];
}

// Count
echo count($response); // items on current page

// Access raw data array
$response->data; // array of items
```

### Paginating Through All Results

[](#paginating-through-all-results)

```
$page = 1;

do {
    $response = $nusii->clients()->list(page: $page, perPage: 50);

    foreach ($response as $client) {
        // Process each client
    }

    $page++;
} while ($response->hasNextPage());
```

Error Handling
--------------

[](#error-handling)

The library throws specific exceptions for different HTTP error codes:

```
use Nusii\Exceptions\AuthenticationException;
use Nusii\Exceptions\NotFoundException;
use Nusii\Exceptions\ValidationException;
use Nusii\Exceptions\RateLimitException;
use Nusii\Exceptions\ServerException;
use Nusii\Exceptions\NusiiException;

try {
    $client = $nusii->clients()->get(99999);
} catch (AuthenticationException $e) {
    // 401 - Invalid API key
    echo $e->getMessage();
} catch (NotFoundException $e) {
    // 404 - Resource not found
    echo $e->getMessage();
} catch (ValidationException $e) {
    // 400, 403, 422 - Validation or permission errors
    echo $e->getMessage();
    echo $e->getCode();          // HTTP status code
    print_r($e->responseBody);   // Raw response body
} catch (RateLimitException $e) {
    // 429 - Rate limit exceeded (100 requests per 30 seconds)
    echo $e->retryAfter;         // Seconds to wait before retrying
} catch (ServerException $e) {
    // 500, 503 - Server errors
    echo $e->getMessage();
} catch (NusiiException $e) {
    // Catch-all for any other API errors
    echo $e->getMessage();
}
```

All exceptions extend `NusiiException`, so you can catch that to handle any API error.

Rate Limiting
-------------

[](#rate-limiting)

The Nusii API allows 100 requests per 30 seconds. Rate limit information is tracked on the client instance:

```
$nusii->clients()->list();

echo $nusii->rateLimitRemaining;   // 99
echo $nusii->rateLimitRetryAfter;  // null (or seconds to wait)
```

Testing
-------

[](#testing)

Run the unit tests:

```
composer test
```

Or with Pest directly:

```
./vendor/bin/pest
```

### Integration Tests

[](#integration-tests)

Integration tests run against a live API server. Set the environment variables and run:

```
NUSII_API_KEY=your-key NUSII_API_URL=http://localhost:3000 ./vendor/bin/pest tests/IntegrationTest.php
```

Integration tests are automatically skipped when `NUSII_API_KEY` is not set.

Authentication
--------------

[](#authentication)

The library uses token authentication. Include your API key when creating the client:

```
$nusii = new Nusii('your-api-key');
```

All requests include the header:

```
Authorization: Token token=your-api-key

```

You can find your API key in your Nusii account settings under **Integrations**.

Requirements
------------

[](#requirements)

- PHP 8.3 or higher
- Guzzle 7.0 or higher

License
-------

[](#license)

MIT

###  Health Score

36

—

LowBetter than 79% of packages

Maintenance81

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

2

Last Release

103d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/18f80f613f67b5cc08690412697a55d5fa6b6287b60c74038afd0a75742b97ae?d=identicon)[michaelkoper](/maintainers/michaelkoper)

---

Top Contributors

[![michaelkoper](https://avatars.githubusercontent.com/u/85612?v=4)](https://github.com/michaelkoper "michaelkoper (3 commits)")

---

Tags

apiclientproposalsnusii

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/nusii-nusii-php/health.svg)

```
[![Health](https://phpackages.com/badges/nusii-nusii-php/health.svg)](https://phpackages.com/packages/nusii-nusii-php)
```

###  Alternatives

[openai-php/laravel

OpenAI PHP for Laravel is a supercharged PHP API client that allows you to interact with the Open AI API

3.7k8.8M83](/packages/openai-php-laravel)[tencentcloud/tencentcloud-sdk-php

TencentCloudApi php sdk

3661.2M46](/packages/tencentcloud-tencentcloud-sdk-php)[resend/resend-php

Resend PHP library.

596.2M35](/packages/resend-resend-php)[mozex/anthropic-laravel

Laravel integration for the Anthropic API: facade, config publishing, install command, testing fakes, messages, streaming, tool use, thinking, and batches.

72287.1k1](/packages/mozex-anthropic-laravel)[files.com/files-php-sdk

Files.com PHP SDK

2478.1k](/packages/filescom-files-php-sdk)[eslazarev/wildberries-sdk

Wildberries OpenAPI clients (generated).

252.5k](/packages/eslazarev-wildberries-sdk)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
