# Official SDKs

Two zero-dependency SDKs wrap the Signal API — TypeScript (Node 18+) and Python 3. Same key, same four endpoints, same Display-mode sandbox. Install one and you are walking the cue loop in a few lines.

## Install

```javascript
npm install @uphealth/signal
```

```python
pip install uphealth-signal
```

Then set `UPHEALTH_API_KEY` in your environment. Get a free sandbox key at [uphealth.us/signup](https://uphealth.us/signup) to begin.

## Create and cue

Construct the client once, create a stream — the opening cue returns synchronously — then walk it: feedback in, the next cue out. The `idempotency_key` is generated for you when you do not pass one, so a retried cue is safe by default.

```javascript
import { Signal } from "@uphealth/signal";
const signal = new Signal({ apiKey: process.env.UPHEALTH_API_KEY });

// create — the opening cue comes back synchronously
const { streamId, firstCue } = await signal.streams.create({
  templateId: "general_wellness_daily",
});

// feedback in, next cue out (idempotencyKey auto-generated if omitted)
const out = await signal.streams.cue(streamId, { responseAction: "did_it" });
// out.nextCue.body, out.nextCue.receptivity, out.nextCue.safety
```

```python
import os
from uphealth_signal import Signal
signal = Signal(api_key=os.environ["UPHEALTH_API_KEY"])

# create — the opening cue comes back synchronously
stream = signal.streams.create(template_id="general_wellness_daily")

# feedback in, next cue out (idempotency_key auto-generated if omitted)
out = signal.streams.cue(stream.stream_id, response_action="did_it")
# out.next_cue.body, out.next_cue.receptivity, out.next_cue.safety
```

## Let the SDK drive the loop

Prefer not to hand-roll the loop? Both SDKs ship a `runStream` helper (Python: `run_stream` ) that creates a stream and advances it to the ended state, calling your decider for each cue. It encodes the feedback-per-cue rule, so you can never accidentally hit a `409 feedback_required` error.

> The SDKs are thin and faithful — every field name and error maps one to one to the API, so the [reference](https://uphealth.us/docs/ref-cue) and the [error index](https://uphealth.us/docs/err-index) apply unchanged.

## What you get back

Every cue carries the message plus its advisory `receptivity` float and audience-safety `safety` verdict (see [The cue response](https://uphealth.us/docs/concepts-response)).

Errors raise typed exceptions — a rate-limit error on the Discovery cap, auth and validation errors otherwise — so you branch on the exception type, not the raw status code.

## Next

- [Your first cue](https://uphealth.us/docs/quickstart) — The same flow in raw curl, JavaScript, Python, and Ruby.
- [Use Signal from OpenAI & Claude](https://uphealth.us/docs/guide-agent-platforms) — Wire Signal into an agent on either platform — today, no listing.

---

_Uphealth Signal developer docs · [View on uphealth.us](https://uphealth.us/docs/sdks) · OpenAPI spec: https://uphealth.us/openapi/signal-v1.yaml · Verified against API v1 on 2026-07-22._
