Use these endpoints to publish and maintain the things people join in Hive3: events, courses, content, quests and jobs. You can sync a catalog from another system, schedule events from a calendar, post jobs from an applicant tracker, or let an AI agent draft and publish for a community you help run. All five kinds share one set of operations, described here. Course and content fields, event scheduling and world booking, and quest credits have their own pages: Courses and content, Events: slots and worlds and Quests: credits and objectives. To enroll, RSVP, apply or review participants, see Participation workflows.
API access needs a Honey Bee plan or above; see the developer overview. The examples read the key from HIVE_API_KEY. Operations shown with one curl block follow the same pattern in JavaScript (fetch) and Python (requests) as the full examples. Some field names still say community or person; both identify accounts, and a "community" is an account that others join.
#Kinds and scopes
The path segment {kind} is one of events, courses, content, quests or jobs. Posts use the same shape on their own page.
| Operation | Scope | Also needed for a community |
|---|---|---|
| List, get | resources:read | communities:read |
| Create, update, archive | resources:write | communities:write |
For a community you manage, the key owner must currently be an owner, admin or moderator of it, and the key's account allowlist (if set) must include it; see Managed accounts. Reads return only resources owned by your account or by accounts you manage; other accounts' public resources return 404. Use Search to find them.
#Shared behavior
- Owner. Create for your own account by omitting
owner(or{ "type": "person" }). To create for a community, send{ "owner": { "type": "community", "communityId": "account_456" } }(an account ID or@handle). Any otherownervalue is ignored.owneris ignored on update. - Visibility.
public(default),protected(members only) orprivate; unknown values becomepublic. A Worker Bee owning account can only publishpublicresources: a request that newly sets another value returns403 forbidden(A Honey Bee subscription is required to make content members-only or private), and one that newly sets asubscriptionIdreturns403 forbidden(A Honey Bee subscription is required to sell subscriptions, tickets or paid access). The owning account's plan decides, not the acting admin's. Values a resource already stores can stay after a downgrade. - Subscriptions.
subscriptionIdties access to one of the owning account's subscription plans. Moderators can only choose an existing plan of that account (403 forbidden,Choose an existing subscription plan of this account). - Title and description.
title(orname) is required on create (400,Title is required).descriptionalso acceptsshortDescriptionandbody. - Images and files. URL fields (
imageUrl,heroImage,attachmentUrl) take plain URLs.*StorageIdfields (imageStorageId,heroImageStorageId,attachmentStorageId,employerLogoStorageId) take upload IDs from Uploads made by the same key owner. Image fields need an image upload; a bad ID returns400 invalid_request(imageStorageId must be a valid storage ID) or404 not_found. - Other fields. For events, courses, content and quests the whole JSON body is kept in the response's
dataobject, so unknown fields are stored as sent. Jobs keep only the fields listed below. - Server-owned fields. The server sets
id,type,owner,createdAt,updatedAtandarchivedAt. Each kind also protects a few fields (eventmetaverseTime,courseId,kind,officeHoursandsessionKey; questmaxQuestDays,questCreditSource,questCreditId) and ignores values you send for them. - Timestamps. Resource timestamps in responses are epoch milliseconds. Schedule fields you send are ISO 8601 strings; events require an offset or
Z(Timestamps). - Updates.
PATCHis partial: omitted fields keep their value. Arrays you send (eventSlots,lessons,objectives,sections,tags,badges) replace the stored array. - Archiving.
DELETEarchives; archived resources disappear from lists, reads and search and cannot be updated (404).
| Kind | Creates per day | Request size limit |
|---|---|---|
events | 20 | 128 KiB |
courses | 10 | 256 KiB |
content | 50 | 256 KiB |
quests | 30 | 128 KiB |
jobs | 20 | 64 KiB |
All kinds allow 60 creates per minute, 120 updates per minute and 60 archives per minute per account, on top of the account's 600 requests per minute. A body above its size limit (measured on the serialized request) returns 400 invalid_request (<kind> payload is too large), or 413 when the raw body is more than 4 KiB over it. Limited requests return 429 rate_limited with Retry-After.
#List and read resources
/api/v1/{kind}Scoperesources:readcommunities:read (managed accounts)Lists active resources of one kind, newest first. Without filters you get your own resources, plus those of up to 25 communities you currently moderate when the key has communities:read. The example lists jobs.
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
kind | path | string | Yes | events, courses, content, quests or jobs. |
limit | query | integer | No | 1 to 100, default 25. Zero or negative returns 400. |
cursor | query | string | No | The page.nextCursor of the previous page. |
communityId | query | string | No | List one account's resources (ID or @handle). Needs communities:read. |
ownerType | query | string | No | person or community; it does not filter by type. community without communityId returns an empty list. |
curl "https://app.hive3.tech/api/v1/jobs?limit=2" \
-H "Authorization: Bearer $HIVE_API_KEY"const res = await fetch("https://app.hive3.tech/api/v1/jobs?limit=2", {
headers: { Authorization: `Bearer ${process.env.HIVE_API_KEY}` },
});
const { data, page } = await res.json();import os, requests
res = requests.get(
"https://app.hive3.tech/api/v1/jobs",
params={"limit": 2},
headers={"Authorization": f"Bearer {os.environ['HIVE_API_KEY']}"},
)
jobs = res.json()["data"]Returns 200. Errors: 403 insufficient_scope (communities:read missing), 403 forbidden (account not managed by the key).
{
"data": [
{
"id": "job_123",
"type": "job",
"title": "Community Manager",
"description": "Grow and support our member community.",
"employerName": "Design Guild",
"employmentType": "full-time",
"location": "Remote",
"status": "published",
"visibility": "public",
"badges": [],
"owner": { "type": "person", "personId": "account_123" },
"createdAt": 1767225600000,
"updatedAt": 1767225600000
}
],
"page": { "nextCursor": null, "hasMore": false }
}/api/v1/{kind}/{id}Scoperesources:readcommunities:read (managed accounts)Returns one active resource owned by your account or an account you manage. Anything else, including archived resources, returns 404 not_found (Resource not found).
curl https://app.hive3.tech/api/v1/jobs/job_123 \
-H "Authorization: Bearer $HIVE_API_KEY"Returns 200 with the resource object.
#Create a resource
/api/v1/{kind}Scoperesources:writecommunities:write (community owner)Creates a resource and returns it. Send an Idempotency-Key header (up to 128 characters) to make retries safe: the same key with the same body returns the first 201 response without creating a second resource, and the same key with a different body or kind returns 409 conflict. Only successful responses are remembered. Common body fields are below; each kind adds its own (see the field sections that follow). The example creates a job.
| Name | In | Type | Required | Notes |
|---|---|---|---|---|
kind | path | string | Yes | events, courses, content, quests or jobs. |
title | body | string | Yes | name is accepted as an alias. |
description | body | string | No | Defaults to an empty string. |
visibility | body | string | No | public, protected, private. |
subscriptionId | body | string | No | One of the owning account's subscription plans. |
owner | body | object | No | Owner selector. |
badges | body | string array | No | Labels shown on the resource. |
curl -X POST https://app.hive3.tech/api/v1/jobs \
-H "Authorization: Bearer $HIVE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: job-community-manager-001" \
-d '{"title":"Community Manager","description":"Grow and support our member community.","employerName":"Design Guild","employmentType":"full-time","location":"Remote"}'const res = await fetch("https://app.hive3.tech/api/v1/jobs", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.HIVE_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": "job-community-manager-001",
},
body: JSON.stringify({
title: "Community Manager",
description: "Grow and support our member community.",
employerName: "Design Guild",
employmentType: "full-time",
location: "Remote",
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://app.hive3.tech/api/v1/jobs",
headers={
"Authorization": f"Bearer {os.environ['HIVE_API_KEY']}",
"Idempotency-Key": "job-community-manager-001",
},
json={
"title": "Community Manager",
"description": "Grow and support our member community.",
"employerName": "Design Guild",
"employmentType": "full-time",
"location": "Remote",
},
)
job = res.json()["data"]Returns 201.
{
"data": {
"id": "job_123",
"type": "job",
"title": "Community Manager",
"description": "Grow and support our member community.",
"employerName": "Design Guild",
"employmentType": "full-time",
"location": "Remote",
"status": "published",
"visibility": "public",
"badges": [],
"owner": { "type": "person", "personId": "account_123" },
"createdAt": 1767225600000,
"updatedAt": 1767225600000
}
}| Status | code | When |
|---|---|---|
| 400 | invalid_request | Title is required, malformed JSON, an invalid upload ID, a kind-specific rule, or a body over the size limit. |
| 403 | insufficient_scope | A community owner without communities:write (requiredScopes). |
| 403 | forbidden | The key does not include that account, your role is too low, or the Worker Bee rule applies. |
| 404 | not_found | Unknown owner account or upload. |
| 409 | conflict | Idempotency-Key reused with a different request. |
| 429 | rate_limited | A per-minute or per-day creation limit. |
#Update and archive
/api/v1/{kind}/{id}Scoperesources:writecommunities:write (community-owned)Partially updates a resource with the same field names as create (without owner). The stored owner decides who may edit; the key owner needs a live owner, admin or moderator role on a community-owned resource. Events and quests that have started return 409 conflict and can no longer be edited.
curl -X PATCH https://app.hive3.tech/api/v1/jobs/job_123 \
-H "Authorization: Bearer $HIVE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"location":"Remote (Europe)","payRangeMin":"60000","payRangeMax":"80000"}'Returns 200 with the updated resource. Errors: 400 (a kind-specific rule), 403 forbidden or insufficient_scope, 404 not_found (unknown or archived), 409 conflict (started event or quest).
/api/v1/{kind}/{id}Scoperesources:writecommunities:write (community-owned)Archives a resource; nothing is hard-deleted. Archiving an event that has not started also refunds the metaverse time it reserved. Events and quests that have started return 409 conflict (This event has started and can no longer be cancelled.). Archiving a quest does not refund its quest credit.
curl -X DELETE https://app.hive3.tech/api/v1/jobs/job_123 \
-H "Authorization: Bearer $HIVE_API_KEY"Returns 200 with { "data": { "archived": true, "id": "job_123", "type": "job" } }. Archiving an already archived resource also returns 200, quests included, so a retry is safe.
#Job fields
Jobs keep only the fields below; others are dropped. Courses, content, events and quests have their own field lists on the pages linked at the end.
| Field | Type | Notes |
|---|---|---|
title | string | Required. |
description | string | Job text. |
employerName | string | Default Hive employer. |
employmentType | string | full-time (default), part-time, contract or intern. Other values fall back to the default on create and keep the stored value on update. |
location | string | Default Remote. |
payRangeMin, payRangeMax | string | Free text such as "60000". Numbers are ignored. |
employerLogo | string | Logo URL (employerLogoUrl and imageUrl also work). employerLogoStorageId or imageStorageId take an upload ID. |
attachmentUrl | string | Link to a document (documentUrl also works). attachmentStorageId takes an upload ID. |
status | string | Default published. |
visibility, subscriptionId, badges | As in Shared behavior. subscriptionID also works. |
#Fields for the other kinds
Courses, content, events and quests take more fields than the common ones above:
- Courses and content have lessons, office hours, sections and tags. See Courses and content.
- Events take
eventSlots(each with ISO 8601startsAtandendsAt),autoEnroll(defaultfalse) and an optionalworldId. See Events: slots and worlds. - Quests need a
questCreditPlan(singleorbundle) that spends one quest credit, plusobjectives,startsAtandendsAt. See Quests: credits and objectives.