186 lines
4.9 KiB
Markdown
186 lines
4.9 KiB
Markdown
# Usage Guide
|
|
|
|
## What this SDK is
|
|
|
|
`@socialhose/api` is a TypeScript client for the Socialhose Public API. It is built for backend services, scripts, serverless functions, and dashboards that need campaign analytics, mention search, mailing-list management, and term-level entity analytics.
|
|
|
|
The SDK handles:
|
|
|
|
1. API-key authentication.
|
|
2. Typed endpoint helpers.
|
|
3. Timeouts, retries, and request cancellation.
|
|
4. GET caching with an injectable cache interface.
|
|
5. Entity analytics assembled from `/mentions/` when native analytics endpoints are campaign-scoped.
|
|
|
|
## Install
|
|
|
|
```bash
|
|
npm install @socialhose/api
|
|
```
|
|
|
|
Requires Node 18+ or a custom `fetch` implementation.
|
|
|
|
## Getting API access
|
|
|
|
Socialhose API keys are provisioned by Socialhose. This SDK only consumes an existing key; it cannot create, rotate, or discover keys for you.
|
|
|
|
Ask the Socialhose team or your account administrator for a Public API key and confirm which campaigns it can access. Then set it in your server environment:
|
|
|
|
```bash
|
|
export SOCIALHOSE_API_KEY="sh_your_key_here"
|
|
```
|
|
|
|
Keep this value server-side. For browser applications, create your own backend endpoint that uses this SDK and returns sanitized data to the frontend.
|
|
|
|
## Basic setup
|
|
|
|
```ts
|
|
import { SocialhoseClient } from '@socialhose/api';
|
|
|
|
const socialhose = new SocialhoseClient({
|
|
apiKey: process.env.SOCIALHOSE_API_KEY!,
|
|
});
|
|
```
|
|
|
|
Keep the API key server-side. Do not instantiate this client in browser code.
|
|
|
|
## Production setup
|
|
|
|
```ts
|
|
const socialhose = new SocialhoseClient({
|
|
apiKey: process.env.SOCIALHOSE_API_KEY!,
|
|
timeoutMs: 10_000,
|
|
retries: 3,
|
|
cacheTtlMs: 60_000,
|
|
});
|
|
```
|
|
|
|
Recommendations:
|
|
|
|
- Keep the default browser-like user-agent unless you have verified an alternative works.
|
|
- Use a shared cache such as Redis for multi-process or serverless deployments.
|
|
- Reduce entity batch concurrency if you see `429` responses.
|
|
- Use `revalidateSeconds` for dashboards so repeated views do not fan out fresh requests.
|
|
|
|
## List campaigns
|
|
|
|
```ts
|
|
const campaigns = await socialhose.getCampaigns();
|
|
for (const campaign of campaigns) {
|
|
console.log(campaign.id, campaign.name, campaign.status);
|
|
}
|
|
```
|
|
|
|
## Search mentions
|
|
|
|
```ts
|
|
const page = await socialhose.getMentions({
|
|
campaign_ids: 'campaign-id',
|
|
content_search: 'hospital',
|
|
platforms: 'twitter,reddit',
|
|
sentiments: 'negative',
|
|
ordering: '-published_at',
|
|
});
|
|
|
|
console.log(page.count);
|
|
console.log(page.results[0]?.content);
|
|
```
|
|
|
|
## Fetch campaign dashboard analytics
|
|
|
|
```ts
|
|
const filters = { campaign_ids: 'campaign-id', date_from: '2026-05-01' };
|
|
|
|
const [overview, timeline, sentiment, platforms, topMentions] = await Promise.all([
|
|
socialhose.getOverview(filters),
|
|
socialhose.getTimeline({ ...filters, interval: 'day' }),
|
|
socialhose.getSentiment(filters),
|
|
socialhose.getPlatforms(filters),
|
|
socialhose.getTopMentions({ ...filters, limit: 10 }),
|
|
]);
|
|
```
|
|
|
|
## Analyze a term or entity
|
|
|
|
```ts
|
|
const stats = await socialhose.getEntityStats('RSF', 'campaign-id', {
|
|
revalidateSeconds: 900,
|
|
});
|
|
|
|
console.log({
|
|
total: stats.total,
|
|
sentiment: stats.sentiment,
|
|
platformMix: stats.platformMix,
|
|
momentumPct: stats.momentumPct,
|
|
topUrls: stats.sample.slice(0, 3).map((m) => m.url),
|
|
});
|
|
```
|
|
|
|
Use `getEntityBrief()` for cheap cards/lists and `getEntityStats()` for detail pages.
|
|
|
|
## Batch entity briefs
|
|
|
|
```ts
|
|
const briefs = await socialhose.getEntityBriefs(
|
|
['Burhan', 'Hemedti', 'SAF', 'RSF'],
|
|
'campaign-id',
|
|
5,
|
|
{ revalidateSeconds: 3600 },
|
|
);
|
|
```
|
|
|
|
Failed terms are skipped. Lower concurrency if rate limits are visible.
|
|
|
|
## Pagination
|
|
|
|
`getCampaigns()` and `getMailingLists()` return first-page arrays. `getMentions()` exposes a `page` filter.
|
|
|
|
For manual pagination, use `get()`:
|
|
|
|
```ts
|
|
let page = 1;
|
|
while (true) {
|
|
const response = await socialhose.get('/mentions/', { page, content_search: 'cholera' });
|
|
// process response.results
|
|
if (!response.next) break;
|
|
page += 1;
|
|
}
|
|
```
|
|
|
|
## Error handling
|
|
|
|
```ts
|
|
import { SocialhoseError } from '@socialhose/api';
|
|
|
|
try {
|
|
await socialhose.getOverview({ campaign_ids: 'bad-id' });
|
|
} catch (error) {
|
|
if (error instanceof SocialhoseError) {
|
|
console.error({ status: error.status, path: error.path, body: error.body });
|
|
} else {
|
|
throw error;
|
|
}
|
|
}
|
|
```
|
|
|
|
## Caching
|
|
|
|
GET requests are cached; POST requests are not.
|
|
|
|
```ts
|
|
await socialhose.getMentions(
|
|
{ content_search: 'sudan' },
|
|
{ revalidateSeconds: 900 },
|
|
);
|
|
```
|
|
|
|
The default cache is process-local. Use a persistent/shared cache for production dashboards and rate-limit control.
|
|
|
|
## Operational pitfalls
|
|
|
|
- Entity analytics are request-heavy. One `getEntityStats()` call can issue roughly 20+ requests.
|
|
- The API rate limit is roughly 60 requests/minute per API key.
|
|
- The entity timeline uses cumulative differencing intentionally to avoid inclusive `date_to` double-counting.
|
|
- Exact entity sentiment/platform values are used only when facet counts reconcile with the known total.
|
|
- `409` mailing-list conflicts are normalized to `{ outcome: 'already' }`; other non-OK responses throw.
|