---
title: "List the account's notifications"
method: GET
path: "/v1/{account_id}/notifications"
tags: ["Notifications"]
---

# List the account's notifications

`GET /v1/{account_id}/notifications`

## Request

- Base URL: `https://api.curviate.com`
- URL: `https://api.curviate.com/v1/{account_id}/notifications`
- Auth: HTTP bearer

Returns the account's notification cards, cursor-paginated, plus unread_count and a latest_published_at watermark for cheap polling. Each post-related card carries the activity id for the Posts group. Page until cursor is null.

## Path parameters

- `account_id` string, required

## Query parameters

- `filter` 'all' | 'jobs' | 'mentions' | 'my_posts' | 'my_posts_comments' | 'my_posts_reactions' | 'my_posts_reposts'
- `limit` integer
- `cursor` string

## Response `200`

A page of the account's notification cards, plus the account-level unread badge (unread_count) and newest-notification watermark (latest_published_at). Injected/promo cards are included and flagged (injected:true). Zero notifications is a valid 200 (items:[], cursor:null, unread_count:0). Page until cursor is null.

- object
  - `object` 'notification_list', required: Response type discriminator.
  - `items` object[], required: The notification cards for this page, newest first, injected/promo cards included and flagged. [] for a zero-notification account. A page may return slightly more than `limit` (whole pages up to the next boundary).
    - `object` 'notification', required: Item type discriminator.
    - `card_urn` string, nullable, required: The card entity urn, the item's primary identity AND the exact handle passed to DELETE .../{card_urn} and .../{card_urn}/show-less. null on injected cards (not deletable). This, not object_urn, is the write handle.
    - `object_urn` string, nullable, required: The notification's own object urn, a SECONDARY identifier, NOT the delete handle (feeding it to a write targets the wrong notification). null on injected cards.
    - `injected` boolean, required: true for an injected promo/suggestion card (card_urn/object_urn/type all null; not deletable). Injected cards are always included, flagged, never filtered.
    - `type` string, nullable, required: Notification kind (e.g. SHARED_BY_YOUR_NETWORK, COMMENTS_BY_YOUR_NETWORK, REACTIONS_BY_YOUR_NETWORK, PYMK, WVMP_V2, CAREER_INSIGHTS_FREEMIUM, SEARCH_APPEARANCE). Some kinds carry a trailing version digit (WVMP_V2). Open enum; treat unknown values as pass-through. null when the urn encodes no type.
    - `text` string, nullable, required: Full preview text of the notification. Pass-through, never stored. null on cards with no headline.
    - `actor_id` string, nullable, required: Primary actor, the profile id of who triggered the notification. null for system/algorithmic cards.
    - `actor_ids` string[], required: All distinct actor profile ids in the card ([] for system cards). Superset of actor_id.
    - `actor_profile_url` string, nullable, required: Deep-link to the primary actor's profile. null when actor_id is null.
    - `activity_urn_id` string, nullable, required: Numeric activity id of the post to act on (no urn prefix) for post-related cards, feeds a downstream react/comment. null for non-post cards (profile views, career insights).
    - `read` boolean, nullable, required: Whether the notification has been read/seen. false = unread. null when the substrate omits it.
    - `published_at` number, nullable, required: When the notification was published (epoch ms).
    - `target_url` string, nullable, required: Where the card links when tapped, a LinkedIn-relative path.
    - `can_show_less` boolean, required: Whether the card exposes a 'show less like this' affordance.
  - `cursor` string, nullable, required: Opaque cursor for the next page; null on the terminal page. Pass it back verbatim. There is no total (a shifting feed), page until cursor is null.
  - `unread_count` integer, required: The unseen-badge count for the account (0 when nothing is unread). Threaded from account metadata, NOT a count of items. Poll this cheaply rather than deep-paging.
  - `latest_published_at` number, nullable, required: Timestamp (epoch ms) of the newest notification, a poll watermark to detect 'anything new since last poll'. null if unavailable.
  - `safety_warning` SafetyWarning: Present on a successful response when this account crossed an account-safety ceiling while the affected budget row is on the default warn posture. The action still happened. Field-identical to the BUDGET_EXHAUSTED error body except that blocked is false and hint.message describes the outcome, so one branch handles both postures and switching the account to enforce is a configuration change rather than a client rewrite.
    - `row` string, nullable, required: The budget row that breached, for example profile_views or pending_invites. Null when the breach is not about a row: an activity_window warning on an action that spends no budget of its own (editing a message, dismissing a notification, a Recruiter or Sales Navigator admin action) is still governed by the hours the account works in. Read hint.parameter for what to change; whenever this is null it names posture, because the activity window edges are set per action type and this action has none, so the levers that reach it are the account timezone and posture.
    - `reset_at` string, nullable, required: The instant the refusal lifts: the window roll on a ceiling refusal, the next window open on an activity-window one. Null in the two cases no clock frees, the pending_invites gauge and InMail credits (row inmail).
    - `hint` object, required
      - `parameter` string, required: The settable parameter on PATCH /v1/{account_id}/safety-policy.
      - `message` string, required: What the condition is and what changing that parameter would do. This is the one field whose text differs from the BUDGET_EXHAUSTED refusal: here it says the action went through, and on a ceiling breach how far past the ceiling this row now stands, rather than telling you to set posture to warn when it already is. Branch on parameter, reason and blocked, never on this text.
    - `reason` 'ceiling' | 'activity_window', required: Which rule was crossed. ceiling means the row's configured limit is spent; activity_window means the account is outside the hours it works in, which is a different fact with a different remedy. hint.parameter names the right setting for each.
    - `blocked` boolean, required: Always false here. True on the BUDGET_EXHAUSTED refusal carrying the same payload.

## Other responses

- `400`: Invalid request, an unsupported `filter`, an out-of-range `limit`, or a corrupt `cursor`.
- `401`: The connected LinkedIn account's session is disconnected, reconnect the account.
- `403`: The LinkedIn account lacks a feature backing notifications. Not expected, free accounts read notifications; documented for completeness.
- `404`: The account_id does not belong to this tenant, or the account is unknown. An id whose connection was replaced or removed also stops resolving here, and it is already absent from the list, so re-read `GET /v1/accounts` for the current id.
- `429`: Rate limited. This feed throttles hard under fast polling, poll `unread_count` rather than deep-paging, and retry after the hinted delay.
- `500`: Internal error.
- `502`: A temporary upstream error occurred, or the upstream response could not be interpreted. Check `retry_likely_to_succeed`: a temporary error is worth retrying, a response that could not be interpreted is not, and carries `retry_hint: {"kind": "never"}`.
- `503`: Service unavailable.
- `504`: Gateway timeout.

---

[API](https://skmtc.dev/curviate/apis/curviate-api.md) · [All operations](https://skmtc.dev/curviate/apis/curviate-api/llms.txt) · [OpenAPI document](https://skmtc.dev/curviate/apis/curviate-api/revisions/eab848801d95?raw)
