# Partner Public API

## Background

Cournot is an AI-driven oracle for prediction-market resolution. For every market it covers, Cournot produces a final settlement record — verdict, confidence tier, and on-chain proofs — and makes that record publicly auditable by both Partners and end users.

Partners use Cournot as the source of truth for resolving their own markets: once Cournot publishes a verdict, the Partner pulls that record and uses it to settle the corresponding market on their platform.

Two public endpoints support this:

* **`get_public_market`** — anonymous read. Look up a market by `slug` + `source` and return its public record (status / verdict / confidence / proofs / disputes). The primary endpoint Partners call to drive their own resolution.
* **`submit_dispute`** — Partner-authenticated write. If an end user disagrees with a Cournot verdict, the Partner backend can file a dispute on their behalf.

The `source` value is a Partner-specific identifier issued by Cournot at integration time. Each Partner uses its own dedicated value; it is not a public enum.

## Typical integration flow

The primary loop: Partner pulls Cournot's verdict and settles its own market.

```
   Partner backend                                                        Cournot
        │                                                                    │
        │  GET /markets/public?slug=...&source=...                           │
        │ ─────────────────────────────────────────────────────────────────► │
        │ ◄────── { markets:[{ status, verdict, confidence, proofs }] } ──── │
        │                                                                    │
        │  (status = resolved → settle the corresponding Partner market)     │
        │                                                                    │
```

* Poll `get_public_market` for the relevant market. When `status = resolved`, `verdict` / `confidence` / `proofs` are populated.
* Use the returned record to settle the Partner-side market. On-chain `proofs` can be surfaced to end users for auditability.
* No authentication is required for this loop.

## Dispute flow (optional)

If an end user disputes a Cournot verdict, the Partner backend can file the dispute and observe its outcome through the same `get_public_market` endpoint.

```
   end user (Partner)                  Partner backend                    Cournot
        │                                     │                              │
        │   "I disagree with this verdict"    │                              │
        │ ──────────────────────────────────► │                              │
        │                                     │  POST /markets/dispute/      │
        │                                     │       submit                 │
        │                                     │ ───────────────────────────► │
        │                                     │ ◄───── { dispute_id } ────── │
        │                                     │                              │
        │  (later — anyone, no auth)                                         │
        │                                                                    │
        │  GET /markets/public?slug=...&source=...                           │
        │ ─────────────────────────────────────────────────────────────────► │
        │ ◄────── { markets:[{ ..., disputes:[{ ..., decision }] }] } ────── │
```

* Once a dispute is filed, the market transitions from `resolved` to `disputed` and Cournot starts an internal review.
* After the review, the market becomes `closed` and the dispute carries a `decision` — `keep` retains Cournot's verdict, `override` adopts the submitter's selection.
* Partner reads the dispute's progress and final decision via `get_public_market`. Disputes are returned inline as a sub-resource on the market — there is no separate dispute-read endpoint.

## Response envelope

All responses share the same envelope and **always return HTTP 200**. Success vs. failure is signalled by the `code` field, not the HTTP status code.

**Success:**

```json
{ "code": 0, "msg": "Success", "data": { /* endpoint payload */ } }
```

**Error:**

```json
{ "code": 4100, "msg": "slug is required", "detail": "slug is required" }
```

| field    | type   | description                                                |
| -------- | ------ | ---------------------------------------------------------- |
| `code`   | int    | `0` = success; non-zero = error                            |
| `msg`    | string | human-readable message                                     |
| `data`   | object | present on success; carries the endpoint payload           |
| `detail` | string | present on error; additional detail (often equal to `msg`) |

**Integration note:** do not branch on HTTP status. Read `code` — `0` means success and `data` is populated; any other value means the request failed and `msg` / `detail` describe why.

The endpoint specs below describe the contents of `data`.

## 1) get\_public\_market

Look up a market's public record by `slug` + `source`. This is a **market endpoint**: it returns the market's status / verdict / confidence / on-chain proofs, with disputes embedded as a sub-resource on the market. Disputes appear here because they belong to the market — there is no separate dispute-read endpoint.

|            |                           |
| ---------- | ------------------------- |
| **Method** | `GET`                     |
| **Path**   | `/cournot/markets/public` |
| **Auth**   | none (anonymous)          |

**Query params**

| field    | type   | required | description                                  |
| -------- | ------ | -------: | -------------------------------------------- |
| `slug`   | string |      yes | market slug (no leading/trailing `/`)        |
| `source` | string |      yes | Partner-specific source id issued by Cournot |

**`data.markets[]` (`market_item`)**

| field         | type                       | description                                          |
| ------------- | -------------------------- | ---------------------------------------------------- |
| `id`          | int64                      | market id                                            |
| `source`      | string                     | request source                                       |
| `slug`        | string                     | request slug                                         |
| `status`      | string                     | `monitoring` · `resolved` · `disputed` · `closed`    |
| `verdict`     | string                     | final verdict                                        |
| `resolved_at` | string                     | RFC3339 UTC, e.g. `2026-04-28T10:30:00Z`             |
| `confidence`  | string                     | `VERY_HIGH` · `HIGH` · `MEDIUM` · `LOW` · `VERY_LOW` |
| `reasoning`   | string                     | human-readable explanation of the verdict            |
| `proofs`      | `proof_item[]`             | on-chain proofs                                      |
| `disputes`    | `dispute_item[]` \| `null` | dispute list; `null` when the market has no disputes |

**`proof_item`**

| field     | type   | description    |
| --------- | ------ | -------------- |
| `chain`   | string | `base` · `bsc` |
| `tx_hash` | string | tx hash        |

**`dispute_item`**

| field                 | type             | description                               |
| --------------------- | ---------------- | ----------------------------------------- |
| `id`                  | int64            | dispute id                                |
| `status`              | string           | `open` · `closed`                         |
| `submitter_selection` | string           | submitter's claimed outcome               |
| `reason_text`         | string           | dispute reason                            |
| `submitted_at`        | string           | RFC3339 UTC                               |
| `decision`            | object \| `null` | present only when the dispute is `closed` |

**`decision`**

| field                   | type   | description                                                   |
| ----------------------- | ------ | ------------------------------------------------------------- |
| `type`                  | string | `keep` · `override`                                           |
| `partner_final_verdict` | string | `override` → `submitter_selection`; `keep` → market `verdict` |
| `reason_text`           | string | decision reason                                               |
| `decided_at`            | string | RFC3339 UTC                                                   |

**Example**

```bash
curl -G "https://interface.cournot.ai/cournot/markets/public" \
  --data-urlencode "slug=ram-average-price-above-600-by-end-of-march" \
  --data-urlencode "source=YOUR_SOURCE_ID"
```

```json
{
  "code": 0,
  "msg": "Success",
  "data": {
    "markets": [
      {
        "id": 61,
        "source": "YOUR_SOURCE_ID",
        "slug": "ram-average-price-above-600-by-end-of-march",
        "status": "resolved",
        "verdict": "YES",
        "resolved_at": "2026-04-28T10:08:40Z",
        "confidence": "HIGH",
        "reasoning": "multi-source evidence confirmed the final outcome is YES",
        "proofs": [
          { "chain": "base", "tx_hash": "0xabc..." },
          { "chain": "bsc", "tx_hash": "0xdef..." }
        ],
        "disputes": [
          {
            "id": 4,
            "status": "closed",
            "submitter_selection": "NO",
            "reason_text": "we believe the resolved outcome is incorrect based on source evidence",
            "submitted_at": "2026-04-28T10:30:00Z",
            "decision": {
              "type": "override",
              "partner_final_verdict": "NO",
              "reason_text": "submitted dispute is valid",
              "decided_at": "2026-04-28T11:00:00Z"
            }
          }
        ]
      }
    ]
  }
}
```

When the market has no disputes, `disputes` is `null` (not `[]`). When no market matches `slug` + `source`, `data.markets` is `[]`.

## 2) submit\_dispute

File a dispute on behalf of an end user on the Partner platform.

|                  |                                          |
| ---------------- | ---------------------------------------- |
| **Method**       | `POST`                                   |
| **Path**         | `/cournot/markets/dispute/submit`        |
| **Auth**         | header `x-api-key: YOUR_PARTNER_API_KEY` |
| **Content-Type** | `application/json`                       |

**Request body**

| field                 | type   | required | description                                                 |
| --------------------- | ------ | -------: | ----------------------------------------------------------- |
| `market_id`           | int64  |      yes | market id                                                   |
| `submitter_id`        | string |      yes | end user's unique id on the partner side                    |
| `submitter_name`      | string |      yes | submitter display name                                      |
| `submitter_selection` | string |      yes | outcome the submitter claims is correct (e.g. `YES` / `NO`) |
| `reason_text`         | string |      yes | dispute reason                                              |
| `submitted_at`        | string |      yes | RFC3339 UTC; if omitted/invalid, server uses current time   |

**`data` (response payload)**

| field        | type  | description        |
| ------------ | ----- | ------------------ |
| `dispute_id` | int64 | created dispute id |

**Business rules**

* `x-api-key` must be valid.
* The partner's `source` (resolved from the API key) must equal the market's `source` — no cross-partner disputes.
* Only markets with `status = resolved` can be disputed.
* A market can have at most one dispute (a second submission errors out).

**Example**

```bash
curl -X POST "https://interface.cournot.ai/cournot/markets/dispute/submit" \
  -H "content-type: application/json" \
  -H "x-api-key: YOUR_PARTNER_API_KEY" \
  -d '{
    "market_id": 61,
    "submitter_id": "partner_user_1001",
    "submitter_name": "alice",
    "submitter_selection": "NO",
    "reason_text": "we believe the resolved outcome is incorrect based on source evidence",
    "submitted_at": "2026-04-28T10:30:00Z"
  }'
```

```json
{ "code": 0, "msg": "Success", "data": { "dispute_id": 4 } }
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.cournot.ai/api-reference/partner-public-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
