Skip to content

Resources

MOVED




Resources for Developers

Overview

Resources are files, plain text, or JSON stored alongside systems, devices, users, blueprints and other data objects in the Leverege IoT Stack. They can capture images, videos, and other binary data generated by or associated with devices over time, as well as textual information such as I18n files, json, cvs, and plain text. Resources enable applications to store visual records, support AI/ML inference workflows, and provide historical context for device activity.
Each resource belongs to a data object and has a unique path within that data object’s resource hierarchy. Resources are stored in Google Cloud Storage and tracked by the resource-server, which handles storage, retrieval, and lifecycle management.

When to Use Resources

Resource Use Cases
Use Case
Use Resources
Use Attributes
Camera captures, uploaded photos
Yes (Image)
No
Surveillance footage, recordings
Yes (Video)
No
Configuration exports, data attachments
Yes (File)
No
Inference snapshots
Yes (Image)
No
Temperature reading
No
Yes (number)
Device name
No
Yes (string)
Configuration settings
No
Yes (map)
There are no rows in this table
megaphone
Rule of thumb: If it’s a file that gets uploaded, captured, or downloaded, use a resource. If it’s structured data the system processes, use an attribute.
Resource Types
Type
Description
Common Use Cases
Images
JPEG, PNG, and other image formats
Camera captures, uploaded photos, inference snapshots
Videos
MP4 and other video formats
Surveillance footage, time-lapse recordings
Files
JSON, CSV, and other data files
Configuration exports, data attachments
I18N Translations
JSON
Configures Internationalization files.
There are no rows in this table
Resource Attributes
Field
Type
Description
id
string
Globally unique ID. Only relevant when querying with filters or through project-level “allOwners” endpoints—normally the unique key is the owner/coowner/path triplet
projectId
string
ID of the Imagine project the resource belongs to
path
string
Organizational descriptor, like a file location (e.g., inspections/2025-01-15/front)
type
string
MIME type (image/jpeg, video/mp4, application/json for non-file resources)
ownerId
string
Main owner ID—typically the device ID
coownerId
string
Secondary owner (less common, used for things like user system metadata)
data
object
The resource data. For JSON resources, this is the data itself. For files, this contains signed GCS URLs
details
object
File location details (null for JSON resources)
metadata
object
Custom metadata—useful for inference results, annotations, or other context
createdAt
timestamp
When the resource record was created in the system
dataCreatedAt
timestamp
When the underlying data was actually captured or generated
updatedAt
timestamp
When the resource was last updated
archiveAt
timestamp
Directive telling resource-server when to auto-archive
deleteAt
timestamp
Directive telling resource-server when to auto-delete
There are no rows in this table

Resource Timestamps: createdAt vs dataCreatedAt

Resources have two timestamp fields that serve different purposes:
createdAt: When the resource record was created in the system
dataCreatedAt: When the underlying data was actually captured or generated
Why this matters: A camera might capture an image at 10:00 AM but upload it at 10:15 AM due to network delays. The dataCreatedAt would be 10:00 AM (when the image was taken), while createdAt would be 10:15 AM (when the system received it).
By default, resources are sorted by dataCreatedAt in the UI, showing them in capture order rather than upload order.

Resources vs Resource Pointers

A resource stores an actual file in Google Cloud Storage.
A resource pointer references another resource’s file without duplicating it. Pointers have their own metadata independent of the original resource.
Use resource pointers when:
Multiple devices need to reference the same image
You want to annotate an image differently for different contexts
Creating a curated subset of resources from a larger collection
Important: If the original resource is deleted, the pointer will still exist but its file will be inaccessible.


Resource Query Parameters
Parameter
Type
Description
limit
number
Max resources to return
offset
number
Skip first N resources (avoid high values—see performance note)
order
Array[string]
Sort field
children
boolean
Include child paths in results
childrenOnly
boolean
Only return children, not the path itself
returnSignedUrl
boolean
Include GCS signed URL for direct file access
returnWriteableUrl
boolean
Include URL for direct upload to GCS
returnCount
boolean
Include total count in response
There are no rows in this table
megaphone
Performance tip: Avoid high offset values when paginating large result sets. Use time-based filtering on dataCreatedAt or cursor-based pagination when possible.

BigQuery Integration

Resource changes are appended to a BigQuery table for analytics and historical queries:
Table: resource_server.resource
BigQuery Resource Fields
Field
Type
Notes
id
string
Unique resource identifier
projectId
string
Project the resource belongs to
ownerId
string
Device ID that owns the resource
coownerId
string
Secondary owner (for shared resources)
path
string
Hierarchical path within the device
type
string
Content type (image, video, file)
details
object
File details (size, format, etc.)
data
object
Resource data
metadata
object
Custom metadata including inference results
createdAt
timestamp
When the record was created
dataCreatedAt
timestamp
When the data was captured
updatedAt
timestamp
Last modification time
deletedAt
timestamp
When deleted (if applicable)
archivedAt
timestamp
When archived (if applicable)
There are no rows in this table
Every resource create, update, delete, or archive appends a new row. Deduplicate using updatedAt for the latest state.
Cost optimization: This table is partitioned by createdAt. Always include a createdAt filter in queries for maximum efficiency.
-- Example: Get latest state of resources for a device
SELECT * FROM `project.resource_server.resource`
WHERE ownerId = 'device-id-here'
AND createdAt >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
QUALIFY ROW_NUMBER() OVER (PARTITION BY id ORDER BY updatedAt DESC) = 1

Permissions

Resource access has an independent permission set from the resource owner (device, system, etc):
By default, viewing blueprint resources (like translations) is restricted. To grant access to all users for ui purposes:
// Grant ResourceViewer to all users for a system's resources
await api.system(systemId)
.resource('i18n')
.user('any')
.addRole({ name: 'ResourceViewer', projectId: 'imagine' });

// Grant ResourceViewer for each blueprint
const blueprints = await api.project(projectId).blueprints().list();
for (const bp of blueprints.items) {
await api.blueprint(bp.id)
.resource('i18n')
.user('any')
.addRole({ name: 'ResourceViewer', projectId: 'imagine' });
}

Configuration

Resource Server File Limits
Service
Config Key
Default
Description
api-server
BODY_SIZE_LIMIT
5MB
Max request body size
resource-server
BODY_SIZE_LIMIT
1MB
Max file upload size
There are no rows in this table
Increase both values in service configmaps, or use writeable gcs url’s for larger uploads.

Deletion Behavior

When a device is deleted, its resources are archived by default rather than deleted. This:
Preserves files in Google Cloud Storage
Can be overridden via url params

Troubleshooting

“Request entity too large” Error

Cause: File exceeds BODY_SIZE_LIMITFix: Increase limits in api-server and resource-server configmaps, or use writeable gcs url’s (preferred)

Resources Upload but Don’t Display

Causes:
Missing permissions (most common)
Incorrect content type
File corruption
Debug steps:
Check resource-server logs for errors
Verify resource exists via API
Confirm user has ResourceViewer role for aforementioned resource
Access the signed URL directly to test file availability

Resource Pointer Shows No Image

Causes:
Source resource was deleted (pointer becomes orphaned)
Pointer path is incorrect
Debug: Query the pointer’s details to inspect its source reference fields

“ECONNREFUSED” to Resource Server

Cause: resource-server pod is down or restarting ​Fix: Check pod status in Kubernetes, review resource-server logs for crash reasons

Want to print your doc?
This is not the way.
Try clicking the ··· in the right corner or using a keyboard shortcut (
CtrlP
) instead.