SDK Workflows
This page shows practical workflows that are the same in both official SDKs. For endpoint-level request and response schemas, use the API Reference.
Create schema-free records
Section titled “Create schema-free records”Objects, rooms, locations, and persons use field keys configured in your seventhings instance. The SDKs therefore accept plain maps or arrays instead of fixed request models.
fields := map[string]any{ "inventory_name": "MacBook Pro 16", "serial": "SN-123",}
missing, err := c.MissingMandatoryFields(ctx, models.AssetTrackingTemplateAsset, fields)if err != nil { return err}if len(missing) > 0 { // collect the missing instance-specific field keys before creating}
uuid, err := c.ObjectCreate(ctx, fields)Use models.AssetTrackingTemplateAsset, models.AssetTrackingTemplateRoom, or
models.AssetTrackingTemplatePerson when reading field definitions.
use Seventhings\Models\Enums\AssetTrackingTemplate;
$fields = [ 'inventory_name' => 'MacBook Pro 16', 'serial' => 'SN-123',];
$definitions = $client->fieldDefinitions->list(AssetTrackingTemplate::Asset);$uuid = $client->objects->create($fields);In PHP, check the returned field definitions directly when you need to enforce mandatory instance-specific fields before creating a record.
List, filter, sort, and page records
Section titled “List, filter, sort, and page records”Objects, rooms, locations, rental cases, and CircularityHub list calls share
the same page, perPage, sort, and filters model.
opts := models.NewListOptions(). WithPage(1). WithPerPage(50). SortBy("updated_at", models.SortDESC). Where(models.Like("inventory_name", "Laptop"))
objects, err := c.ObjectsList(ctx, opts)To walk every page, use one of the Go iterator helpers:
for object, err := range c.ObjectsAll(ctx, models.NewListOptions().WithPerPage(100)) { if err != nil { return err } _ = object["inventory_name"]}use Seventhings\Models\FilterEntry;use Seventhings\Models\ListOptions;use Seventhings\Models\Enums\FilterOperator;use Seventhings\Models\Enums\SortDirection;
$page = 1;$perPage = 50;
do { $objects = $client->objects->list(new ListOptions( page: $page, perPage: $perPage, sort: ['updated_at' => SortDirection::Desc], filters: [ new FilterEntry('inventory_name', FilterOperator::Like, ['Laptop']), ], ));
foreach ($objects as $object) { // process each object }
$page++;} while (count($objects) === $perPage);Upload and attach files
Section titled “Upload and attach files”Upload a file first, then attach the returned file UUID to an attachment field on an object.
file, err := os.Open("manual.pdf")if err != nil { return err}defer file.Close()
fileUUID, err := c.FileUpload(ctx, "manual.pdf", file)if err != nil { return err}
_, err = c.ObjectAddFiles(ctx, objectUUID, []models.FileAttachment{ {FieldKey: "documents", FileUUID: fileUUID},})use Seventhings\Models\FileAttachment;
$stream = fopen('manual.pdf', 'rb');$fileUuid = $client->files->upload('manual.pdf', $stream);
$client->objects->addFiles($objectUuid, [ new FileAttachment('documents', $fileUuid),]);Use the field definitions endpoint to discover which object fields are attachment fields in your instance.
Manage a task lifecycle
Section titled “Manage a task lifecycle”Tasks use typed request models. A task must reference at least one asset and have at least one assignee.
deadline := "2026-12-31"
taskUUID, err := c.TaskCreate(ctx, models.CreateTask{ Title: "Review inventory", Deadline: &deadline, Assignees: []string{userUUID}, References: []models.TaskReferenceInput{ {Type: models.TaskReferenceTypeAsset, UUID: objectUUID}, }, Reminders: []models.TimeInterval{ {Unit: models.TimeIntervalDays, Value: 1}, },})if err != nil { return err}
err = c.TaskUpdateStatus(ctx, taskUUID, models.TaskStatusClosed)use Seventhings\Models\CreateTaskRequest;use Seventhings\Models\TaskReferenceInput;use Seventhings\Models\TimeInterval;use Seventhings\Models\Enums\TaskReferenceType;use Seventhings\Models\Enums\TaskStatus;use Seventhings\Models\Enums\TimeIntervalUnit;
$taskUuid = $client->tasks->create(new CreateTaskRequest( title: 'Review inventory', deadline: '2026-12-31', assignees: [$userUuid], references: [new TaskReferenceInput(TaskReferenceType::Asset, $objectUuid)], reminders: [new TimeInterval(TimeIntervalUnit::Days, 1)], recurringSchedule: null,));
$client->tasks->updateStatus($taskUuid, TaskStatus::Closed);Use TaskListOptions to list tasks by status, deadline range, assignee,
author, or reference type.
Persons vs users
Section titled “Persons vs users”Persons are asset-tracking records and can have instance-specific fields such as department, phone number, or custom fields. Users are login accounts.
- Use persons when you need people as assignable or searchable records.
- Use users when you need login-user metadata or task assignees.
- Persons can be fetched by UUID or numeric ID in both SDKs.
- Users can be listed, fetched by UUID, or fetched by numeric ID.
- The customer API does not expose a direct create-user endpoint, but it can create a user from a person through the persons resource.
personUUID, err := c.PersonCreate(ctx, map[string]any{ "email": "max@example.com", "first_name": "Max",})
user, err := c.UserGetByID(ctx, 42)$personUuid = $client->persons->create([ 'email' => 'max@example.com', 'first_name' => 'Max',]);
$user = $client->users->getById(42);CircularityHub IDs and orders
Section titled “CircularityHub IDs and orders”CircularityHub is the main exception to the SDKs’ UUID convention. Items and orders use integer IDs.
err := c.CircularityHubAddObjects(ctx, map[string]models.AddObjectEntry{ objectUUID: {Category: "Electronics", Price: "50.00"},})
orderID, err := c.CircularityHubOrderCreate(ctx, []int{itemID})order, err := c.CircularityHubOrderGet(ctx, orderID)use Seventhings\Models\AddObjectEntry;
$client->circularityHub->addObjects([ $objectUuid => new AddObjectEntry(category: 'Electronics', price: '50.00'),]);
$orderId = $client->circularityHub->createOrder([$itemId]);$order = $client->circularityHub->getOrder($orderId);Use the integer ID returned by createOrder() for later order reads or
updates.

