PHPackages                             searsandrew/briar-rose - 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. searsandrew/briar-rose

ActiveLibrary[API Development](/categories/api)

searsandrew/briar-rose
======================

NetSuite RESTlet + SuiteTalk REST client for Laravel (OAuth 1.0a TBA, HMAC-SHA256).

v0.2.8(1mo ago)02↓50%MITPHPPHP ^8.2CI passing

Since Feb 5Pushed 2mo agoCompare

[ Source](https://github.com/searsandrew/briar-rose)[ Packagist](https://packagist.org/packages/searsandrew/briar-rose)[ RSS](/packages/searsandrew-briar-rose/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (10)Versions (13)Used By (0)

briar-rose
==========

[](#briar-rose)

**Briar Rose** is a Laravel-friendly NetSuite client that supports:

- **SuiteTalk REST Web Services (REST Record)** via OAuth 1.0a (HMAC-SHA256)
- **RESTlets** via OAuth 1.0a (HMAC-SHA256)
- Developer ergonomics: relative paths, pagination helpers, hydration helpers, retries/backoff.

---

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

[](#requirements)

- PHP ^8.2
- Laravel 10 / 11 / 12 (via illuminate components)
- NetSuite OAuth 1.0a integration (Consumer Key/Secret + Token ID/Secret)

---

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

[](#installation)

### Composer

[](#composer)

```
composer require searsandrew/briar-rose

```

---

Configuration
-------------

[](#configuration)

Briar Rose supports configuration via **environment variables** (no config publish required).

### Required

[](#required)

```
NETSUITE_ACCOUNT=0000000
NETSUITE_BASE_URL=https://0000000.suitetalk.api.netsuite.com

NETSUITE_CONSUMER_KEY=...
NETSUITE_CONSUMER_SECRET=...
NETSUITE_TOKEN_ID=...
NETSUITE_TOKEN_SECRET=...

```

### Optional REST defaults

[](#optional-rest-defaults)

```
NETSUITE_REST_DEFAULT_LIMIT=1000

NETSUITE_REST_RETRY=true
NETSUITE_REST_RETRY_MAX=5
NETSUITE_REST_RETRY_BASE_DELAY_MS=250
NETSUITE_REST_RETRY_MAX_DELAY_MS=5000

```

### Optional RESTlet connections

[](#optional-restlet-connections)

```
NETSUITE_RESTLET_BASE_URL=https://0000000.restlets.api.netsuite.com/app/site/hosting/restlet.nl?script=0000&deploy=1
NETSUITE_RESTLET_SCRIPT_ID=...
NETSUITE_RESTLET_DEPLOY_ID=1

```

> Sandbox note: NetSuite sandbox account ids often use underscores in the OAuth realm. Briar Rose will normalize realm formatting for you.

---

Usage
-----

[](#usage)

You can call Briar Rose via the facade:

```
use Searsandrew\BriarRose\Facades\BriarRose;

```

### SuiteTalk REST Record

[](#suitetalk-rest-record)

#### Get a record (by internal id)

[](#get-a-record-by-internal-id)

```
$response = BriarRose::rest()
    ->record('inventoryItem')
    ->get(0000);

$data = $response->json();

```

#### Get only certain fields

[](#get-only-certain-fields)

```
$response = BriarRose::rest()
    ->record('inventoryItem')
    ->getFields(0000, ['id', 'itemId', 'displayName']);

$data = $response->json();

```

#### List a record collection (one page)

[](#list-a-record-collection-one-page)

```
$response = BriarRose::rest()
    ->record('classification')
    ->list(['limit' => 1000, 'offset' => 0]);

$page = $response->json(); // items + links

```

#### List all pages (generator)

[](#list-all-pages-generator)

```
foreach (BriarRose::rest()->record('classification')->listAll(['limit' => 1000]) as $pageResponse) {
    $page = $pageResponse->json();
}

```

#### Iterate all collection items (generator)

[](#iterate-all-collection-items-generator)

```
foreach (BriarRose::rest()->record('classification')->listItemsAll(['limit' => 1000]) as $item) {
    // Usually contains id + links
    $id = $item['id'] ?? null;
}

```

#### Iterate all item IDs (generator)

[](#iterate-all-item-ids-generator)

```
foreach (BriarRose::rest()->record('classification')->listItemIdsAll(['limit' => 1000]) as $id) {
    // $id is the internal id
}

```

#### Filter a collection (q=…)

[](#filter-a-collection-q)

NetSuite supports a `q` query parameter for record collection filtering. Briar Rose exposes this directly:

```
$response = BriarRose::rest()
    ->record('inventoryItem')
    ->where('isinactive IS false', ['limit' => 1000]);

$page = $response->json();

```

> Note: NetSuite’s filtering syntax varies by record type. Refer to NetSuite docs for supported fields/operators.

---

Hydration helper (list → getFields)
-----------------------------------

[](#hydration-helper-list--getfields)

Collection endpoints typically return **id + links**, not full records. If you want to cache “id + name” locally, hydrate each record.

### Generator mode

[](#generator-mode)

```
$endpoint = BriarRose::rest()->record('classification');

foreach ($endpoint->hydrateAll(['limit' => 1000], ['id', 'name']) as $row) {
    // $row includes the requested fields
}

```

### Callback mode

[](#callback-mode)

```
$endpoint = BriarRose::rest()->record('classification');

$endpoint->hydrateAll(
    listQuery: ['limit' => 1000],
    fields: ['id', 'name'],
    onRow: function (array $row) {
        // Your app code: upsert locally, cache, etc.
    }
);

```

---

RESTlets
--------

[](#restlets)

### Requesting a RESTlet

[](#requesting-a-restlet)

You can call any RESTlet deployed to your account via the script method.

```
BriarRose::restlet()
    ->script(0000, 1)
    ->get(['listId' => 0000]);

```

### Requesting a RESTlet via the script ID + deploy ID

[](#requesting-a-restlet-via-the-script-id--deploy-id)

If you have a single RESTlet script deployed, you can set enviromental variables to call it directly:

> Note: This is the preferred method for production use if you have a single RESTlet script deployed.

Set the deploy ID in the environment:

```
NETSUITE_RESTLET_SCRIPT_ID=... // Script ID of the deployed RESTlet
NETSUITE_RESTLET_DEPLOY_ID=1   // Booleans are 1 or 0

```

```
$response = BriarRose::restlet('000')
    ->request('GET', ['listId' => 000]);

```

### Requesting a RESTlet via the base URL

[](#requesting-a-restlet-via-the-base-url)

If you have a RESTlet base URL set, you can call it like this:

Set the RESTlet base URL in the environment:

```
NETSUITE_RESTLET_BASE_URL=... // Be sure to set the Script ID of the RESTlet in the URL.

```

```
$response = BriarRose::restlet()
    ->request('GET', ['listId' => 000]);

$data = $response->json();

```

---

Error handling
--------------

[](#error-handling)

All requests return `Illuminate\Http\Client\Response`. Use standard helpers:

```
$response->successful();
$response->status();
$response->throw(); // throws RequestException

```

Retries/backoff are enabled by default for common transient failures (429 / 5xx) and honor `Retry-After` when present.

---

Roadmap
-------

[](#roadmap)

- SuiteQL endpoint helpers (paged queries, incremental sync patterns)
- Better query/filter helpers
- Additional first-class endpoints (as needed)

---

License
-------

[](#license)

MIT

###  Health Score

36

—

LowBetter than 82% of packages

Maintenance87

Actively maintained with recent releases

Popularity3

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity43

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 ~4 days

Recently: every ~10 days

Total

12

Last Release

54d ago

PHP version history (2 changes)v0.1.0PHP ^8.1

v0.2.4PHP ^8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/a5c84ad1a6d5d04e99f67803bcbb72987ede348a9153bb6b0daf3e3d0e12ed1f?d=identicon)[searsandrew](/maintainers/searsandrew)

---

Top Contributors

[![searsandrew](https://avatars.githubusercontent.com/u/1470088?v=4)](https://github.com/searsandrew "searsandrew (25 commits)")

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/searsandrew-briar-rose/health.svg)

```
[![Health](https://phpackages.com/badges/searsandrew-briar-rose/health.svg)](https://phpackages.com/packages/searsandrew-briar-rose)
```

###  Alternatives

[simplestats-io/laravel-client

Client for SimpleStats!

4515.5k](/packages/simplestats-io-laravel-client)[jasara/php-amzn-selling-partner-api

A fluent interface for Amazon's Selling Partner API in PHP

1344.8k1](/packages/jasara-php-amzn-selling-partner-api)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

255.2k](/packages/aedart-athenaeum)[surface/laravel-webfinger

A Laravel package to create an ActivityPub webfinger.

113.8k](/packages/surface-laravel-webfinger)

PHPackages © 2026

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