Technical reference

API documentation

Description

Authentication

Send the API key in the Authorization header and a unique Idempotency-Key for every write request. Keys are for server-side use only.

Authorization: Bearer <YOUR_API_KEY>
Idempotency-Key: <CLIENT_GENERATED_UUID>
Content-Type: application/json

Do not send a user UUID. Each API key is already bound to its owner, and every request is authorized as that user. Idempotency-Key is a client-generated UUID that identifies one write attempt, not a user.

AI integration brief

Copy this concise brief into an AI assistant to help it understand the API and generate an integration plan or request example.

Endpoints

Read active categories and use their id values in POST /api/v1/tools.categoryIds.

Call this first and pass one to five returned category UUIDs in categoryIds.

Required scope
Public
Credit cost
No charge
Idempotency-Key
Not required

Request fields

FieldTypeRequiredDescription
localestringNoOptional language code such as en. Defaults to en.

cURL example

curl 'https://navs.site/api/v1/categories?locale=en'

Success response

{
  "code": 200,
  "msg": "Categories retrieved successfully.",
  "data": {
    "locale": "en",
    "categories": [
      {
        "id": "<CATEGORY_UUID>",
        "slug": "ai-design-tools",
        "name": "AI Design Tools"
      }
    ]
  },
  "timestamp": 1723526400000
}

Response fields

FieldTypeNullableDescription
data.localestringNoLanguage code used for the returned dictionary.
data.categoriesarray of objectsNoActive category entries with id, slug, and name. Use id in categoryIds.

Upload each screenshot and optional logo before submitting a tool. The response contains a mediaUploadId for each uploaded image.

Pass each mediaUploadId as screenshots[].mediaId or logo.mediaId. Uploads must belong to the authenticated user.

Required scope
tools:write
Credit cost
No charge
Idempotency-Key
Not required

Request fields

FieldTypeRequiredDescription
imagefileYesMultipart form field. JPEG, PNG, WebP, or GIF; original file up to 5 MB; 10 uploads per user per minute.

cURL example

curl -X POST https://navs.site/api/v1/media/images \
  -H "Authorization: Bearer <YOUR_API_KEY>" \
  -F "image=@./preview.png"

Success response

{
  "code": 201,
  "msg": "Image uploaded successfully.",
  "data": {
    "mediaUploadId": "media_xxx",
    "expiresAt": "2026-08-19T05:00:00.000Z"
  },
  "timestamp": 1723526400000
}

Response fields

FieldTypeNullableDescription
data.mediaUploadIdstringNoUser-owned image ID to use as screenshots[].mediaId or logo.mediaId.
data.expiresAtISO 8601 timestampNoThe earliest cleanup time for an image that has not been attached. While the resource still exists it may be attached; after first attachment it remains reusable and can be reused by the same authenticated user.

Create a private tool draft with validated metadata for manual editorial review; API submissions never publish automatically.

First fetch category IDs with GET /api/v1/categories, then upload one to three screenshots through POST /api/v1/media/images. Use the returned IDs in categoryIds and screenshots[].mediaId. An optional logo also requires its own upload.

Required scope
tools:write
Credit cost
1 credit
Idempotency-Key
Required

Request fields

FieldTypeRequiredDescription
namestringYes2–160 characters.
websiteUrlstring (URL)YesPublic HTTP or HTTPS website URL; tracking parameters are removed.
oneLineDescriptionstringYes2–160 characters.
primaryKeywordstringYes1–25 characters.
categoryIdsstring[] (UUID)YesRequired array with 1–5 UUID strings returned in the id field by GET /api/v1/categories.
aiToolTypeenumYescore_ai, ai_assisted, or non_ai.
platformsstring[]Yes1–8 values: web, ios, android, macos, windows, linux, browser_extension, api.
languagesstring[]Yes1–20 supported ISO 639-1 language codes, such as en.
screenshotsobject[]YesRequired array with 1–3 items. Each item must contain mediaId (string, required; returned by POST /api/v1/media/images) and title (string, required, 1–120 characters). Do not send url or thumbnailUrl; the server resolves them from mediaId.
logoobject | nullNoOptional object. If present, mediaId (string, required; returned by POST /api/v1/media/images) is the only field needed. Send null to omit a logo.
featuresobject[]YesRequired array with 1–10 items. Each item must contain title (string, required, 1–120 characters) and description (string, required, 1–500 characters).
targetUsersobject[]NoOptional array with up to 5 items. Each item must contain audience (string, required) and useCase (string, required). Defaults to [].
faqItemsobject[]NoOptional array with up to 8 items. Each item must contain question (string, required) and answer (string, required). Defaults to [].
pricingModelenumYesfree, freemium, paid, or unknown.
trialStatusenumYesyes, no, or unknown.
taglinestringYes1–250 characters.
descriptionMarkdownstring (Markdown)Yes1–2,500 characters.
tagsstring[]No1–10 tags, each 1–80 characters. Defaults to [].
supportEmailstring (email)NoValid support email address.
youtubeVideoUrlstring (URL)NoStandard YouTube video URL.
faqPageUrlstring (URL)NoPublic HTTP or HTTPS FAQ URL.
helpCenterUrlstring (URL)NoPublic HTTP or HTTPS help center URL.
priceNotestringNoUp to 120 characters.
pricingDetailsstringNoUp to 5,000 characters.
pricingPageUrlstring (URL)NoPublic HTTP or HTTPS pricing URL.
alternativeToToolIdsstring[]NoUp to 100 existing tool IDs as positive decimal strings. Defaults to [].
submissionNotesstringNoUp to 2,000 characters.

cURL example

curl -X POST https://navs.site/api/v1/tools \
  -H "Authorization: Bearer <YOUR_API_KEY>" \
  -H "Idempotency-Key: <CLIENT_GENERATED_UUID>" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Example Studio",
  "websiteUrl": "https://example.com",
  "oneLineDescription": "An AI design workspace for product teams.",
  "primaryKeyword": "AI design",
  "categoryIds": [
    "<CATEGORY_UUID_FROM_CATEGORIES_API>"
  ],
  "aiToolType": "core_ai",
  "platforms": [
    "web"
  ],
  "languages": [
    "en"
  ],
  "screenshots": [
    {
      "mediaId": "<MEDIA_UPLOAD_ID>",
      "title": "Product screenshot"
    }
  ],
  "logo": {
    "mediaId": "<LOGO_MEDIA_UPLOAD_ID>"
  },
  "features": [
    {
      "id": "design",
      "title": "AI design",
      "description": "Create and revise designs with AI assistance."
    }
  ],
  "targetUsers": [],
  "faqItems": [],
  "pricingModel": "freemium",
  "trialStatus": "unknown",
  "tagline": "Design together with AI.",
  "descriptionMarkdown": "Example Studio helps product teams create and revise visual work.",
  "tags": [
    "design",
    "collaboration"
  ],
  "alternativeToToolIds": []
}'

Success response

{
  "code": 201,
  "msg": "Tool submitted successfully.",
  "data": {
    "id": "example-com",
    "status": "pending"
  },
  "timestamp": 1723526400000
}

Response fields

FieldTypeNullableDescription
data.idstringNoDirectory record slug created for the submission.
data.statusenumNoSubmission state; API submissions are pending editorial review.

Response format

Every response uses code (the HTTP status), msg (a human-readable summary), data (business data or null), and timestamp (Unix milliseconds). Failed responses also include errorCode for programmatic handling. The exact data fields are listed under each endpoint.

{
  "code": 201,
  "msg": "Tool submitted successfully.",
  "data": {
    "id": "example-com",
    "status": "pending"
  },
  "timestamp": 1723526400000
}

Failure response

{
  "code": 422,
  "msg": "The request failed validation.",
  "data": null,
  "timestamp": 1723526400000,
  "errorCode": "VALIDATION_ERROR"
}

Idempotency and retries

Repeating the same key with the same validated request returns the original result without creating another submission or using credits again. A different request with the same key returns a replay-mismatch error.

REST conventions

The API uses HTTPS, resource-oriented paths, HTTP methods, and matching HTTP status codes. Requests and responses use JSON except POST /api/v1/media/images, which accepts multipart/form-data.

Common errors

401 UNAUTHORIZED
The API key is missing, invalid, revoked, or unavailable.
403 API_ACCESS_REQUIRED
The current membership does not include API access.
429 RATE_LIMITED
The key has reached its request limit. Retry after the response delay.
402 INSUFFICIENT_CREDITS
Neither the current membership credits nor purchased credits can cover the operation.
422 VALIDATION_ERROR
The request did not pass validation; no credits are used.
409 IDEMPOTENCY_KEY_REPLAY_MISMATCH
The idempotency key was previously used with a different validated request.

Editorial policy

A successful API request does not promise inclusion, a particular external-link attribute, traffic, or search performance. Content remains subject to editorial review and may be rejected or removed.

Read the Terms of Service