API

A read-only JSON API for accessing community data. No authentication required. CORS enabled.

Base URL

Endpoints

EndpointDescription
/api/companiesList companies
/api/companies/:slugGet company
/api/eventsList events
/api/events/:slugGet event
/api/groupsList groups
/api/groups/:slugGet group
/api/jobsList jobs
/api/jobs/:slugGet job
/api/educationList education
/api/education/:slugGet education
/api/newsList news
/api/news/:slugGet news article
/api/peopleList people
/api/people/:slugGet person
/api/projectsList projects
/api/projects/:slugGet project
/api/productsList products
/api/products/:slugGet product
/api/technologiesList technologies
/api/technologies/:slugGet technology

Pagination

List endpoints support pagination:

  • limit - Number of items (default: 20, max: 100)
  • offset - Items to skip (default: 0)

Responses include a pagination object:

{
  "data": [...],
  "pagination": {
    "total": 42,
    "limit": 20,
    "offset": 0,
    "hasMore": true
  }
}

Responses also include RFC 5988 Link headers for navigation:

Link: <https://siliconharbour.dev/api/companies?limit=20&offset=20>; rel="next",
      <https://siliconharbour.dev/api/companies?limit=20&offset=0>; rel="first"

OpenAPI Specification

View OpenAPI Spec

MCP Server

An MCP (Model Context Protocol) server is available at /mcp for AI assistants and agents.

Endpoint: https://siliconharbour.dev/mcp

Tools

Three MCP tools are exposed. Expand any tool to see the functions it makes available — this listing is auto-generated from the bridge implementation so it always reflects the live server.

searchPublicexpand

Search the SiliconHarbour API schema to discover available entities and field shapes. Call this first to learn what data exists, then use query or execute to fetch it.

queryPublic8 functionsexpand

Execute JavaScript in a secure QuickJS sandbox to read SiliconHarbour data. Imports below are available from the 'siliconharbour' module. Each call hits the real database on-demand. Timeout: 10 seconds.

Read (8)
companies({ query?, limit?, offset? })
List visible companies. Optional query filters by name and description.
education({ limit?, offset? })
List educational institutions and programs.
events({ upcoming?, limit?, offset?, query? })
List events. Pass upcoming:true to limit to future events. Defaults to limit 20.
groups({ limit?, offset? })
List community groups.
jobs({ query?, limit?, offset? })
List active jobs (includes both technical and non-technical postings). Optional text query searches indexed content.
news({ query?, limit?, offset? })
List published news items. Optional query filters by indexed content.
people({ query?, limit?, offset? })
List visible people from the directory.
technologies({ limit?, offset? })
List technologies referenced across the directory.
executeAuthenticated27 functionsexpand

Like query, but also exposes sync, creation, review, and lifecycle functions. Requires an authenticated MCP session (apiToken). Timeout: 60 seconds.

Read (8)
companies({ query?, limit?, offset? })
List visible companies. Optional query filters by name and description.
education({ limit?, offset? })
List educational institutions and programs.
events({ upcoming?, limit?, offset?, query? })
List events. Pass upcoming:true to limit to future events. Defaults to limit 20.
groups({ limit?, offset? })
List community groups.
jobs({ query?, limit?, offset? })
List active jobs (includes both technical and non-technical postings). Optional text query searches indexed content.
news({ query?, limit?, offset? })
List published news items. Optional query filters by indexed content.
people({ query?, limit?, offset? })
List visible people from the directory.
technologies({ limit?, offset? })
List technologies referenced across the directory.
Import sources (4)
eventImportSources()
List all event import sources with id, sourceType, fetchStatus, lastFetchedAt, and pendingCount.
jobImportSources()
List all job import sources with id, sourceType, fetchStatus, and lastFetchedAt.
listImporterTypes()
Return metadata for every job importer type (greenhouse, ashby, workday, bamboohr, lever, custom, etc.) — name, approach, reliability, quirks.
newsImportSources()
List all news import sources (RSS feeds and custom) with enabled flag, lastSyncStatus, and pendingCount.
Synchronous sync (2)
syncAllSources({ type? }) where type is 'event'|'job'|'news' (omit to sync all)
Synchronously sync all sources of the given type sequentially. If type omitted, syncs every event, job, and news source in turn.
syncSource({ type, sourceId }) where type is 'event'|'job'|'news'
Run a sync for a single import source. Dispatches by `type` to the matching sync function.
Background sync (3)
asyncSyncAllSources({ type? }) where type is 'event'|'job'|'news' (omit to sync all)
Start a background sync of all sources of the given type. If type omitted, queues every event, job, and news source in one run. Returns a runId — poll via getAsyncSync(runId).
getAsyncSync(runId)
Get the live status of a background sync run: { status, completed, failed, current, steps[] }.
listAsyncSyncs()
List recent background sync runs (most recent first, max 20 stored).
Creation (3)
createEntity({ type, ...fields })
Create an entity. `type` dispatches to the matching create flow: person, education, product, project, technology, company, group, event, job, event-source, job-source, news-source, news-article, news-link. Slug auto-generated where applicable; most entities default visible=false so an admin can review before publishing. Per-type field requirements are listed in the execute tool description; also discoverable via search('createEntity <type>').
deleteEntity({ type, id })
Delete an entity by id. Types: person, education, product, project, technology, company, group, event, job, event-source, job-source, news-source. Use with care — there is no undo, and deleting an import source orphans any pending events/jobs/news that came from it.
updateEntity({ type, id, ...fields })
Patch fields on an entity. `type` dispatches: person, education, product, project, technology, company, group, event, job, news, event-source, job-source, news-source. All fields except `type` and `id` are optional — only supplied fields are updated.
Lookup / detail (2)
getEntity({ type, by, value }) where by is 'id'|'slug'|'name'
Look up an entity. `by:'name'` is only supported for type:'company'. Types: company, group, person, education, product, project, technology, job, news, event, event-source, job-source, news-source. Source types support by:'id' only. Returns { found: true, type, entity } or { found: false }.
listEntities({ type, filter? }) where filter is 'manual'|'pending'|'all'
List entities by kind and filter. Types include the 8 directory entities (job, event, news, company, group, person, education, technology) and the 3 source types (event-source, job-source, news-source). filter:'pending' (job, event, news) returns the pending_review queue. filter:'manual' (job, event) returns manually-created entries (sourceType='manual' for jobs, no importSourceId for events). filter:'all' (the default for source types) returns the unfiltered set.
External search (4)
getTechNLJob(link)
Full HTML/text description for one TechNL posting by its link.
listTechNLJobs()
Live technl.ca job board with company-match info so you can spot which postings we already have via createEntity({ type:'job' }) or an importer.
searchIndeedJobs({ query?, location?, limit?, hoursOld? })
Search Indeed via their mobile GraphQL API. Returns id, title, company, location, description, salary, datePosted. Default location: "St. John's, NL".
searchLinkedInJobs({ query?, location?, limit? })
Search LinkedIn via the public jobs-guest endpoint. No authentication required. Returns id, title, company, location, url, datePosted, salary.
Lifecycle / review (1)
reviewEntity({ type, id, action })
Move a pending entity to its final state. type:'job' actions: approve | approve-non-technical | hide | requeue | deactivate-removed | deactivate-filled | deactivate-expired. type:'news' actions: approve | hide.

Setup (Claude Desktop / OpenCode)

Public access — no token needed:

{
  "mcpServers": {
    "siliconharbour": {
      "url": "https://siliconharbour.dev/mcp"
    }
  }
}

Example queries

// Upcoming events
import { events } from "siliconharbour";
export default await events({ upcoming: true, limit: 5 });
// Jobs filtered by keyword
import { jobs } from "siliconharbour";
export default await jobs({ query: "developer", limit: 10 });
// Cross-entity query
import { events, companies, groups } from "siliconharbour";
const [upcoming, cos, grps] = await Promise.all([
  events({ upcoming: true }),
  companies({ limit: 5 }),
  groups({ limit: 5 }),
]);
export default {
  upcoming: upcoming.length,
  companies: cos.map((c) => c.name),
  groups: grps.map((g) => g.name),
};

Feeds

RSS feeds and an iCal calendar are also available. See Stay Connected for details.

  • /feed.rss - Combined RSS feed
  • /events.rss - Events RSS feed
  • /news.rss - News RSS feed
  • /jobs.rss - Jobs RSS feed
  • /calendar.ics - iCal calendar subscription