Plugin data models
Entity catalogue and field reference for plugin data_access — accounts, rentals, invoices, catalogue_items from SchemaRegistry, custom_fields semantics, and how to read/write via the guarded facade.
Purpose
This is the canonical “what data can my plugin see and touch” page. Cross-links:
- Runtime facade: Plugin data access
- YAML declaration: Plugin manifest (
data_access)
Entity catalogue (PluginEntityMap)
| Entity key | Eloquent model | Domain meaning |
|---|---|---|
accounts |
App\Models\Account |
Universal CRM entity — contacts, organisations, venues, and users differentiated by account_type |
rentals |
App\Models\Rental |
Quotes and orders (rental job lifecycle) |
invoices |
App\Models\Invoice |
Invoices and related billing documents in the invoice model |
catalogue_items |
App\Models\CatalogueItem |
Catalogue items (rental, sale, service, etc.) |
No other entity keys are accepted by the data facade on this branch.
Accounts as the universal entity
In Signals, people, companies, venues, and login-capable users are all rows in accounts. Plugins that sync “contacts” or “customers” almost always target accounts (as Xero Sync does), not a separate contact table.
Field-name parity
| Surface | Naming |
|---|---|
| REST API resource attributes | RMS-compatible names |
| SchemaRegistry / import-export field names | Same core names |
Plugin data_access field lists |
Same core names |
Guaranteed for core schema fields: field names are the FieldDefinition::$name values from App\Services\SchemaRegistry::resolve($modelClass) (core + computed sources) — the same names the REST API uses. Use those strings in fields / read_fields / write_fields. This page deliberately does not repeat per-entity field lists; the API reference for each entity is the canonical source.
Custom fields differ: API and facade expose them as a nested flat map custom_fields: { name: value }. In the manifest, declare custom_fields (wholesale) or custom_fields.{name}. Custom field definitions live in the custom_fields table and appear in SchemaRegistry with source = custom — they are installation-specific, so consult your install rather than any static list.
Virtual facade field: accounts + email (primary email sync) is supported by PluginDataAccess but is not a SchemaRegistry core column — declare it explicitly when needed.
How to access
Signals::read($package, 'accounts', $id);
Signals::update($package, 'invoices', $id, [
'custom_fields' => ['xero_invoice_id' => $xeroId],
]);
Signals::operation($package, 'activities.complete', $dto);
In hooks, use PluginContext::read() / update() / setting().
Cannot: query builder, list/filter APIs, or direct Eloquent on core models — see Coming soon.
REST API links
OpenAPI UI: /docs/api. Markdown references:
| Entity | API docs |
|---|---|
| Accounts | Accounts API |
| Rentals | Rentals API |
| Invoices | Invoices API |
| Catalogue items | Catalogue items API |
Schema introspection: GET /api/v1/schemas/{accounts\|rentals\|invoices\|catalogue_items} (when enabled in your install).
Field reference
Field structure is documented once, in the API reference — this page does not duplicate it. For each entity above, the linked API docs list every attribute, type, and filterable name; those are exactly the names data_access accepts.
To introspect the live registry on your install (includes your custom fields):
$fields = app(\App\Services\SchemaRegistry::class)->resolve(\App\Models\Account::class);
foreach ($fields as $field) {
// $field->name, $field->type, $field->importable, $field->exportable, $field->source
}