Nodaro Docs
DocumentationNode ReferenceModelsAI Agents (MCP)DevelopersSelf-hostingResearch
REST API

Community Library

Browse, search, favorite and clone shared characters, locations and objects from the Community Library over REST, and report a listing for moderation.

Available on Nodaro Cloud · Business edition

The Community Library API lets you browse the shared catalog of characters, locations and objects on your Nodaro instance, and clone a listing into your own library. The catalog is curated: the instance's admins publish listings, and every signed-in user can search, favorite, clone and report them.

The library is a multi-user feature. It exists on Nodaro Cloud and on self-hosted Business edition; on a Community edition instance these routes are not registered and answer 404. The routes take a bearer token: a personal API token (ndr_…), an OAuth app token (ndr_app_…) or your session token. See Authentication.

Endpoints

MethodPathWhat it does
GET/v1/community/browseList public listings, one page at a time.
GET/v1/community/detail/:slugGet one listing by its slug.
GET/v1/community/favoritesThe listings you favorited.
POST/v1/community/listings/:id/cloneCopy a listing into your library.
POST/v1/community/listings/:id/favoriteAdd or remove a favorite.
POST/v1/community/listings/:id/reportReport a listing for moderation.

What a listing holds

Every read route returns listings with these public fields only.

FieldWhat it holds
id, slugThe listing's id, used by the write routes, and its slug, used by the detail route.
entity_typecharacter, location or object.
title, description, category, style, tagsWhat the admin wrote when publishing.
creator_display_nameWho published the listing.
preview_media_url, preview_imagesThe preview picture and the gallery of images.
clone_count, favorite_countHow many times the listing was cloned and favorited.
created_atWhen the listing was published.

GET /v1/community/browse returns { data: Listing[], nextCursor }. Pass nextCursor back as cursor for the next page; it is null when there are no more results.

Query parameterWhat it does
entityTypecharacter, location or object.
qFull-text search across the title, the description and the tags.
categoryOnly one category.
sortnewest (the default) or popular, the most cloned first.
limitPage size, 20 by default and 50 at most.
cursorThe nextCursor of the previous page.
curl "https://app.nodaro.ai/v1/community/browse?entityType=character&sort=popular&limit=20" \
  -H "Authorization: Bearer $NODARO_API_KEY"
import { createClient, StaticTokenAuth } from '@nodaro/sdk'

const client = createClient({
  baseUrl: 'https://app.nodaro.ai',
  auth: new StaticTokenAuth(process.env.NODARO_API_KEY!),
})

const { data, nextCursor } = await client.community.browse({
  entityType: 'character',
  sort: 'popular',
  limit: 20,
})
{
  "data": [
    {
      "id": "e4b2d8f1-6a3c-4e9b-8d7f-1c5a3e9b2d6f",
      "entity_type": "character",
      "slug": "detective-mara",
      "title": "Detective Mara",
      "description": "Noir-styled investigator",
      "category": "people",
      "style": "realistic",
      "tags": ["noir", "detective"],
      "creator_display_name": "Nodaro Team",
      "preview_media_url": "https://cdn.nodaro.ai/community/detective-mara.png",
      "clone_count": 128,
      "favorite_count": 41,
      "created_at": "2026-08-30T14:02:11Z"
    }
  ],
  "nextCursor": "eyJjcmVhdGVkX2F0IjoiMjAyNi0wOC0zMCJ9"
}

GET /v1/community/detail/:slug returns { data: Listing }, or 404 not_found when the listing does not exist or was taken down. GET /v1/community/favorites returns { data: Listing[] }.

Clone a listing

POST /v1/community/listings/:id/clone copies a listing into your library and returns { entityType, id }: the kind and the id of your new character, location or object. The body is { entityType }, which must match the listing's kind.

  • It is a copy, not a link. The listing's images and clips are copied into your own storage. Later changes to the original, or the listing being taken down, do not affect your copy.
  • It is yours. The clone is an ordinary character, location or object. Rename it, edit it, regenerate its assets or delete it.
  • Names do not collide. When you already have one with the same name, the clone gets a unique name with a copy suffix.
  • It uses your storage. When your account is over its storage limit, the clone is refused with 413 storage_limit_exceeded.

An OAuth app token needs the assets:write scope to clone. Personal API tokens need no scope.

curl -X POST https://app.nodaro.ai/v1/community/listings/e4b2d8f1-6a3c-4e9b-8d7f-1c5a3e9b2d6f/clone \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "entityType": "character" }'
const { id } = await client.community.clone(listingId, 'character')
const mara = await client.characters.get(id)
{ "entityType": "character", "id": "5a7c9e1b-3d4f-4a2c-b8e6-9f1d3b5a7c2e" }

Use the new id with the Characters, Locations or Objects API.

Favorite a listing

POST /v1/community/listings/:id/favorite toggles your favorite and returns { favorited }: true after adding it, false after removing it.

const { favorited } = await client.community.favorite(listingId)
const { data: favorites } = await client.community.favorites()

Report a listing

POST /v1/community/listings/:id/report flags a listing for the admins to review and returns { ok: true }. The body is { reason }, one of:

reasonUse it when the listing…
real_person_no_consentShows a real person who did not consent.
inappropriateContains inappropriate content.
ip_violationInfringes someone's intellectual property.
otherHas any other problem.
await client.community.report(listingId, 'real_person_no_consent')

A listing can be taken down after a report. Copies that users already cloned stay in their libraries.

Publishing is curated

The catalog is curated by the instance's admins. Publishing a listing is not part of the public API or the SDK. See Community Library.

Errors

StatusCodeMeaning
400validation_errorA field is missing or invalid.
401unauthorizedThe token is missing, invalid or revoked.
403insufficient_scopeAn OAuth app token lacks assets:write for a clone.
404not_foundThe listing does not exist or was taken down, or the instance is Community edition.
413storage_limit_exceededYour account is over its storage limit.

Frequently asked questions

Last updated on

On this page