> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.respona.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.respona.com/_mcp/server.

# Orders & Placements

An **order** is a container for one or more **placements**. A placement is a single link-placement request - a target
URL, an anchor, a quality tier, and optional guidelines. `requested_url` and `quality_tier` are **required** on every
placement. Placements are always sub-resources of an order; there is no top-level placement endpoint.

## Resource shape

Every order and placement response includes the current `price` and `price_breakdown`, recomputed live. All monetary
amounts are integer **USD cents** (1 credit = 1 cent). Field-level detail is in the
**[API Reference](/api-reference)**; this is the overall shape:

```json
{
  "order_id": "123",
  "title": "Q3 link building",
  "status": "DRAFT",
  "placements": [
    {
      "placement_id": "456",
      "number": null,
      "status": "DRAFT",
      "requested_url": "https://example.com/post",
      "requested_anchor": "best widgets",
      "publisher_url": null,
      "quality_tier": "DR_40",
      "content_guidelines": "string or null",
      "domain_specifications": "string or null",
      "domain_rating": null,
      "domain_traffic": null,
      "approved_at": null,
      "rejected_count": 0,
      "rejection_limit": 3,
      "concern_status": null,
      "price": 28800,
      "price_breakdown": [
        { "code": "BASE_DR_40", "amount": 24000 },
        { "code": "CONTENT_GUIDELINES_20PCT", "amount": 4800 }
      ]
    }
  ],
  "price": 28800,
  "price_breakdown": [
    { "code": "PLACEMENTS_SUBTOTAL", "amount": 28800 }
  ],
  "created_at": "2026-06-26T10:15:30Z",
  "updated_at": "2026-06-26T10:15:30Z",
  "launched_at": null
}
```

`title` defaults to `"New order"` when omitted on creation. `number` - the human-facing sequential order
number - is assigned when the order is launched, so it is omitted from a draft order and appears once launched.

Order `status` is one of `DRAFT`, `LAUNCHED`, `IN_PROGRESS`, `COMPLETED`, `REJECTED`, `REFUNDED`. Placement
`status` is one of `DRAFT`, `ORDERED`, `PENDING_APPROVAL`, `REJECTED`, `IN_PROGRESS`, `APPROVED`, `LIVE`,
`REFUNDED`.

## Quality tiers

`quality_tier` is a string selecting the minimum domain-authority band for the placement:

| `quality_tier` | Tier      | Minimum authority |
| -------------- | --------- | ----------------- |
| `DR_20`        | Starter   | DR 20+            |
| `DR_30`        | Standard  | DR 30+            |
| `DR_40`        | Authority | DR 40+            |
| `DR_50`        | Power     | DR 50+            |
| `DR_60`        | Elite     | DR 60+            |

## Pricing modifiers

Two optional fields refine a placement and each add **+20%** to that placement's base price. They **stack** - supplying
both adds +40% over the base. Omit a field (or send `null`) to leave it disabled.

* **`content_guidelines`** - free-text editorial instructions for the placed content. Surfaces as a
  `CONTENT_GUIDELINES_20PCT` line in the breakdown.
* **`domain_specifications`** - free-text constraints on the hosting domain. Surfaces as a
  `DOMAIN_SPECIFICATIONS_20PCT` line.

The `price_breakdown` always itemizes the base band (`BASE_<tier>`) plus any active modifiers so the total is fully
explained. See [Credits & Billing](/guides/core-concepts/credits-billing) for how price maps to credits.

## Order state machine

```
DRAFT ──launch──▶ LAUNCHED ──▶ IN_PROGRESS ──▶ COMPLETED
                                     │
                                     ├──▶ REJECTED
                                     └──▶ REFUNDED
```

| Status        | Meaning                                                    |
| ------------- | ---------------------------------------------------------- |
| `DRAFT`       | Editable. Add/remove placements, or launch. No charge yet. |
| `LAUNCHED`    | Accepted and charged; work is starting.                    |
| `IN_PROGRESS` | Placements are being worked.                               |
| `COMPLETED`   | All placements reached a terminal state.                   |
| `REJECTED`    | The order could not be fulfilled.                          |
| `REFUNDED`    | Credits were returned per the refund policy.               |

Only `DRAFT` orders are mutable. Adding, removing, deleting, or re-launching a non-`DRAFT` order returns `409 Conflict`.

## Placement state machine

Placements progress independently after launch:

```
DRAFT ─▶ ORDERED ─▶ IN_PROGRESS ─▶ PENDING_APPROVAL ─▶ APPROVED ─▶ LIVE
                                                            │
                                                            ├─▶ REJECTED
                                                            └─▶ REFUNDED
```

Terminal states are `LIVE`, `REJECTED`, and `REFUNDED`. Everything else is transient - [poll](/guides/core-concepts/polling-for-status) until a
placement is terminal. A rejected or refunded placement returns credits per the [refund policy](/guides/core-concepts/credits-billing).

## Domain approval

When a placement reaches `PENDING_APPROVAL`, the Respona team has proposed a publisher domain and is waiting on you.
The proposal is surfaced on the placement:

| Field             | Meaning                                                                 |
| ----------------- | ----------------------------------------------------------------------- |
| `publisher_url`   | The proposed publisher URL.                                             |
| `domain_rating`   | Domain Rating (DR) of the proposed domain.                              |
| `domain_traffic`  | Monthly organic traffic of the proposed domain.                         |
| `rejected_count`  | How many proposed domains you have already rejected for this placement. |
| `rejection_limit` | Your rejection budget (default **3**).                                  |

[Poll](/guides/core-concepts/polling-for-status) the placement until its `status` is `PENDING_APPROVAL`, then
**approve** or **reject** the proposed domain. Both need the `orders:write` scope; a placement outside your workspace
returns `404`.

### Approve

```bash
curl -X POST https://api.respona.com/rest/api/v1/orders/123/placements/456/approve \
  -H "x-api-key: $RESPONA_API_KEY"
```

The placement moves to `APPROVED` and `approved_at` is stamped. The response is the recomputed placement. Approving a
placement that is not `PENDING_APPROVAL` returns `409 Conflict`.

### Reject

A `reason` is **required** and must be non-blank.

```bash
curl -X POST https://api.respona.com/rest/api/v1/orders/123/placements/456/reject \
  -H "x-api-key: $RESPONA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "The proposed domain is not relevant to our niche." }'
```

Rejecting sends the team back to propose a different domain and increments `rejected_count`. When `rejected_count`
reaches `rejection_limit`, the placement automatically transitions to `REFUNDED` and credits are returned per the
[refund policy](/guides/core-concepts/credits-billing). Rejecting a placement that is not `PENDING_APPROVAL` returns
`409 Conflict`.

### Auto-approve fallback

If you never act on a `PENDING_APPROVAL` placement, it auto-approves after **28 days**. Acting through the API is the
way to approve sooner or to reject a domain you do not want.

## Concerns

You can raise **one concern per placement** - a short message thread with the Respona team, with its own
`RAISED → IN_REVIEW → RESOLVED` status that overlays (never replaces) the placement's fulfillment status via
`concern_status`. Attachments are not supported over the API. See [Concerns](/guides/core-concepts/concerns) for the
full workflow.