Back to catalog
LabfreeHands-On Labs

Lab: Your First DOSFI SDK Call — Send and Receive Mesh Data

Install the DOSFI SDK, authenticate, and make your first API call to send and receive data across the mesh — a practical, end-to-end beginner lab.

beginner 45 minutesFree

What you'll build

Vertical stack context: DOSFIUniversity (research) → DOSFI Academy (this course) → MeshNativeExchange (publishing & monetizing). Students progress from Learning → Building → Publishing → Monetizing. In this beginner-friendly lab, you will go from zero to a working DOSFI SDK integration. You will install the SDK, configure authentication using your @dosfi.ai identity, and make your first API call to send a telemetry event into the mesh and receive a confirmation back. This lab is purely practical: every step is hands-on, every command is runnable, and every output is deterministic.

Skills you'll practice

  • Install and configure the DOSFI SDK in a local project
  • Authenticate using your @dosfi.ai identity credentials
  • Send a structured telemetry event into the mesh via the SDK
  • Receive and parse a confirmation response from the mesh
  • Handle common SDK errors using public error codes

Before you start

  • A DOSFI Academy account with an @dosfi.ai identity
  • Node.js 18+ or Python 3.10+ installed locally
  • Basic familiarity with the command line

Lab steps4 steps

  1. 1
    Installing and Configuring the DOSFI SDK

    ## Module Overview This lesson covers the first step every developer takes: installing the DOSFI SDK and configuring it with your identity credentials. You will set up a local project, install the SDK package, and verify the installation with a simple health check. ## Learning Objectives - Create a new project directory and initialize it - Install the DOSFI SDK from the public package registry - Configure SDK authentication using your @dosfi.ai identity - Run a health-check call to verify connectivity ## Lesson The DOSFI SDK is the public developer interface to the mesh. It exposes typed methods for sending data, receiving responses, and managing application state — all without requiring knowledge of any internal system behavior. ### Step 1: Create Your Project ```bash mkdir my-first-dosfi-app cd my-first-dosfi-app npm init -y ``` ### Step 2: Install the SDK ```bash npm install @dosfi/sdk ``` The SDK is a single package with no native dependencies. It works in Node.js and browser environments. ### Step 3: Configure Authentication Create a file named `dosfi.config.js` in your project root: ```javascript import { DOSFIClient } from '@dosfi/sdk'; export const client = new DOSFIClient({ identity: process.env.DOSFI_IDENTITY, region: 'us-east-mesh', }); ``` Your `DOSFI_IDENTITY` is your @dosfi.ai credential string. You can find it in the Identity tab of your DOSFI Academy dashboard. Never hardcode it — always load it from an environment variable. ### Step 4: Verify with a Health Check ```javascript import { client } from './dosfi.config.js'; const health = await client.health(); console.log('Mesh status:', health.status); // Expected: Mesh status: ok ``` If you see `ok`, your SDK is installed and authenticated correctly. ## Text-Based Diagram ``` [Your Project] | +-- dosfi.config.js (DOSFIClient init) | v [DOSFI SDK] -- public API surface --> | v [Mesh Endpoint (us-east-mesh)] | v [Health Response: { status: "ok" }] ``` ## Example A minimal `index.js` that runs the health check: ```javascript import { client } from './dosfi.config.js'; async function main() { const health = await client.health(); if (health.status === 'ok') { console.log('Connected to the mesh successfully.'); } else { console.error('Connection failed:', health.status); } } main(); ``` Run it with `node index.js`. ## Exercises 1. Create the project directory, install the SDK, and run the health check. Capture the output. 2. Change the `region` to `eu-west-mesh` and re-run. Observe how the response changes. 3. Temporarily set `DOSFI_IDENTITY` to an empty string and run again. Observe the error. ## Expected Output ``` Mesh status: ok Connected to the mesh successfully. ``` ## Troubleshooting Notes 1. **Error: `DOSFI_IDENTITY is not set`** — You forgot to export the environment variable. Run `export DOSFI_IDENTITY=your-credential-here` before running the script. 2. **Error: `SDK package not found`** — Run `npm install` again. Ensure you are in the correct project directory. 3. **Error: `Mesh status: unavailable`** — The region you specified may be under maintenance. Switch to another region and retry. ## Validation Steps 1. Confirm `@dosfi/sdk` appears in your `package.json` dependencies. 2. Confirm `node index.js` prints `Mesh status: ok`. 3. Confirm that removing the identity credential produces an authentication error (not a crash).

  2. 2
    Sending Your First Telemetry Event

    ## Module Overview Now that the SDK is installed and authenticated, you will send your first structured data payload into the mesh. You will construct a telemetry event, send it via the SDK, and receive a confirmation response with a tracking ID. ## Learning Objectives - Construct a valid telemetry event payload - Send the event using `client.send()` - Parse the confirmation response and extract the tracking ID - Understand the event schema requirements ## Lesson A telemetry event is a structured JSON object that the mesh accepts, processes, and acknowledges. The SDK provides a typed `send()` method that handles serialization, transport, and response parsing for you. ### The Telemetry Event Schema Every event must conform to this public schema: ```json { "event_type": "string", "source": "string", "payload": { "temperature_c": 22.5, "sensor_id": "sensor-001" }, "timestamp": "2026-07-15T10:00:00Z" } ``` The `event_type` field is a string that categorizes your event. The `source` field identifies your application. The `payload` is an arbitrary JSON object with your data. The `timestamp` is an ISO 8601 string. ### Sending the Event ```javascript const event = { event_type: 'sensor.reading', source: 'my-first-dosfi-app', payload: { temperature_c: 22.5, sensor_id: 'sensor-001' }, timestamp: new Date().toISOString() }; const response = await client.send(event); console.log('Tracking ID:', response.tracking_id); console.log('Status:', response.status); ``` ### The Response The SDK returns a confirmation object: ```json { "tracking_id": "evt_abc123def456", "status": "accepted", "accepted_at": "2026-07-15T10:00:01Z" } ``` The `tracking_id` is your receipt. You can use it later to query the status of your event. ## Text-Based Diagram ``` [Your App] | | event = { event_type, source, payload, timestamp } v [client.send(event)] | v [Mesh Ingestion] | v [Confirmation: { tracking_id, status, accepted_at }] | v [Your App logs tracking_id] ``` ## Example A complete script that sends a telemetry event and logs the confirmation: ```javascript import { client } from './dosfi.config.js'; async function sendTelemetry() { const event = { event_type: 'sensor.reading', source: 'my-first-dosfi-app', payload: { temperature_c: 22.5, sensor_id: 'sensor-001' }, timestamp: new Date().toISOString() }; const response = await client.send(event); console.log('Event accepted:', response.tracking_id); console.log('Status:', response.status); } sendTelemetry(); ``` ## Exercises 1. Send a telemetry event with `event_type: 'sensor.reading'` and a temperature payload. Record the tracking ID. 2. Send a second event with a different `sensor_id`. Compare the tracking IDs. 3. Send an event with a missing `timestamp` field. Observe what happens. ## Expected Output ``` Event accepted: evt_abc123def456 Status: accepted ``` ## Troubleshooting Notes 1. **Error: `event_type is required`** — The `event_type` field is mandatory. Ensure your event object includes it. 2. **Error: `payload exceeds size limit`** — The payload must be under 256 KB. If your payload is larger, split it into multiple events. 3. **Error: `status: rejected`** — The event did not conform to the schema. Check that all required fields are present and correctly typed. ## Validation Steps 1. Confirm the response contains a `tracking_id` starting with `evt_`. 2. Confirm the `status` field is `accepted`. 3. Confirm that sending a second event produces a different tracking ID.

  3. 3
    Receiving Data Back from the Mesh

    ## Module Overview In this lesson, you will query the mesh for data you previously sent. You will use the `client.query()` method with a tracking ID to retrieve the status of a sent event, and you will use `client.subscribe()` to receive events from the mesh in real time. ## Learning Objectives - Query a previously sent event by its tracking ID - Subscribe to a stream of events from the mesh - Filter incoming events by event type - Gracefully unsubscribe from a stream ## Lesson The SDK provides two methods for receiving data: `query()` for one-time lookups and `subscribe()` for continuous streams. ### Querying by Tracking ID ```javascript const status = await client.query('evt_abc123def456'); console.log('Event status:', status.state); console.log('Processed at:', status.processed_at); ``` The response includes the current state of your event: ```json { "tracking_id": "evt_abc123def456", "state": "processed", "processed_at": "2026-07-15T10:00:02Z", "result": { "validated": true } } ``` ### Subscribing to an Event Stream ```javascript const subscription = client.subscribe({ event_type: 'sensor.reading', source: 'my-first-dosfi-app' }, (event) => { console.log('Received event:', event.tracking_id); console.log('Payload:', event.payload); }); // Later, to stop receiving: subscription.unsubscribe(); ``` The `subscribe()` method takes a filter object and a callback. The filter narrows which events you receive. The callback is invoked for each matching event. ### Filtering You can filter by any combination of fields: ```javascript // Only events from a specific source client.subscribe({ source: 'my-first-dosfi-app' }, callback); // Only events of a specific type client.subscribe({ event_type: 'sensor.reading' }, callback); // All events (no filter) client.subscribe({}, callback); ``` ## Text-Based Diagram ``` [client.query(tracking_id)] | v [Mesh Lookup] | v [Response: { state, processed_at, result }] --- or --- [client.subscribe(filter, callback)] | v [Mesh Stream] | +-- event 1 --> callback(event1) +-- event 2 --> callback(event2) +-- event 3 --> callback(event3) | v [subscription.unsubscribe()] ``` ## Example A script that queries a previously sent event and then subscribes to new events: ```javascript import { client } from './dosfi.config.js'; async function main() { const status = await client.query('evt_abc123def456'); console.log('Past event state:', status.state); const sub = client.subscribe({ event_type: 'sensor.reading' }, (event) => { console.log('New event:', event.tracking_id, event.payload); }); setTimeout(() => { sub.unsubscribe(); console.log('Unsubscribed.'); }, 30000); } main(); ``` ## Exercises 1. Query the tracking ID from Lesson 2. Confirm the state is `processed`. 2. Subscribe to `sensor.reading` events and send a new event from a second terminal. Observe the callback firing. 3. Unsubscribe after receiving 3 events. Confirm no more callbacks fire. ## Expected Output ``` Past event state: processed New event: evt_xyz789 payload: { temperature_c: 23.1, sensor_id: 'sensor-001' } Unsubscribed. ``` ## Troubleshooting Notes 1. **Error: `tracking_id not found`** — The event may not have been fully processed yet. Wait a few seconds and retry. 2. **No events received in subscription** — Ensure your filter matches the events being sent. Try subscribing with an empty filter `{}` to verify. 3. **Callback fires after unsubscribe** — This is a race condition. Wrap your callback logic in a guard flag. ## Validation Steps 1. Confirm `client.query()` returns a `state` field. 2. Confirm `client.subscribe()` invokes the callback when a matching event is sent. 3. Confirm `subscription.unsubscribe()` stops the callback from firing.

  4. 4
    Handling SDK Errors Gracefully

    ## Module Overview Every production application must handle errors. In this final lesson, you will learn the public error model of the DOSFI SDK, implement retry logic for transient failures, and build a robust send-and-receive loop that degrades gracefully. ## Learning Objectives - Identify and handle the three categories of SDK errors - Implement exponential backoff for transient errors - Distinguish between retryable and non-retryable failures - Build a resilient send loop with error handling ## Lesson The DOSFI SDK exposes a public error model with three categories: ### Error Categories 1. **Authentication errors** — Invalid or expired identity credentials. These are not retryable; the developer must refresh credentials. 2. **Validation errors** — The event payload does not conform to the schema. These are not retryable; the developer must fix the payload. 3. **Transient errors** — Network timeouts, rate limits, or temporary mesh unavailability. These are retryable with backoff. ### Error Structure ```javascript try { const response = await client.send(event); } catch (error) { console.error('Error code:', error.code); console.error('Error message:', error.message); console.error('Retryable:', error.retryable); } ``` Each error has a `code` (a stable string identifier), a `message` (human-readable), and a `retryable` boolean. ### Common Error Codes | Code | Category | Retryable | |------|----------|-----------| | `AUTH_INVALID` | Authentication | No | | `AUTH_EXPIRED` | Authentication | No | | `VALIDATION_FAILED` | Validation | No | | `RATE_LIMITED` | Transient | Yes | | `TIMEOUT` | Transient | Yes | | `MESH_UNAVAILABLE` | Transient | Yes | ### Implementing Retry with Backoff ```javascript async function sendWithRetry(event, maxRetries = 3) { let attempt = 0; while (attempt < maxRetries) { try { const response = await client.send(event); return response; } catch (error) { if (!error.retryable) throw error; attempt++; const delay = Math.pow(2, attempt) * 1000; console.log(`Retry ${attempt}/${maxRetries} after ${delay}ms`); await new Promise(resolve => setTimeout(resolve, delay)); } } throw new Error('Max retries exceeded'); } ``` ### A Resilient Send Loop ```javascript async function resilientSendLoop(events) { const results = []; for (const event of events) { try { const response = await sendWithRetry(event); results.push({ success: true, tracking_id: response.tracking_id }); } catch (error) { results.push({ success: false, error: error.code, event_type: event.event_type }); console.error(`Failed to send ${event.event_type}:`, error.message); } } return results; } ``` ## Text-Based Diagram ``` [send(event)] | +-- success --> return response | +-- error.retryable == false --> throw (auth/validation) | +-- error.retryable == true | +-- attempt < maxRetries --> wait(backoff) --> retry | +-- attempt >= maxRetries --> throw('Max retries exceeded') ``` ## Example A complete error-handling script: ```javascript import { client } from './dosfi.config.js'; async function sendWithRetry(event, maxRetries = 3) { let attempt = 0; while (attempt < maxRetries) { try { return await client.send(event); } catch (error) { if (!error.retryable) throw error; attempt++; await new Promise(r => setTimeout(r, Math.pow(2, attempt) * 1000)); } } throw new Error('Max retries exceeded'); } const event = { event_type: 'sensor.reading', source: 'my-first-dosfi-app', payload: { temperature_c: 22.5, sensor_id: 'sensor-001' }, timestamp: new Date().toISOString() }; sendWithRetry(event) .then(r => console.log('Sent:', r.tracking_id)) .catch(e => console.error('Failed:', e.code || e.message)); ``` ## Exercises 1. Send an event with an invalid payload (missing `event_type`). Catch the `VALIDATION_FAILED` error and confirm `retryable` is `false`. 2. Temporarily set an invalid identity credential. Send an event and catch the `AUTH_INVALID` error. 3. Implement the `sendWithRetry` function and test it by sending 5 events in a loop. ## Expected Output ``` Failed: VALIDATION_FAILED Error code: AUTH_INVALID Retryable: false Sent: evt_abc123def456 ``` ## Troubleshooting Notes 1. **Retries loop forever** — Ensure your `while` condition checks `attempt < maxRetries` and increments `attempt` on each iteration. 2. **Non-retryable errors are retried** — Check that you are testing `error.retryable` before retrying. Authentication and validation errors should be thrown immediately. 3. **Backoff is too aggressive** — Start with 2 seconds and double each time. Cap the maximum delay at 30 seconds. ## Validation Steps 1. Confirm that a `VALIDATION_FAILED` error has `retryable: false`. 2. Confirm that `sendWithRetry` retries transient errors up to `maxRetries` times. 3. Confirm that non-retryable errors are thrown immediately without retrying.