Skip to main content

Your First Asset via API

A quickstart for creating your first asset programmatically using the Beacon Tower REST API. This guide covers the full workflow: authentication, model creation, asset creation, provider client provisioning, and binding.

Prerequisites

Before you begin, ensure you have:

  • A Beacon Tower account with appropriate privileges (at minimum: asset_management and model_management)
  • Access to the API base URL for your Beacon Tower instance (e.g., https://api.beacontower.ai)
  • An HTTP client such as curl, Postman, or similar
  • A configured provider (e.g., an IoT Hub provider) — providers are typically set up by your platform operations team

Step 1: Authenticate

Obtain a JWT access token using the Resource Owner Password Credentials (ROPC) flow:

curl -X POST https://api.beacontower.ai/auth/ropc \
-H "Content-Type: application/json" \
-d '{
"username": "user@example.com",
"password": "your-password"
}'

Response:

{
"accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Store the access token for convenience:

export TOKEN="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

Alternative: API Key Authentication

If you have an API key, use the X-API-Key header instead:

export API_KEY="your-api-key"

For detailed information about authentication methods, see the Authentication guide.

Step 2: Create a Model

Assets are instances of models defined using DTDL. Before creating an asset, you must create and publish a model.

Create a Model Draft

curl -X POST https://api.beacontower.ai/models/drafts \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"@id": "dtmi:mycompany:TemperatureSensor;1",
"@type": "Interface",
"@context": "dtmi:dtdl:context;3",
"displayName": "Temperature Sensor",
"contents": [
{
"@type": ["Telemetry", "Temperature"],
"name": "temperature",
"displayName": "Temperature",
"schema": "double",
"unit": "degreeCelsius"
}
]
}'

Save the draft ID from the response:

export MODEL_DRAFT_ID="<id-from-response>"

Promote the Model

Draft models are not usable until promoted:

curl -X POST https://api.beacontower.ai/models/drafts/$MODEL_DRAFT_ID/promote \
-H "Authorization: Bearer $TOKEN"

The model is now published and ready for use.

Step 3: Create the Asset

With the model published, create an asset instance:

curl -X POST https://api.beacontower.ai/assets \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"id": "temp-sensor-001",
"modelId": "dtmi:mycompany:TemperatureSensor;1",
"displayName": "Temperature Sensor 001",
"organizationId": "your-org-id"
}'

Note: organizationId is required. This determines which organization owns the asset and controls access permissions.

The asset exists but is not yet connected to any data source. To receive telemetry, you need to bind it — either to a provider client (for external devices) or to another asset (for asset-to-asset data routing).

Binding: Two Approaches

Beacon Tower supports two binding approaches depending on where the data comes from:

ApproachWhen to UseKey Concept
Provider Client + AutobindConnecting to an external device (IoT Hub, import provider, etc.)Create a provider client, provision it on the provider infrastructure, then autobind
Binding DescriptionRouting data from one asset to anotherUse a binding description to define how signals map between asset models

This quickstart covers the provider client approach since it's the most common for connecting physical devices. See Binding with Binding Descriptions at the end for the asset-to-asset flow.

Step 4: Create a Provider Client

A provider client represents your device's identity on the provider infrastructure. You need the provider ID for your target provider (ask your administrator).

export PROVIDER_ID="your-iot-hub-provider-id"

curl -X POST https://api.beacontower.ai/providers/$PROVIDER_ID/clients \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"id": "device1",
"displayName": "Temperature Device 1",
"organizationId": "your-org-id",
"enabled": true
}'

The id must be unique within the provider. This becomes the device identity used for authentication and message routing.

Step 5: Provision the Provider Client

Provisioning registers the provider client on the provider's infrastructure (e.g., creates the device on IoT Hub). The options object depends on your provider type.

IoT Hub Device (minimal)

curl -X POST https://api.beacontower.ai/providers/$PROVIDER_ID/clients/device1/provision \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"options": {
"hub": "your-iot-hub-name"
}
}'

IoT Hub Device (with authentication and desired properties)

curl -X POST https://api.beacontower.ai/providers/$PROVIDER_ID/clients/device1/provision \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"options": {
"hub": "your-iot-hub-name",
"isEdge": false,
"deviceEnabled": true,
"authenticationType": "sas",
"IoTDeviceProvisioningOptions": {
"DesiredProperties": {
"UpdateInterval": 10
}
}
}
}'

Import Provider (for file/API-based data)

curl -X POST https://api.beacontower.ai/providers/$PROVIDER_ID/clients/device1/provision \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"options": {
"Signals": [
{ "Id": "temperature" },
{ "Id": "humidity" }
]
}
}'

If your provider has templates configured, you can reference one with "templateId": "template-uuid" to apply default provisioning settings.

Step 6: Bind the Asset

Now bind the asset to the provisioned provider client using autobind. The autobind function automatically creates content bindings that map the provider client's signals to the asset's telemetry definitions.

curl -X POST https://api.beacontower.ai/assets/temp-sensor-001/bind \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"autobindRemoteInstanceIds": [
"'$PROVIDER_ID'::device1"
]
}'

The autobindRemoteInstanceIds format is {providerId}::{clientId}. Autobind generates a default binding description if one doesn't exist, mapping signals from the provider client to matching telemetry definitions in the asset's model.

The asset is now fully connected. When the device sends telemetry through the provider, the data flows into the asset.

Step 7: Query Telemetry

Once your device starts sending data, query it using the timeseries endpoints.

Get Latest Values

curl -X POST https://api.beacontower.ai/timeseries/get/last \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"items": [
{
"assetId": "temp-sensor-001",
"componentId": null,
"timeseries": null
}
]
}'

Get Historical Data

curl -X POST https://api.beacontower.ai/timeseries/get \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"assetId": "temp-sensor-001",
"timeseriesName": ["temperature"],
"searchSpanFrom": "2024-01-15T00:00:00Z",
"searchSpanTo": "2024-01-15T23:59:59Z",
"aggregationType": "avg",
"aggregationInterval": "PT5M"
}'

See Telemetry and Timeseries for details on aggregation types and intervals.

Summary: Provider Client Flow

The complete sequence for connecting an asset to an external device:

1. Create Model Draft    POST /models/drafts
2. Promote Model POST /models/drafts/{id}/promote
3. Create Asset POST /assets
4. Create Provider Client POST /providers/{providerId}/clients
5. Provision Client POST /providers/{providerId}/clients/{clientId}/provision
6. Bind Asset POST /assets/{assetId}/bind (autobindRemoteInstanceIds)

Binding with Binding Descriptions

When routing data from one asset to another (instead of from a provider client), you use binding descriptions. A binding description defines how signals from a source asset model map to a target asset model.

When to Use

  • Aggregating data from multiple assets into a summary asset
  • Routing processed data from one asset to another
  • Creating hierarchical data flows between asset models

Flow Overview

1. Create both assets (source and target)
2. Get or generate a binding description for the target model
3. Bind the target asset using the binding description + source asset ID

Step 1: Get Binding Descriptions for a Model

Check if a binding description already exists for your target model:

curl -X GET https://api.beacontower.ai/bindings/model/$TARGET_MODEL_ID \
-H "Authorization: Bearer $TOKEN"

This returns binding descriptions that define which source models are compatible (sources array) and how signals map between them.

Step 2: Generate a Binding Description (if needed)

If no existing binding description fits, generate one:

curl -X POST https://api.beacontower.ai/bindings/generate/$TARGET_MODEL_ID/$SOURCE_MODEL_ID \
-H "Authorization: Bearer $TOKEN"

Then save the generated binding description:

curl -X POST https://api.beacontower.ai/bindings \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '<generated-binding-description>'

Step 3: Bind Using the Binding Description

curl -X POST https://api.beacontower.ai/assets/$TARGET_ASSET_ID/bind \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"bindingDescriptions": [
{
"bindingDescriptionId": "btbi:dtmi:myModel;1:myBinding;1",
"instances": [
{
"instanceName": "Source Sensor",
"instanceId": "source-asset-id"
}
]
}
]
}'

The instances array maps source assets to the binding description's source slots. The system creates content bindings that route telemetry from the source asset into the target asset.


Next Steps

For step-by-step guidance using the web interface, see Your First Asset via Web UI.