---
title: "Submit a listing for review"
method: POST
path: "/v1/projects/{project_id}/listings/{listing_id}:submit"
tags: ["Listings"]
---

# Submit a listing for review

`POST /v1/projects/{project_id}/listings/{listing_id}:submit`

## Request

- Base URL: `https://api.naturali.ai`
- URL: `https://api.naturali.ai/v1/projects/{project_id}/listings/{listing_id}:submit`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://api.naturali.ai/authorize`, token URL `https://api.naturali.ai/token`, scopes: `mcp:access`)

Move a `draft` listing to `in_review`. naturali lists it in the marketplace or sends it back to `draft`. Any other state answers `409 invalid_listing_state`.

## Response `200`

Listing submitted.

- Listing: A listing, as its publisher reads it.
  - `id` string, required
  - `project_id` string, required: The publishing project.
  - `resource_type` 'tool' | 'agent', required: What the listing publishes.
  - `resource_id` string, required: The published tool or agent.
  - `title` string, required
  - `description` string, nullable, required
  - `pricing` ListingPricingComponent[], required: What an installing project is charged per call. Empty is free.
    - `component` string, required: The publisher's name for what is charged. Must not be a name the runtime already meters, such as `input_tokens` or `tool_call`.
    - `unit` string, required
    - `quantity` object, nullable, required: JSON Logic giving the quantity `unit_price_usd` multiplies, over `{ input, action, response, outcome, duration_ms }` for a tool and `{ response: { usage, cost_usd, steps, tool_calls, stop_reason }, outcome }` for an agent. `null` charges one per call. A failed call is never charged a component.
    - `unit_price_usd` number, required: US dollars per `unit`.
  - `pricing_next` ListingPricingNext, nullable, required: A price increase waiting out its notice. Installing projects are charged `pricing` until `effective_from`, then this.
    - `effective_from` string, date-time, required
    - `pricing` ListingPricingComponent[], required
      - `component` string, required: The publisher's name for what is charged. Must not be a name the runtime already meters, such as `input_tokens` or `tool_call`.
      - `unit` string, required
      - `quantity` object, nullable, required: JSON Logic giving the quantity `unit_price_usd` multiplies, over `{ input, action, response, outcome, duration_ms }` for a tool and `{ response: { usage, cost_usd, steps, tool_calls, stop_reason }, outcome }` for an agent. `null` charges one per call. A failed call is never charged a component.
      - `unit_price_usd` number, required: US dollars per `unit`.
  - `state` 'draft' | 'in_review' | 'listed' | 'suspended', required: `draft` until submitted, `in_review` until naturali decides, `listed` in the marketplace, `suspended` when paused by its publisher or by naturali.
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required

## Other responses

- `401`: Missing or invalid credentials.
- `403`: The credential is scoped to a different project, or the caller's role in the project does not carry this action.
- `404`: The resource does not exist (existence is not leaked).
- `409`: `listing_exists` (the resource already has a listing) or `invalid_listing_state` (the move is not allowed from the listing's current state).
- `503`: `model_not_priced`: the agent runs on a naturali model that has no price yet, so its use could not be billed.

---

[API](https://skmtc.dev/naturali/apis/naturali-ai-api.md) · [All operations](https://skmtc.dev/naturali/apis/naturali-ai-api/llms.txt) · [OpenAPI document](https://skmtc.dev/naturali/apis/naturali-ai-api/revisions/e4905b78f422?raw)
