---
title: "Place a licence order"
method: POST
path: "/enterprise-license"
tags: ["Buy"]
---

# Place a licence order

`POST /enterprise-license`

## Request

- Base URL: `https://api.opedd.com`
- URL: `https://api.opedd.com/enterprise-license`
- Auth: HTTP bearer

Place a licence order: one licence, one billing mode, up to 500 publishers. Each publisher becomes one Schedule, priced at what that publisher set. You must be signed in to your buyer account (`Authorization: Bearer <session>`); buyer API keys are refused here, so an agent can never place an order on its own. Your name, company and email come from your buyer account. 20 orders per hour.

**Which licence with which billing:**

| `licence` | Licence | `billing_mode` |
|---|---|---|
| `enterprise` | AI answers | `monthly` (articles published from the start of the order onwards) or `metered` (billed per request; at most 18 publishers) |
| `training` | AI training | `one_time` (articles published up to the order date; the publisher's back catalogue must be on Opedd) |
| `display` | Client display | `monthly`, with `quantity` = number of named clients (1 to 500) |
| `archive` | Full catalogue | `one_time` (articles published up to the order date, kept for answering questions; the publisher's back catalogue must be on Opedd) |

`include_archive: true` is accepted only with `enterprise` + `monthly`: it adds the Full catalogue for the same publishers to the order (complete access). The first invoice carries the one-off Full catalogue price; the monthly price repeats. The two licences stay separate: ending the monthly one doesn't end the Full catalogue.

`terms_version` is required: the version of the Buyer Master Agreement you accepted. Don't hard-code it: read the current value from `GET /api?action=trust_facts` (`agreements.enterprise_msa_current`) or `GET /legal-documents?kind=buyer_master_agreement`. Any other value is refused with `409 NOT_CURRENT_VERSION`: read the current agreement, accept it and send its identifier. `agreement_text_sha256` (optional) records the SHA-256 of the text you accepted.

The answer carries the access key (`ent_…`, shown once, working once paid), one line per publisher, the publishers left out and why, and how to pay: `hosted_invoice_url`, or `client_secret` for Stripe.js. After payment the access key is also emailed to you.

Also accepted: `scope: "filtered"` with `filter_rules`, for AI answers billed per request from every publisher matching your rules. The older body with `license_tier`, `scope: "custom"`/`"platform_wide"` and `billing_type` is refused with `400 LEGACY_ORDER_BODY_RETIRED`.

## Request body

- union
  - object
    - `licence` 'enterprise' | 'training' | 'display' | 'archive', required: `enterprise` AI answers, `training` AI training, `display` Client display, `archive` Full catalogue.
    - `billing_mode` 'monthly' | 'metered' | 'one_time', required: Must suit the licence: see the table above.
    - `publisher_ids` string[], required
    - `quantity` integer: `display` only: the number of named clients. Refused for other licences.
    - `include_archive` boolean: `enterprise` + `monthly` only: add the Full catalogue for the same publishers (complete access).
    - `terms_version` string, required: The current Buyer Master Agreement identifier, from `GET /api?action=trust_facts` (`data.agreements.enterprise_msa_current`). Anything else answers `409 NOT_CURRENT_VERSION`.
    - `agreement_text_sha256` string: Optional: SHA-256 of the agreement text you accepted.
  - object
    - `scope` 'filtered', required
    - `filter_rules` object, required: For `scope: "filtered"`. At least one rule is required.
      - `license_types` string[]: Required and not empty for a filtered order. Only `enterprise` (AI answers) is billed per request, so send `["enterprise"]`; an order whose types match no billable publisher is refused with 422. Older values (`ai_retrieval`, `ai_training`, `ai_inference`, `ai`, `human_per_article`) are still accepted and read as `enterprise` or `human`.
      - `categories` string[]: Up to 50, each up to 100 characters. Empty means any category.
      - `included_publisher_ids` string[]: Only these publishers (up to 5,000).
      - `excluded_publisher_ids` string[]: Never these publishers (up to 5,000).
      - `max_price_per_event` number: Leave out publishers priced above this, in US dollars per request.
      - `per_publisher_monthly_cap` number: US dollars per publisher per month.
      - `global_monthly_cap` number: US dollars per month in total.
    - `duration_months` integer
    - `buyer_webhook_url` string, uri: Optional: where to send notices about new articles; its signing secret is returned once.
    - `terms_version` string, required: The current Buyer Master Agreement identifier, from `GET /api?action=trust_facts` (`data.agreements.enterprise_msa_current`). Anything else answers `409 NOT_CURRENT_VERSION`.
    - `agreement_text_sha256` string

## Response `200`

Order created and waiting for payment. A licence order answers with the order shape; a filtered order with the filtered shape.

- object
  - `success` true, required
  - `data` union, required
    - EnterpriseLicenseOrderData: Answer to a licence order. The order is `pending` until paid. Pay at `hosted_invoice_url`, or confirm `client_secret` with Stripe.js (`confirmSetup` when `intent_type` is `setup`, `confirmPayment` when it is `payment`). Each publisher becomes one line, and one Schedule, at the price that publisher set; publishers that don't offer the licence with this billing are listed in `unavailable` and are not charged.
      - `order_id` string, uuid
      - `license_id` string, uuid: Same value as `order_id`.
      - `access_key` string: Your access key (`ent_…`) for this order. Shown here once and emailed after payment; it works only once the order is paid.
      - `status` 'pending'
      - `licence` 'enterprise' | 'training' | 'display' | 'archive'
      - `billing_mode` 'monthly' | 'metered' | 'one_time'
      - `total_amount_cents` integer: What the first invoice charges, in US cents. For a per-request order this is 0: requests are billed as they happen.
      - `lines` object[]
        - `publisher_id` string, uuid
        - `publisher_name` string
        - `unit` 'month' | 'request' | 'one_off' | 'client_month'
        - `unit_price_cents` integer
        - `quantity` integer
        - `amount_cents` integer: What this line charges per billing period; 0 for per-request lines.
        - `back_catalogue_date` string, date-time, nullable: AI training and Full catalogue: the licence covers articles published up to this moment. Null for other licences.
        - `terms_version` string: The version of the Standard Licence Terms this line is sold under.
        - `licence` string: The licence of this line. A complete-access order has two lines per publisher: `enterprise` and `archive`.
      - `unavailable` object[]: Publishers left out of the order, with the reason (for example `LICENSE_TYPE_DISABLED` or `BACK_CATALOGUE_NOT_READY`).
        - `publisher_id` string, uuid
        - `reason` string
      - `subscription_id` string, nullable
      - `hosted_invoice_url` string, uri, nullable: A Stripe page where the invoice can be paid.
      - `client_secret` string, nullable
      - `intent_type` 'setup' | 'payment'
      - `payment_intent_id` string, nullable
      - `setup_intent_id` string, nullable
      - `publishable_key` string: The Stripe publishable key to confirm the payment with.
    - EnterpriseLicensePostFilteredData: Answer to a `scope: "filtered"` order: AI answers billed per request, from every publisher matching your `filter_rules`. Confirm `client_secret` with Stripe.js: `confirmSetup` when `intent_type` is `setup` (nothing to pay now), `confirmPayment` when it is `payment`.
      - `scope` 'filtered', required: Always `filtered` for this answer.
      - `license_id` string, uuid, required
      - `access_key` string, required: Your access key, shown once. The feed lists articles only (`content_access: "search_only"`, `content_body: null`); read the content by asking questions with `POST /search`, billed per answer.
      - `status` 'pending' | 'active', required: `pending` until the payment method is confirmed.
      - `filter_rules` object: Your `filter_rules`, as stored. Change them later with `PATCH /buyer-account`.
        - `categories` string[]
        - `license_types` string[]
      - `valid_from` string, date-time, required
      - `valid_until` string, date-time, required
      - `duration_months` integer, required
      - `webhook_secret` string, nullable: Shown once, to check the signature of deliveries to `buyer_webhook_url`; null without one.
      - `client_secret` string, required: The Stripe secret to confirm, per `intent_type`.
      - `intent_type` 'setup' | 'payment', required: `setup`: nothing to pay now; confirm with `stripe.confirmSetup()`. `payment`: confirm with `stripe.confirmPayment()`.
      - `payment_intent_id` string, nullable
      - `setup_intent_id` string, nullable
      - `hosted_invoice_url` string, uri, nullable
      - `publishable_key` string, required: The Stripe publishable key to confirm the payment with.
      - `subscription_id` string, required: Stripe Subscription ID.
      - `billing_type` 'metered', required: Always `metered`: billed per request.
      - `total_amount_cents` integer: What the first invoice charges, in US cents; usually 0.

## Other responses

- `400`: Invalid order: a missing or unknown field, a billing mode that doesn't suit the licence, more than 500 publishers, a missing `terms_version`, or the older body (`LEGACY_ORDER_BODY_RETIRED`).
- `401`: Not signed in to a buyer account. Buyer API keys are refused here.
- `403`: A publisher has not verified its website or confirmed its rights (`PUBLISHER_NOT_VERIFIED`, `PUBLISHER_NOT_ATTESTED`)
- `404`: One or more publishers not found
- `409`: `terms_version` is not the current Buyer Master Agreement (`NOT_CURRENT_VERSION`), or you already have an open per-request order (`PAY_PER_REQUEST_ORDER_EXISTS`, `FILTERED_SUBSCRIPTION_EXISTS`).
- `422`: None of the publishers offer this licence with this billing (`NO_PRICED_PUBLISHERS`), a publisher has no articles ready, or a publisher can't be paid yet
- `429`: Too many orders (20 per hour)
- `502`: Stripe error; nothing was charged. Retry.
- `503`: Orders are switched off for now (`ORDERS_NOT_AVAILABLE`), or a check could not run. Retry later.

---

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