# archivum

> Preferred location: /agents.md (this text is also served at /llms.txt).

> Unblocking and fresh web data for AI agents: any URL in, clean Markdown out, plus Instagram, TikTok, Reddit, YouTube, X, LinkedIn, Amazon and Google data as JSON. Also screenshots and PDFs of pages, YouTube transcripts, Google Maps reviews, job listings, Google News, Amazon reviews and web search with page content. Each call is paid in stablecoins: x402 on Base and Polygon (plus Solana on most routes) or MPP on Base. No API keys, accounts or subscriptions. A scrape that fails is never charged; otherwise you pay a small fixed per-call fee plus the results you get.

## When to use this service

- Use it when an agent needs structured public web data.
- Pick the endpoint matching the source and data type, read its request shape below, send a JSON POST; `/openapi.json` is the contract.
- Not for private or login-protected content, browsing without a data task, or workloads needing a coverage commitment; sources are best-effort and failed calls are not charged.

## How to call it

- POST a small JSON body to an endpoint below. Without payment you get HTTP 402 with the price.
- x402: the 402 carries a `PAYMENT-REQUIRED` header. Sign it (`exact` scheme) and retry the same request with `PAYMENT-SIGNATURE`.
- MPP: the 402 carries `WWW-Authenticate: Payment`. Sign it and retry with `Authorization: Payment ...`.
- Every endpoint is also served under `/mpp/<name>`; either path accepts either protocol.
- MPP is Base only. Solana is taken on every route except twitter, youtube-transcript, web-search, x-replies, meta-ads, domain-contacts, maps-contacts, email-verify, instagram-profile, instagram-reels, linkedin-post-search, facebook-group-posts, linkedin-company-search and linkedin-comments: pay those on Base or Polygon (their 402 has no Solana offer).
- The 402 quotes the price for the `limit` you ask for: a fixed per-call fee plus a per-result price for each result. Endpoints with no `limit` field return one result.
- You sign that quote (x402 `exact` and MPP `charge` are fixed-amount). Missing results are refunded on-chain to the paying address within minutes (refunds too small to send are skipped). If the scrape finds nothing, nothing is charged and nothing is settled, on every endpoint. If the scrape fails, nothing is settled or charged.
- Response headers `X-Archivum-Results-Requested`, `X-Archivum-Results-Delivered` and `X-Archivum-Refund` (USDC base units, when a refund is due) report what happened. Ask for the `limit` you need.
- `limit` is a whole number. A value above an endpoint's maximum is lowered to the maximum, 0 or less means the default, and the 402 quotes the value used. Free-text fields are at most 500 characters and take no control characters; a body over 64 KiB is refused (413).
- A field an endpoint does not know is ignored on instagram, google-maps, tiktok, linkedin, youtube, twitter, reddit, amazon and google-search and refused on every other endpoint.
- Service errors are JSON `{"error": code, "message": text}`. An invalid body gets 400 `invalid_request` once paid; unpaid, it gets a 402 quote for 1 result with `X-Archivum-Invalid-Request: 1`, not worth signing: read `error`.
- instagram, youtube, linkedin and amazon records carry a `normalized` object with the same keys whichever upstream served it (null where it has no value), plus `source`; the upstream's own fields stay.
- reddit and tiktok return compact records by default (reddit: posts only, at most `limit`). Send `"raw": true` to get the provider's own records instead (more fields; for tiktok some links in them expire within hours).

## What to call

- Who is saying what (people & social): Posts, profiles and search results from the big social platforms. LinkedIn company details from page URLs. One LinkedIn profile with its verified email. Posts of a LinkedIn profile or company page. Replies under a post on X. Comments under a YouTube video. Comments under a TikTok video. Comments under an Instagram post. Facebook page details. Facebook page posts. Facebook post comments. Endpoints: `instagram-profile`, `instagram-reels`, `linkedin-post-search`, `facebook-group-posts`, `linkedin-company-search`, `linkedin-comments`, `instagram`, `tiktok`, `reddit`, `twitter`, `youtube`, `linkedin`, `linkedin-company`, `linkedin-profile-email`, `linkedin-posts`, `x-replies`, `youtube-comments`, `tiktok-comments`, `instagram-comments`, `facebook-page`, `facebook-posts`, `facebook-comments`.
- What customers say (places & reviews): Google Maps places by search and location. Reviews of a place. Reviews of an Amazon product. Reviews of an Android app on Google Play. Endpoints: `google-maps`, `google-maps-reviews`, `amazon-reviews`, `google-play-reviews`.
- What is out there right now (search & news): Google Search results for a query. Current news articles for a query, in the language and country edition you pick. Web search with each result's page read as Markdown, in one call. Endpoints: `google-search`, `google-news`, `web-search`.
- What is hiring, what is selling (jobs & products): LinkedIn job listings. Indeed job listings with salary and employer details. Amazon product search. eBay sold listings, for resale price comps. Public products of a Shopify store, with prices and variants. Public ads from the Meta ad library, for competitor research. Endpoints: `linkedin-jobs`, `indeed-jobs`, `amazon`, `ebay-sold`, `shopify-products`, `meta-ads`.
- Who to contact (contacts & leads): Contacts printed on a website. Verify an email address. Local businesses with contacts. Endpoints: `domain-contacts`, `email-verify`, `maps-contacts`.
- Everything else: any URL in, clean Markdown out (unblocking · any page): When there is no dedicated endpoint, unblocking reads the page for you: it renders JavaScript, copes with common bot protection, and returns Markdown, HTML or text with title, language and final URL. Need to see it instead? Capture a screenshot or PDF. Need what a video says? Get its transcript. Endpoints: `unblock`, `screenshot`, `youtube-transcript`.

## Limits and reliability

No uptime SLA. Quote first; data may be fetched before settlement, while resources provision after it. A request refused before settlement is not charged. Paid calls have an upstream timeout, usually 120 seconds (shorter on some routes); some routes also cap in-flight work per host. Undeliverable results are not charged and the missing portion of a short result is refunded. Free docs/discovery: 120 requests per client IP per minute; RateLimit headers report the budget, and 429 carries Retry-After. GET /health checks liveness only. 402 requires payment; 502 means delivery failed; 503 means unavailable. Follow Retry-After. Refunds follow the route's rules; support: /contact.

## Reference documents

- [API reference](/docs.md)
- [OpenAPI](/openapi.json)
## Try also portal

- Need a residential IP of your own? portal sells residential proxy traffic by the gigabyte and a raw fetch from a residential address, paid the same way. Site: https://portal.dalaran.sh, docs: https://portal.dalaran.sh/agents.md

## Unblocker

- POST `/x402/unblock` (or `/mpp/unblock`) with `{"url":"https://example.com/","format":"markdown"}`. `format` is `markdown` (the default), `html` or `text`. Only these two fields are accepted: headers, cookies and POSTs to the target are not supported.
- It gets through Cloudflare and other common bot protection and can render JavaScript-heavy pages (best effort: some sites still block it). Use it when your own fetch got a 403 or a challenge page, or to turn JavaScript-rendered pages into Markdown for RAG.
- The answer is a JSON array with one record: `url`, `finalUrl`, `statusCode`, `contentType`, `fetchedAt`, `title`, `description`, `language`, `canonicalUrl`, `jsonLd`, `format`, `content`, `contentBytes`, `truncated` (null where the page has no value). `content` is cut at 512 KiB (`truncated` is then true); a page with no Markdown comes back as `text`.
- A page that could not be fetched (blocked, an error status or empty) is never charged: the answer is `502 {"error":"not_fetched","reason":...,"charged":false}` and the payment is not settled. There is no `limit` field: one page per call, one flat quote.
- A call can take up to about 90 s: keep the connection open. Retrying with the same payment returns the stored result.
- Fetch only pages you may access; hosts are blocked on complaint (support@dalaran.sh).

## Screenshot

- POST `/x402/screenshot` (or `/mpp/screenshot`) with `{"url":"https://example.com/","format":"jpeg"}`. `format` is `jpeg` (the default), `png`, `webp` or `pdf`. Optional: `fullPage`, `device` (`desktop`, `desktop_hd`, `mobile` or `tablet`), `width`, `height`, `delayMs`, `colorScheme` (`light` or `dark`), `selector` (capture one element) and `waitForSelector`, both CSS selectors. Cookies, headers and proxies are refused.
- The answer is a JSON array with one record: `finalUrl`, `format`, `contentType`, `width`, `height`, `fullPage`, `bytes`, `capturedAt` and `imageBase64` (standard base64: decode it to get the file). A capture over 5 MiB is not delivered: ask for `jpeg` or leave `fullPage` off.
- It shows what a normal browser sees. It does not get past bot protection: a protected page may come back as its challenge screen. Use the unblock endpoint to read such a page's text.
- A page that cannot be captured, renders blank or gives an image over 5 MiB is never charged: the answer is `502 {"error":"not_fetched","reason":...,"charged":false}` and the payment is not settled. One capture per call, one flat quote, no `limit` field.
- A call can take up to about 60 s: keep the connection open. Retrying with the same payment returns the stored capture for 24 hours.

## YouTube transcript

- POST `/x402/youtube-transcript` (or `/mpp/youtube-transcript`) with `{"video":"dQw4w9WgXcQ","format":"json","lang":"en"}`. `video` is an 11-character video id or the URL of one video (watch, shorts, live, embed or youtu.be; not a channel, playlist or search). `format` is `json` (the default), `text`, `srt` or `vtt`. `lang` is `en` (the default), `any`, `de`, `es`, `fr`, `it`, `ja`, `ko`, `nl`, `pt` or `ru`.
- The answer is a JSON array with one record: `videoId`, `url`, `title`, `channelName`, `durationSeconds`, `publishedAt`, `language`, `availableLanguages`, `subtitleType`, `format`, `transcript` and `truncated`. With `json`, `transcript` is a list of `{start, duration, text}` (seconds); with `text`, `srt` or `vtt` it is one string. Only published subtitles are returned, there is no speech-to-text. `any` takes English when present, else the first track.
- A video with no subtitles in the language asked for (or an unavailable one) is never charged: `502 {"error":"not_fetched",...,"charged":false}`; try `lang` `any`. One video per call, one flat quote, no `limit` field.
- A call can take up to about 60 s: keep the connection open. Retrying with the same payment returns the stored first answer, in the format of the first call.

## Google Maps reviews

- POST `/x402/google-maps-reviews` (or `/mpp/google-maps-reviews`) with `{"place":"ChIJN1t_tDeuEmsRUsoyG83frY4","limit":10}`. `place` is a Google place_id (27 characters starting with `ChIJ` or `GhIJ`) or a Google Maps place URL (`https://www.google.com/maps/place/...` or `https://www.google.com/maps?cid=...`; a URL without a place id is best effort: otherwise not fetched, not charged). `limit` is 1 to 50 (default 10), `sort` is `newest` (the default), `relevant`, `highest` or `lowest`, `language` is a Google Maps language code.
- The answer is a JSON array with one record per review: `reviewId`, `stars`, `text`, `textTranslated`, `originalLanguage`, `translatedLanguage`, `publishedAt`, `publishedAgo`, `likesCount`, `ownerResponse` (`text`, `publishedAt` or null), `imageCount`, `origin`, `context`, `detailedRating` and `place` (`placeId`, `name`, `address`, `category`, `rating`, `reviewsCount`, `url`). Reviewer names, ids, profile links and photos are never returned.
- The quote is for the `limit` you ask for; missing reviews are refunded. A place with no reviews, or an unknown place, is never charged: `502 {"error":"not_fetched",...,"charged":false}`.

## Job listings

- POST `/x402/linkedin-jobs` (or `/mpp/linkedin-jobs`) with `{"query":"data engineer","location":"Prague","limit":10,"posted":"week"}`. `query` is a job title or keywords; `location`, `limit` (1 to 50, default 10) and `posted` (`24h`, `week` or `month`) are optional.
- The answer is a JSON array with one record per job: `id`, `url`, `title`, `companyName`, `companyUrl`, `location`, `postedDate`, `postedTimeAgo`, `contractType`, `experienceLevel`, `workType`, `sector`, `salary`, `applicants`, `applyType`, `applyUrl`, `description` and `descriptionTruncated` (null where a listing has no value). Recruiter names are never returned.
- POST `/x402/indeed-jobs` (or `/mpp/indeed-jobs`) with `{"query":"nurse","location":"Austin, TX","country":"us","limit":10,"posted":"week"}`. `query` is a job title or keywords; `location`, `country` (a two-letter code, default `us`), `limit` (1 to 50, default 10) and `posted` (`24h`, `3d`, `week` or `14d`) are optional.
- The answer is a JSON array with one record per job: `id`, `url`, `applyUrl`, `title`, `publishedAt`, `expired`, `language`, `location` (`city`, `state`, `country`, `postalCode`), `employer` (`name`, `url`, `website`, `industry`, `employeeCount`, `rating`, `ratingsCount`), `salary` (`min`, `max`, `unit`, `currency`, or null), `jobTypes`, `benefits`, `description` and `descriptionTruncated`.

## Company details from LinkedIn

- POST `/x402/linkedin-company` (or `/mpp/linkedin-company`) with `{"companies":["https://www.linkedin.com/company/stripe/"]}`. `companies` is 1 to 10 LinkedIn company page URLs (`https://www.linkedin.com/company/<name>/`). No search by name; priced per company.
- The answer is a JSON array with one record per company: `name`, `universalName`, `linkedinUrl`, `website`, `employeeCount`, `followerCount`, `foundedOn`, `tagline`, `description` (cut at 3,000 characters), `industries`, `specialities`, `headquarters`, `locations`, `companyType` and `pageVerified`. No people are returned.
- Companies not found are refunded; none found is never charged (`502 not_fetched`).

## LinkedIn profile with verified email

- POST `/x402/linkedin-profile-email` (or `/mpp/linkedin-profile-email`) with `{"url":"https://www.linkedin.com/in/jane-example/"}`. One profile URL per call. The answer is the profile with its verified work email (`emails`). No verified email is `502 not_fetched`, never charged.

## LinkedIn posts

- POST `/x402/linkedin-posts` (or `/mpp/linkedin-posts`) with `{"url":"https://www.linkedin.com/company/stripe/","limit":5}`. `url` is a profile or company page URL; `limit` is 1 to 20 (default 5). Priced per post; no posts is `502 not_fetched`, never charged.

## Shopify store products

- POST `/x402/shopify-products` (or `/mpp/shopify-products`) with `{"store":"example.com","limit":20}`. `store` is the store's domain (no port, path or IP address); `limit` is 1 to 250 (default 20).
- The answer is a JSON array with one record per product: `title`, `vendor`, `productType`, `url`, `handle`, `priceMin`, `priceMax`, `compareAtPrice`, `currency`, `onSale`, `available`, `variantCount`, `tags` (at most 20), `image`, `updatedAt`, `description` (cut at 500 characters) and `variants` (at most 10, each with `title`, `sku`, `price` and `available`).
- The quote is for the `limit` you ask for; missing products are refunded. A site that is not a Shopify store, or has no public products, is never charged: `502 {"error":"not_fetched",...,"charged":false}`.

## eBay sold listings

- POST `/x402/ebay-sold` (or `/mpp/ebay-sold`) with `{"keyword":"mechanical keyboard","site":"ebay.com","days":30,"limit":20}`. `keyword` is what was sold (2 to 100 characters). `site` is `ebay.com` (the default), `.co.uk`, `.de`, `.fr`, `.it`, `.es`, `.ca` or `.com.au`; `days` is 1 to 90 (default 30); `condition` is `any` (default), `new` or `used`; `limit` is 1 to 100 (default 20).
- The answer is a JSON array with one record per sold listing: `title`, `soldPrice`, `soldCurrency`, `shippingPrice`, `totalPrice`, `endedAt`, `condition`, `listingType`, `bidCount`, `sellerFeedbackPercent`, `url` and `itemId`. Seller names and thumbnails are never returned.
- Fewer listings than asked are refunded; an empty search is never charged (`502 not_fetched`, retry once).

## Meta ad library

- POST `/x402/meta-ads` (or `/mpp/meta-ads`) with `{"keyword":"running shoes","country":"US","limit":20}`. Give `keyword` or `page` (an advertiser's page name or numeric page id), not both. `country` is a two-letter code or `ALL` (default `US`); `active` is `true` (default, running now) or `false` (all ads); `limit` is 1 to 100 (default 20).
- The answer is a JSON array with one record per ad, each ad once: `adId`, `pageName`, `pageId`, `startDate`, `endDate`, `active`, `platforms`, `text` (cut at 5,000 characters), `title`, `cta`, `linkUrl`, `displayFormat` and `imageUrls` (at most 5). `spend` and `reach` appear only where Meta publishes them.
- Fewer ads than asked are refunded; no ads is never charged (`502 not_fetched`).

## Google News

- POST `/x402/google-news` (or `/mpp/google-news`) with `{"query":"openai","limit":10}`. `query` is a keyword or phrase; `limit` (1 to 30, default 10), `language` (two letters, default `en`) and `country` (two letters, default `US`) are optional.
- The answer is a JSON array with one record per article: `title`, `url`, `source`, `publishedAt` and `description`. `url` is the article's Google News link, which opens the publisher's page; the article's text is not included.

## Amazon reviews

- POST `/x402/amazon-reviews` (or `/mpp/amazon-reviews`) with `{"product":"B079JLY5M5","limit":10}`. `product` is an ASIN or an Amazon product URL (a URL sets the marketplace). `limit` is 1 to 50 (default 10), `sort` is `recent` (the default) or `helpful`, `stars` is `all` (the default), `5` to `1`, `positive` or `critical`, `country` is `us` (the default), `uk`, `de`, `fr`, `it`, `es`, `ca` or `jp`.
- The answer is a JSON array with one record per review: `asin`, `rating`, `title`, `text`, `date`, `country`, `verifiedPurchase`, `vine`, `helpfulCount` and `imageCount`. Reviewer names and photos are never returned.
- The quote is for the `limit` you ask for; missing reviews are refunded. A product with no reviews, or an unknown one, is never charged: `502 {"error":"not_fetched",...,"charged":false}`. A call can take up to about 15 s.

## Google Play reviews

- POST `/x402/google-play-reviews` (or `/mpp/google-play-reviews`) with `{"app":"com.spotify.music","limit":20}`. `app` is a package name or a Play app URL. `limit` is 1 to 200 (default 20), `sort` is `newest` (the default), `relevant` or `rating`, `rating` filters by stars (1 to 5).
- The answer is a JSON array with one record per review: `reviewId`, `rating`, `date`, `text`, `appVersion`, `language` and `helpfulCounts`. No reviewer names or photos.
- Fewer reviews than asked are refunded; an unknown app, or none found, is never charged (`502 not_fetched`).

## Replies to a post on X

- POST `/x402/x-replies` (or `/mpp/x-replies`) with `{"url":"https://x.com/NASA/status/1234567890","limit":10}`. `url` is a post on x.com or twitter.com; `limit` is 1 to 50 (default 10).
- The answer is a JSON array with one record per reply: `id`, `url`, `text` (cut at 4,000 characters, with `textTruncated`), `createdAt`, `lang`, `likeCount`, `replyCount`, `repostCount`, `quoteCount`, `viewCount`, `inReplyToId` and `author` (`username`, `name`, `verified`). The post itself is not in the array. Fewer replies than asked for refunds the missing ones. A call takes about 20 to 50 s.

## Comments under a video or post

- POST `/x402/youtube-comments` (or `/mpp/youtube-comments`) with `{"url":"https://www.youtube.com/watch?v=dQw4w9WgXcQ","limit":20,"sort":"top"}`. `url` is a YouTube video; `limit` is 1 to 100 (default 20); `sort` is `top` (the default) or `newest`.
- POST `/x402/tiktok-comments` (or `/mpp/tiktok-comments`) with `{"url":"https://www.tiktok.com/@nasa/video/7665075736742530317","limit":20}`. `url` is a TikTok video; `limit` is 1 to 100 (default 20).
- POST `/x402/instagram-comments` (or `/mpp/instagram-comments`) with `{"url":"https://www.instagram.com/p/DdG4RIxIPyf/","limit":20}`. `url` is an Instagram post or reel; `limit` is 1 to 100 (default 20).
- The answer is a JSON array with one record per comment: `id`, `text` (cut at 2,000 characters, with `textTruncated`), `postedAt`, `likeCount`, `replyCount`, `isReply`, `byOwner`, `ownerLiked` and `pinned` (null where the platform does not say). The commenter's name, handle and photo are never returned. Nothing found: `502 not_fetched`, not charged. Fewer comments than asked refunds the rest. A call takes up to a minute.

## Facebook and contacts

- Facebook (`facebook-page`, `facebook-posts`, `facebook-comments`): public pages only, no profiles or groups. `url` is a page URL such as `https://www.facebook.com/nasa/`; for comments, a post, video or reel URL. `limit` is 1 to 20 posts or 1 to 100 comments. A page has `name`, `followers`, `website` and, when listed, `email`, `phone`, `address`; a post has `postedAt`, `text` and reaction, comment, share and view counts; comments carry no commenter names.
- `domain-contacts` takes 1 to 5 sites in `urls` and returns, per site, the `emails`, `phones`, `socials` and `contactPage` printed on its pages (nothing is guessed). A site with nothing found has `found` false and is not charged.
- `maps-contacts` takes `query`, `location` and `limit` (1 to 8; up to about 90 s) and returns Google Maps places with the `emails`, `phones` and `socials` of their websites.
- `email-verify` takes 1 to 20 addresses in `emails` and returns `status`, `score`, `catchAll`, `disposable`, `roleBased` and `mailboxExists` (null when the server will not say); catch-all and strict servers stay `risky` or `unknown`.

## Web search with page content

- POST `/x402/web-search` (or `/mpp/web-search`) with `{"query":"lithium prices","limit":3}`. `query` is search keywords (not a URL; `site:` and quoted phrases work); `limit` is 1 to 5 (default 3).
- The answer is a JSON array with one record per page that was read: `url`, `title`, `description`, `language`, `content` (the page as Markdown, cut at 20,000 characters) and `contentTruncated`. A result whose page could not be fetched is dropped and its price refunded;
- A call takes about 20 to 30 s.

## Social research

- `instagram-profile`: One public account by `username`: biography, website and account statistics.
- `instagram-reels`: `target` is an account or reel URL. Metadata and engagement; a direct reel returns one record.
- `linkedin-post-search`: `query` with optional `author_url`, `posted` and `sort`: matching posts and engagement.
- `facebook-group-posts`: A public group `url`: posts and counts, without member profiles or nested comments.
- `linkedin-company-search`: `query` with optional `location`, `industry` and `size`: company search summaries, not full enrichment.
- `linkedin-comments`: One post `url`: top-level comments and engagement, without commenter identities or replies.
Lists default to 5 results and cap at 20; profiles return one. Optional add-ons are off. OpenAPI has the full schemas.

## MCP

- The same routes are also an MCP server (streamable HTTP, stateless, latest and earlier protocol versions): one tool per route, paid with x402 inside the tool call. Endpoint: `https://archivum.dalaran.sh/mcp` (POST only, no session). `tools/list` shows the tools; call a tool without a payment to get the quote in the result, sign it, and call the tool again with the signed payment in `_meta["x402/payment"]`.

## Endpoints

- POST /x402/unblock: `{"format":"markdown","url":"https://example.com/"}`
- POST /x402/instagram: `{"limit":5,"mode":"profile","query":"natgeo"}`
- POST /x402/google-maps: `{"limit":5,"location":"Prague","query":"coffee shops"}`
- POST /x402/tiktok: `{"limit":5,"mode":"profile","query":"nasa"}`
- POST /x402/linkedin: `{"query":"jane-example"}`
- POST /x402/youtube: `{"limit":5,"mode":"search","query":"web scraping tutorials"}`
- POST /x402/twitter: `{"limit":5,"mode":"profile","query":"elonmusk"}`
- POST /x402/reddit: `{"limit":5,"mode":"hashtag","query":"programming"}`
- POST /x402/amazon: `{"limit":5,"query":"wireless keyboard"}`
- POST /x402/google-search: `{"limit":5,"query":"best CRM tools"}`
- POST /x402/google-maps-reviews: `{"limit":10,"place":"ChIJN1t_tDeuEmsRUsoyG83frY4"}`
- POST /x402/youtube-transcript: `{"format":"json","lang":"en","video":"dQw4w9WgXcQ"}`
- POST /x402/screenshot: `{"format":"jpeg","url":"https://example.com/"}`
- POST /x402/linkedin-jobs: `{"limit":10,"location":"Prague","query":"data engineer"}`
- POST /x402/indeed-jobs: `{"country":"us","limit":10,"location":"Austin, TX","query":"nurse"}`
- POST /x402/shopify-products: `{"limit":20,"store":"example.com"}`
- POST /x402/google-news: `{"limit":10,"query":"openai"}`
- POST /x402/amazon-reviews: `{"limit":10,"product":"B079JLY5M5"}`
- POST /x402/google-play-reviews: `{"app":"com.spotify.music","limit":20}`
- POST /x402/linkedin-company: `{"companies":["https://www.linkedin.com/company/stripe/"]}`
- POST /x402/web-search: `{"limit":3,"query":"lithium prices"}`
- POST /x402/x-replies: `{"limit":10,"url":"https://x.com/NASA/status/2106751099063484493"}`
- POST /x402/youtube-comments: `{"limit":20,"url":"https://www.youtube.com/watch?v=dQw4w9WgXcQ"}`
- POST /x402/tiktok-comments: `{"limit":20,"url":"https://www.tiktok.com/@nasa/video/7665075736742530317"}`
- POST /x402/instagram-comments: `{"limit":20,"url":"https://www.instagram.com/p/DdG4RIxIPyf/"}`
- POST /x402/ebay-sold: `{"days":30,"keyword":"mechanical keyboard","limit":20,"site":"ebay.com"}`
- POST /x402/meta-ads: `{"country":"US","keyword":"running shoes","limit":20}`
- POST /x402/linkedin-profile-email: `{"url":"https://www.linkedin.com/in/jane-example/"}`
- POST /x402/linkedin-posts: `{"limit":5,"url":"https://www.linkedin.com/company/stripe/"}`
- POST /x402/facebook-page: `{"url":"https://www.facebook.com/nasa/"}`
- POST /x402/facebook-posts: `{"limit":5,"url":"https://www.facebook.com/nasa/"}`
- POST /x402/facebook-comments: `{"limit":20,"url":"https://www.facebook.com/nasa/posts/pfbid02Xk4Lm9Qa1"}`
- POST /x402/domain-contacts: `{"urls":["example.com"]}`
- POST /x402/maps-contacts: `{"limit":3,"location":"Prague, Czech Republic","query":"dentist"}`
- POST /x402/email-verify: `{"emails":["jane@example.com"]}`
- POST /x402/instagram-profile: `{"username":"nasa"}`
- POST /x402/instagram-reels: `{"limit":5,"target":"nasa"}`
- POST /x402/linkedin-post-search: `{"limit":5,"query":"web scraping","sort":"date"}`
- POST /x402/facebook-group-posts: `{"limit":5,"url":"https://www.facebook.com/groups/874728723021553/"}`
- POST /x402/linkedin-company-search: `{"limit":5,"query":"web scraping"}`
- POST /x402/linkedin-comments: `{"limit":5,"url":"https://www.linkedin.com/feed/update/urn:li:activity:7320867199693246465/"}`

## Machine-readable

- [OpenAPI 3.1](https://archivum.dalaran.sh/openapi.json): full request schemas and x-payment-info
- [x402 manifest](https://archivum.dalaran.sh/.well-known/x402)
- [Health](https://archivum.dalaran.sh/health)

## REST payment example

```sh
printf '%s' '{"format":"markdown","url":"https://example.com/"}' > request.json
URL='https://archivum.dalaran.sh/x402/unblock'
curl -i -H 'Content-Type: application/json' --data-binary @request.json "$URL"
# Wallet supplies PAYMENT_SIGNATURE after quote approval.
curl -i -H 'Content-Type: application/json' -H "PAYMENT-SIGNATURE: $PAYMENT_SIGNATURE" --data-binary @request.json "$URL"
```

Wallet limits apply; curl cannot sign. See /auth.md and https://dalaran.sh/agents.md.

## Feedback

- Free, no payment: POST `https://archivum.dalaran.sh/feedback` (or the MCP tool `feedback`) with `{"message":"what you want to tell us","kind":"bug|idea|praise|other","route":"optional route name","contact":"optional"}`. `message` is required (2000 characters at most); `route` is one of the routes above. Say what worked, what failed (route, request, response) and what you miss; send no secrets or private data. Limited to a few messages an hour per caller.
