---
title: "Import OPML"
method: POST
path: "/import_opml"
---

# Import OPML

`POST /import_opml`

## Request

- Base URL: `https://newsmind.app/api/v1`
- URL: `https://newsmind.app/api/v1/import_opml`
- Auth: OAuth 2 (authorization code, authorization URL `https://newsmind.app/oauth/authorize`, token URL `https://newsmind.app/oauth/token`, scopes: `mcp`)

Bulk-subscribe from an OPML 2.0 document. Queues entries and returns at once — nothing is subscribed yet. Already-subscribed, duplicate and over-limit entries are skipped. Poll get_import_status for pending/succeeded/failed counts; report counts, never a completion time.

## Request body

- object
  - `opml` string, required: The OPML 2.0 XML document as a string. Must contain <outline xmlUrl="…"> entries.
  - `folder` string: Optional override folder for every imported feed. If omitted, the OPML's own folder structure (parent <outline> titles) is preserved.

## Response `200`

Success

- object
  - `queued` integer: Entries accepted into the import queue. Nothing is subscribed yet — poll get_import_status.
  - `format_invalid` integer: Entries whose URL was unusable as written.
  - `skipped_already_subscribed` integer
  - `skipped_duplicate_in_opml` integer: The same feed appeared more than once in this document.
  - `skipped_already_queued` integer: Already pending from an earlier import.
  - `skipped_over_limit` integer: Beyond the plan's feed limit.
  - `total_in_opml` integer
  - `eta` string: Human-readable estimate of when the queue should drain. Advisory — report counts from get_import_status rather than this.
  - `message` string
  - `details` object[]
    - `url` string
    - `status` 'queued' | 'format_invalid' | 'skipped_already_subscribed' | 'skipped_duplicate_in_opml' | 'skipped_already_queued' | 'skipped_over_limit'
    - `reason` string

## Other responses

- `400`: Bad request
- `401`: Unauthorized
- `402`: Subscription required (trial expired or cancelled)
- `429`: Too many calls. Either the per-account rate limit ({error: "rate_limited", message}) or the account's in-flight work ({error: <sentence>, code: "busy"}). Wait Retry-After seconds.
- `500`: Server error on our side (error: internal_error). The team has been notified.
- `503`: Temporarily unable to answer. error: timeout (the request ran too long; narrow it), server_busy or tier_unavailable (retry after Retry-After seconds when sent).

---

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