npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@boe-ventures/platform-schemas

v0.1.1

Published

TypeScript schemas for unofficial messaging platform APIs — endpoints, auth patterns, rate limits, and response types for Slack, LinkedIn, Instagram, Tinder, and iMessage.

Readme

@boe-ventures/platform-schemas

TypeScript types and endpoint documentation for unofficial messaging platform APIs.

What This Is

A community-maintainable reference for the internal APIs that messaging platforms use under the hood. Not an API client — a typed field manual and endpoint reference built from reverse-engineering browser sessions.

The primary audience is humans and AI agents trying to understand what Hydra knows: which endpoints exist, how auth is extracted, what is volatile, what is risky, and which claims are live-verified versus merely documented. Some normalized types are consumed directly by Hydra, but runtime SDK behavior is deliberately out of scope.

Each platform module documents:

  • API endpoints — URLs, methods, required headers
  • Authentication — how to extract tokens from a browser session (cookies, CSRF tokens, localStorage)
  • Raw response types — what the API actually returns, as TypeScript interfaces
  • Normalization — optional functions to convert raw responses into a common shape
  • Anti-detection — rate limits, delay recommendations, known risks per platform
  • Volatile IDs — GraphQL query IDs and doc_ids that change with deploys
  • Verification metadata — whether an endpoint is live-verified, experimental, stale, or reference-only
  • Changelog — observed API changes over time

Why

These platforms don't offer official messaging/DM APIs — or lock them behind enterprise tiers. The only way to build on them is to ride the browser session, making the same API calls the web app makes.

The problem: these APIs change without notice. LinkedIn rotates GraphQL query IDs. Instagram changes doc_ids on deploy. When they change, your integration breaks.

This package documents what we've learned, in one place, with types.

Platforms

| Platform | Auth Pattern | Read | Write | API Style | Stability | |----------|-------------|------|-------|-----------|-----------| | Slack | xoxc- token + d cookie | ✅ | ✅ | REST (internal) | Stable | | LinkedIn | CSRF from JSESSIONID cookie | ✅ | ⚠️ experimental | GraphQL (Voyager) | ⚠️ Volatile query IDs | | Instagram | CSRF cookie + x-ig-app-id | ✅ | — | REST + GraphQL | ⚠️ Volatile doc_ids, strictest detection | | Tinder | x-auth-token (bearer) | ✅ | ✅ | REST | Stable | | iMessage | Full Disk Access (macOS) | ✅ | ✅ | Local SQLite | Stable (schema changes across macOS versions) |

Install

npm install @boe-ventures/platform-schemas

Usage

Read confidence metadata

Every endpoint can carry verification metadata. Agents should inspect this before treating an endpoint as product-safe:

import { linkedinAdapter } from "@boe-ventures/platform-schemas";

console.log(linkedinAdapter.endpoints.sendMessage?.verification);
// {
//   status: "experimental",
//   lastChecked: "2026-06-25",
//   source: "external_reference",
//   notes: "Endpoint family cross-checked..."
// }

Status values:

| Status | Meaning | |--------|---------| | live_verified | Recently exercised by Hydra or a local platform path. | | documented | Known/documented from capture or prior work, but not necessarily product-runtime. | | experimental | Plausible and useful, but needs a controlled live test before broad use. | | reference_only | Included to orient agents; do not treat as implemented. | | stale | Known or suspected to be outdated. |

Browse endpoint documentation

import { linkedinAdapter, slackAdapter } from "@boe-ventures/platform-schemas";

// What endpoint does LinkedIn use for conversations?
console.log(linkedinAdapter.endpoints.listConversations.urlTemplate);
// → https://www.linkedin.com/voyager/api/voyagerMessagingGraphQL/graphql?queryId=...

// What headers does it need?
console.log(linkedinAdapter.endpoints.listConversations.headers);
// → { "csrf-token": "{csrfToken}", "x-restli-protocol-version": "2.0.0", ... }

// How do you extract auth tokens?
console.log(linkedinAdapter.auth.sources);
// → [{ type: "cookie", name: "csrfToken", selector: "JSESSIONID", ... }]

Check volatile IDs

When a platform integration breaks, check here first:

import { linkedinAdapter } from "@boe-ventures/platform-schemas";
import { DOC_IDS } from "@boe-ventures/platform-schemas/instagram";

// LinkedIn GraphQL query IDs (change periodically)
console.log(linkedinAdapter.volatileIds);
// → { conversations: "messengerConversations.0d5e6...", messages: "messengerMessages.5846e..." }

// Instagram doc_ids (change on deploy)
console.log(DOC_IDS);
// → { inboxQuery: "27228858046797698", threadDetail: "27530161873341603" }

Use raw response types

import type { SlackBootResponse, SlackRawChannel } from "@boe-ventures/platform-schemas/slack";
import type { LinkedInRawConversation } from "@boe-ventures/platform-schemas/linkedin";
import type { TinderRawMatch } from "@boe-ventures/platform-schemas/tinder";

// Type your own API responses
const response: SlackBootResponse = await fetchSlackBoot();
const channels: SlackRawChannel[] = response.channels;

Use built-in normalization (optional)

Each platform includes normalization functions that map raw responses to a common Conversation type. Use them or build your own:

import { normalizeConversation } from "@boe-ventures/platform-schemas/slack";
import type { Conversation } from "@boe-ventures/platform-schemas";

const conversation: Conversation = normalizeConversation(rawChannel, userMap, teamId, selfId);

Anti-detection reference

import { instagramAdapter } from "@boe-ventures/platform-schemas";

console.log(instagramAdapter.antiDetection);
// → { minDelayMs: 2000, maxDelayMs: 5000, maxMessageThreads: 5,
//     notes: "Instagram is the STRICTEST platform..." }

Fetching a single thread (targeted pull)

The inbox/list endpoints return a thread list with only each thread's last message — not full history. To pull one conversation's messages on demand (e.g. lazy-loading a person's thread), call the per-thread endpoint keyed by the thread's id:

| Platform | Endpoint | Thread key | Notes | |----------|----------|------------|-------| | Instagram | REST GET /api/v1/direct_v2/threads/{thread_id}/ (primary) — or GraphQL IGDSlideAsyncFetchAndInsertIGDViewerThreadQuery (doc_id 27110549851904846) | REST: long thread_id · GraphQL: short thread_fbid | ⚠️ Don't mix the two ids. The inbox's long thread_id (340282…) works with REST but NOT GraphQL, which wants the short thread_fbid (1360…). REST is reliable since we already hold the thread_id. Non-text items (story replies, reactions, shares) carry no text — label by item_type. | | LinkedIn | messengerMessages (Voyager GraphQL) | conversation URN urn:li:msg_conversation:… | URN is URL-encoded in the query variables | | Slack | POST /api/conversations.history | channel (C…/D…/G… id) | same call the inbox loop makes, for one channel | | Tinder | GET /v2/matches?message=1 | — | matches already include recent messages inline (message=0 returns none) | | iMessage | local chat.db | chat.ROWID / chat_identifier | join chat_message_joinmessage; text may live in attributedBody (streamtyped) |

⚠️ The single most common extraction bug: reading the inbox's last_message and assuming you have the conversation. You don't — most threads need this per-thread call to actually get their messages.

Sending messages (write)

Where supported, the web client sends via the same internal API. Writes execute in the browser's page context (same origin, same session) — indistinguishable from the user. Gate them behind explicit approval.

Write endpoints are documentation unless their verification.status says they are live-verified in the current Hydra runtime. Even then: no bulk sending, no unattended campaigns, and keep human cadence.

| Platform | Endpoint | Key payload | Auth | |----------|----------|-------------|------| | Slack | POST /api/chat.postMessage (multipart) | channel, blocks (rich_text) or text, client_msg_id, draft_id | xoxc- token + d cookie | | LinkedIn | POST /voyagerMessagingDashMessengerMessages?action=createMessage | conversationUrn, mailboxUrn, originToken, trackingId, attributed text body | CSRF from JSESSIONID; run same-origin in a LinkedIn tab | | Tinder | POST /user/matches/{matchId} | { message } | x-auth-token | | Instagram | GraphQL IGDirectTextSendMutation (doc_id 26911679871773184) | ig_thread_igid (the short thread_fbid), offline_threading_id, text.sensitive_string_value, send_attribution: "igd_web_chat_tab:in_thread" | x-csrftoken + fb_dtsg + x-fb-lsd (from page config) |

Current Coverage Notes

The normalized Platform union includes a few platforms that do not yet have full adapter docs in this package:

| Platform | Current package status | |----------|------------------------| | whatsapp | Normalized types are consumed by the local Baileys sidecar; adapter docs live elsewhere for now. | | x | Hydra extension has runtime work, but package docs are not promoted yet. | | homi | Hydra-specific source; not a general messaging API package entry yet. | | beeper | Intentionally adjacent, not a reverse-engineered platform API. Consider a future source-adapter note. |

Contributing

When an API breaks:

  1. Open the platform in your browser → Network tab
  2. Navigate to the messaging/DM section
  3. Find the new endpoint URL, query ID, or doc_id
  4. Update the relevant file in src/platforms/
  5. Update volatileIds and add a changelog entry
  6. Open a PR

What to capture

  • Endpoint URLs — filter Network tab by graphql, api, voyager
  • Headers — especially CSRF tokens, app IDs, protocol versions
  • Response shapes — copy a response and type it
  • Query IDs — for GraphQL platforms, the queryId or doc_id parameter

License

MIT


Originally extracted from Hydra, a multi-platform conversation aggregator.