This is a PHP SDK (codebes/gripp-sdk) for the Gripp business management JSON-RPC API.
src/
├── GrippClient.php # Static facade - configure token/URL here first
├── Transport/
│ ├── JsonRpcClient.php # HTTP transport (batch, pagination, retries)
│ └── JsonRpcResponse.php # Response wrapper (rows, count, toCollection)
├── Query/
│ ├── QueryBuilder.php # Fluent filter builder (where/orderBy/limit/get)
│ └── Filter.php # Filter value object (field, operator, value)
├── Features/
│ └── Billability.php # Billability calculations (employee, team, project)
├── Resources/
│ ├── Resource.php # Abstract base class - all 54 resources extend this
│ ├── Concerns/
│ │ ├── CanRead.php # get(), find(), all(), where(), first()
│ │ ├── CanCreate.php # create()
│ │ ├── CanUpdate.php # update()
│ │ └── CanDelete.php # delete()
│ └── [54 resource classes] # Company, Contact, Project, Invoice, etc.
└── Exceptions/
├── GrippException.php # Base exception
├── AuthenticationException.php # 401/403
├── RateLimitException.php # 429
└── RequestException.php # Other API errors
- Always call
GrippClient::configure()before using any resource. It reads fromGRIPP_API_TOKENenv var if no arguments are given. Useshttps://api.gripp.comby default; override withGRIPP_API_URLenv var orbaseUrlparameter. - Resources are static classes. Usage:
Company::find(123),Company::create([...]),Project::where('name', 'contains', 'foo')->get(). - Traits compose CRUD capabilities. Check which traits a resource
uses to know what operations are available. Some resources are read-only (e.g.Cost,File,Memorial). - Each resource has schema constants:
FIELDS(field→type),READONLY,REQUIRED,RELATIONS(FK→class). - JSON-RPC methods follow the pattern:
{entity}.{action}(e.g.company.get,project.create). - The
Notificationresource is special - it usesemit()andemitall()instead of standard CRUD. - Features are computed logic, not API resources.
Billabilityaggregates Hour and OfferProjectLine data to calculate billable/non-billable time. Usage:Billability::forEmployee(42, '2026-01-01', '2026-01-31'). - QueryBuilder auto-paginates.
get()fetches all pages automatically. Uselimit()to restrict to a single page. - QueryBuilder auto-prefixes entity names.
Project::where('createdon', ...)becomesproject.createdonautomatically. Fully qualified fields (project.createdon) are left as-is. - Date helpers on QueryBuilder:
whereDateBetween($field, $start, $end),whereYear($field, $year),whereMonth($field, $year, $month),whereModifiedSince($date, $field = 'updatedon'). - Transport hooks:
beforeRequest(callback)fires before each HTTP call (throw to abort).onRateLimitExceeded(callback)fires on 429/503-1004 before the SDK throws. - Rate limit tracking:
getRateLimitRemaining()andgetRateLimitLimit()expose values fromX-RateLimit-*response headers. - 503 with error_code 1004 is treated as a rate limit (Gripp's short-burst throttle), not a server error.
When using where($field, $operator, $value):
equals, notequals, contains, notcontains, startswith, endswith, greaterthan, lessthan, greaterequals, lessequals, in, notin, isnull, isnotnull
Two-argument where($field, $value) defaults to equals.
Important: The Gripp API uses greaterequals / lessequals (NOT greaterthanorequal / lessthanorequal).
composer install
vendor/bin/phpunit # Run tests
vendor/bin/gripp-setup # Interactive credential setup- PSR-4 autoloading under
CodeBes\GrippSdk\ - Static methods on all resources (no instantiation needed)
- Returns
Illuminate\Support\Collectionfor multi-record queries,?arrayfor single records - Entity names are lowercase concatenation of class name:
ProjectPhase→'projectphase' - Fields use the Gripp API naming conventions (lowercase, no underscores between words in entity names)