Skip to content

Catalog refresh: email.find narrows to email + status, two new contact SKUs - #29

Merged
kev1n merged 2 commits into
mainfrom
sync-email-find-lane-swap
Aug 30, 2026
Merged

Catalog refresh: email.find narrows to email + status, two new contact SKUs#29
kev1n merged 2 commits into
mainfrom
sync-email-find-lane-swap

Conversation

@kev1n

@kev1n kev1n commented Aug 30, 2026

Copy link
Copy Markdown
Member

Regenerated against the live gateway after anyapi#886. regen.yml classified this blocked because it carries removals, so automation correctly refused to version, commit, or tag it. This is that review.

Why the removals

email.find ran on one Apify actor that generated a likely address pattern, checked it against a catch-all domain, and reported "status": "found". Measured against 37 people whose real address came from a public git commit: 40.5% exact, 37.8% confidently wrong. It is now three independent finders in a cost-sorted waterfall, and a lookup that finds nothing is free.

Four fields go with it, all previously optional:

field why it is gone
isDeliverable true on every hit, including all 14 wrong ones
firstName the request echoed back
lastName the request echoed back
domain the request echoed back, and the half of email after the @

EmailFindItem keeps its index signature ([extra: string]: unknown / the Python equivalent), so a consumer still reading one of those compiles against unknown rather than a missing key. Price drops from $0.0231 per request plus $0 per result to $0.0154 per request.

Also in this refresh

Already live on the gateway and blocked behind the same gate since earlier today, so they ride along:

  • new SKU instagram.profile_contact
  • new SKU tiktok.profile_contact
  • output.comments[].score optional field added (reddit)
  • output.externalUrl optional field added (twitter)

Classifier output

## Removals (4)
- output.items[].domain field removed
- output.items[].firstName field removed
- output.items[].isDeliverable field removed
- output.items[].lastName field removed

## Added (4)
- new SKU instagram.profile_contact
- output.comments[].score optional field added
- output.externalUrl optional field added
- new SKU tiktok.profile_contact

## Changed (6)
- example updated
- pricing documentation updated
- output.items[].email description updated
- output.items[].status description updated
- output must-populate fields changed
- pricing documentation updated

Gate

  • pnpm run generate:check proved the committed baseline byte-identical before refreshing, and passes again after.
  • @anyapi/generator check: 158 tests pass.
  • TypeScript package check: 467 tests pass, tsup builds, consumer-typecheck OK.
  • Python: pyright reports 5 errors and pytest 18 failures on the untouched baseline as well - identical counts before and after this diff, so no regression here. This refresh adds 2 passing fixture-sweep tests (474 -> 476). Repo CI is the authority on that leg and is green on main.

🤖 Generated with Claude Code

kev1n and others added 2 commits August 30, 2026 15:51
…t SKUs

Regenerated against the live gateway after anyapi#886. The classifier blocks
this on automation because it carries removals, so it lands as a reviewed PR
rather than an auto-tagged release.

email.find swapped from one Apify actor that generated address patterns and
reported them as found (40.5% exact, 37.8% confidently wrong on a 37-person
measured set) to three independent finders in a cost-sorted waterfall. Four
output fields go with it:

  - isDeliverable  was true on every hit, including all 14 wrong ones
  - firstName      the request echoed back
  - lastName       the request echoed back
  - domain         the request echoed back, and the half of email after the @

The item record keeps its index signature, so a consumer reading one of those
still compiles against `unknown` rather than a missing key. Price drops from
$0.0231 per request to $0.0154, and a lookup that finds nothing is now free.

Also picked up from earlier gateway deploys, already live and previously
blocked behind the same gate: instagram.profile_contact, tiktok.profile_contact,
reddit comment score, and twitter externalUrl.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Minor rather than patch: email.find drops four optional output fields, which
narrows both generated result types. Removals are what made regen.yml block
this, so the level is a reviewed decision rather than an automated one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@kev1n
kev1n merged commit a58dfd2 into main Aug 30, 2026
4 checks passed
@kev1n
kev1n deleted the sync-email-find-lane-swap branch August 30, 2026 22:55
kev1n added a commit that referenced this pull request Sep 6, 2026
Accepts the blocked classification that has stopped every regen run since
2026-09-01T06:55Z. All eleven surface changes trace to a deliberate merged
AnyAPI change, so the fail-closed gate did its job and this is the review it
was waiting for. Minor bump, following the v0.34.0 precedent for a reviewed
narrowing (#29).

Breaking, in the order a customer will hit them:

  twitter.search      input.lang is gone. X honours "lang:" inside the query,
                      and declaring lang collapsed the SKU to one apify lane at
                      9x the price, so it was retired upstream (anyapi#940). Put
                      it in the query: query: "coffee lang:en". The gateway
                      still folds a sent lang into the query, so an untyped
                      caller keeps working; the SDK type no longer offers it.

  youtube.search_hashtag
                      input.type no longer accepts "shorts", only "all". No
                      source we buy returns a hashtag Shorts row with the
                      channel and publish time this endpoint requires, so the
                      filter was unpublished (anyapi#961).

  youtube.search_shorts
                      new SKU, and the replacement for the Shorts rows above:
                      client.youtube.searchShorts({ query }) /
                      client.youtube.search_shorts(query=...), cursor-paginated,
                      $0.002 per request (anyapi#965).

  company_enrichment.crustdata_v3
                      output name is now optional. A single null title aborted
                      the whole transform and threw away every good row beside
                      it (anyapi#1044).

  youtube.channel_shorts
                      output.shorts[].title is now optional, same reason
                      (anyapi#1023).

  tiktok.video        input.url is now optional because input.id was added: the
                      SKU accepts either (anyapi#1030). Existing url callers are
                      unaffected. The IR carries no anyOf, so both read as
                      optional in the emitted types; send one.

  tiktok.video_transcript_full
                      output.segments[].words[].confidence lost its 0..1 bounds.
                      On audio the recognizer could not align, it reports a
                      negative log-scale score, and the old bound rejected real
                      responses (anyapi#1023). Read the sign before treating the
                      number as a probability.

  yelp.search         input.limit now documents its default of 20, which is what
                      the gateway already applied (anyapi#1003).

Also in this refresh: threads.search gains optional startDate and endDate
(anyapi#940), and eleven SKUs reprice, most of them down - maps.reviews
$0.0441 -> $0.0035, yelp.search $0.0605 -> $0.0035, perplexity.search
$0.0111 -> $0.0036, youtube.video_transcript_full $0.00308 -> $0.001.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant