2026-05-29 13:35:09 -05:00
# 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.
2026-05-29 14:47:41 -05:00
## 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.
2026-05-29 13:35:09 -05:00
## 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.