# GET /v1/projects/:projectId/users/:appUserId/signal (/docs/api/reference/telemetry/user-signal)



<Endpoint method="GET" path="/v1/projects/:projectId/users/:appUserId/signal" auth="Bearer" scope="events:read" phase="1" />

Returns a merged view of a single user: their latest property state, consent flags, assigned cohorts, and day-1 / 7 / 30 retention status. Use it to render a "user detail" screen inside your partner UI, or to decide whether a user is eligible for a campaign before you target them.

The view is computed from the raw event stream and refreshed hourly. `firstSeen` / `lastSeen` reflect live event timestamps; `retention` and `properties` lag by up to 60 minutes. PII fields follow the same redaction rules as [`GET /events`](/docs/api/reference/telemetry/events) — redacted unless the key carries `events:read+pii`.

<Callout type="info">
  `cohorts` is always returned as an empty array in Phase 1 — the cohort materializer hasn't shipped yet. The field is reserved so partners can begin reading it without a future schema bump.
</Callout>

<Parameters
  title="Path"
  rows="[
  { name: 'projectId', type: 'string', required: true, description: 'Project ID.' },
  { name: 'appUserId', type: 'string', required: true, description: 'The `app_user_id` the SDK emits with each event.' },
]"
/>

## Example request [#example-request]

<Tabs items="['curl', 'TypeScript', 'Python']">
  <Tab value="curl">
    ```bash
    curl "https://api.layers.com/v1/projects/prj_01HX9Y7K8M2P4RSTUV56789AB/users/user_a7f3c1d9/signal" \
      -H "Authorization: Bearer lp_live_01HX9Y6K7EJ4T2_4QZpN..."
    ```
  </Tab>

  <Tab value="TypeScript">
    ```ts
    const signal = await layers.users.signal(
      "prj_01HX9Y7K8M2P4RSTUV56789AB",
      "user_a7f3c1d9"
    );
    ```
  </Tab>

  <Tab value="Python">
    ```python
    signal = layers.users.signal(
        project_id="prj_01HX9Y7K8M2P4RSTUV56789AB",
        app_user_id="user_a7f3c1d9",
    )
    ```
  </Tab>
</Tabs>

## Response [#response]

<Response status="200" description="OK">
  ```json
  {
    "appUserId": "user_a7f3c1d9",
    "firstSeen": "2026-03-28T14:02:11Z",
    "lastSeen": "2026-04-18T19:41:57Z",
    "eventCount30d": 214,
    "properties": {
      "plan": "pro",
      "signup_source": "ios_appstore",
      "locale": "en-US",
      "email": "[redacted]"
    },
    "consent": {
      "analytics": true,
      "marketing": false,
      "personalization": true,
      "capturedAt": "2026-03-28T14:02:14Z"
    },
    "cohorts": [],
    "retention": {
      "day1": true,
      "day7": true,
      "day30": false
    },
    "refreshedAt": "2026-04-18T19:00:00Z"
  }
  ```
</Response>

## Errors [#errors]

| Status | Code              | When                                                                    |
| ------ | ----------------- | ----------------------------------------------------------------------- |
| 401    | `UNAUTHENTICATED` | Missing or invalid key.                                                 |
| 403    | `FORBIDDEN_SCOPE` | Key lacks `events:read`.                                                |
| 404    | `NOT_FOUND`       | Project does not exist, or no events received yet for this `appUserId`. |
| 429    | `RATE_LIMITED`    | Read budget exhausted.                                                  |

## See also [#see-also]

* [`GET /v1/projects/:projectId/events`](/docs/api/reference/telemetry/events) — raw events for this user (filter by `userId=`)
* [`GET /v1/projects/:projectId/conversions`](/docs/api/reference/telemetry/conversions) — aggregated conversions
