Skip to content

Migrating from Perigon ​

Replace /v1/all with /v1/news/everything. Most parameters have a direct counterpart, which is exactly why the three that differ silently are the ones to fix first: paging is 0-indexed on Perigon and 1-indexed here, unquoted adjacent terms mean OR on Perigon and AND here, and the two sentiment models are not the same measurement.

Why teams switch ​

PerigonAPITube
Articles per request100250
SentimentThree probabilities per articleSigned score for title, body, overall, and per entity
Category taxonomy15 fixed namesIPTC MediaTopics — thousands of codes, plus topics and industries
Publisher metadataSource name and domainDomain, country, political bias, Open Page Rank
Article textFull contentFull body and body_html, plus an extractive summary

Your first request ​

bash
# Perigon — page 0 is the first page
curl "https://api.goperigon.com/v1/all?q=tesla&language=en&page=0&size=100" \
  -H "x-api-key: YOUR_KEY"
bash
# APITube — page 1 is the first page
curl "https://api.apitube.io/v1/news/everything?title=tesla&language.code=en&page=1&per_page=100" \
  -H "X-API-Key: YOUR_API_KEY"

The three traps ​

1. Paging is off by one, and APITube does not error. Perigon pages start at 0; APITube pages start at 1 and treat page=0 as page=1. Forward the number unchanged and your first two pages return identical articles with a 200 — verified: page=0 and page=1 return the same three ids, page=2 is the first that differs. Always send perigon_page + 1.

2. The default operator is inverted. Perigon reads q=Elon Musk as Elon OR Musk; APITube reads title=Elon Musk as Elon AND Musk. On the same corpus that is 33 123 articles versus 20 409 — a 38% drop with no error. Translate to query=title:(Elon OR Musk). Quoted phrases ("Elon Musk") mean the same thing on both and port unchanged.

3. Sentiment does not convert exactly. Perigon returns {positive, negative, neutral} summing to 1. APITube returns a signed score per axis. Use score ≈ positive − negative — so positiveSentimentFrom=0.6 becomes sentiment.overall.score.min=0.2 — then re-tune against real results. neutralSentimentFrom and neutralSentimentTo have no equivalent at all.

Parameter mapping ​

PerigonAPITubeNote
qtitle or queryHeadlines only, and the default operator inverts — see above
titletitleLossless
content, desc, url—No body, description or URL search
categorycategory.id13 of 15 names map to IPTC codes, max 3
excludeCategoryignore.category.id
topictopic.idDifferent taxonomies — verify each value
sourcesource.domainMax 3, exact domain
excludeSourceignore.source.domain
sourceCountrysource.country.code
companyNameorganization.nameStrip legal suffixes — Apple Inc returns 400
personNameperson.nameResolves against an index, not free text
companyDomain—Different meaning — the company's site, not the publisher
companyId, personWikidataId—APITube entity ids are its own
bylineauthor.nameReal journalist names only; desk names return 400
languagelanguage.codeNo ru, no uk
from / topublished_at.start / .end
addDateFrom, refreshDateFrom—Publication date only
positiveSentimentFrom / Tosentiment.overall.score.min / .maxApproximate
negativeSentimentFrom / Tosentiment.overall.score.max / .minApproximate, sign inverts
neutralSentimentFrom / To—No neutral axis
showReprints=falseis_duplicate=0Reprint grouping is lost
medium=Videohas_video=1"Has a video" ≠ "is a video"
lat / lon / maxDistance/v1/news/local lat / lng / radiusA different endpoint
pagepage+1
sizeper_page250 max; 10 on Free, 50 on Starter, 200 on Basic (400 ER0171 above)
sortBy=datesort.by=published_at
sortBy=relevance—Returns 500 with a search term; use sort.by=source.rank.opr

The full table of every Articles parameter is in the migration kit.

What does not carry over ​

Body-text search. content=, desc= and url= have no equivalent, and APITube ignores unknown parameters silently — forwarding them returns the whole index with a 200. Search headlines and filter the returned body locally.

Wildcards. q=immuni* fails the same way: title=immuni* is accepted and returns the entire index. Expand into query=title:(immunity OR immunization OR immunology).

Relevance boosting. ^2 has no equivalent. Sent verbatim it becomes a literal search term.

Google Content Categories. taxonomy=/Finance/Banking and prefixTaxonomy use a hierarchy with no mechanical mapping to IPTC. Pick an IPTC code by hand.

Clustering endpoints. /v1/stories/all has no counterpart — every article carries story.id for client-side grouping, but there is no cluster endpoint and no clusterId filter. /v1/vector/news/all has none either: APITube has no embeddings. /v1/summarize is largely covered by the summary array already on every article.

Russian and Ukrainian. language.code=ru and uk return 400 ER0237. There is no substitute.

What you gain ​

250 articles per request instead of 100 (10 on Free, 50 on Starter, 200 on Basic), sentiment on the headline and the body separately plus a score towards each extracted entity, IPTC MediaTopics alongside topics and industries, publisher political bias and Open Page Rank, readability scores, and export to eight formats.

Next steps ​