Developer Documentation

Technology Signals

A signal is one technology appearing on, or disappearing from, one website. This page covers how those changes are detected, what reaches your inbox, and how to read the same data over HTTP.

Nightly sweep
JSON over HTTPS
6 endpoints
Base URL
https://api.ful.io

Introduction

Ful.io holds a record of the technologies each website runs. Technology Signals is what happens when that record changes: the change itself is stored as a dated event, pushed to the people watching that site, and made readable over HTTP.

Watching is done from the Technology Signals page or your watchlist. For single-site lookups and bulk reports, see the developer API.

What is a signal

One signal names one website, one technology and one date, with an event of added or removed. That is the whole unit, which is what makes signals countable, comparable and safe to put on a timeline.

{
  "domain": "example.com",
  "event": "added",
  "date": "2026-10-27",
  "technology": {
    "name": "Klaviyo",
    "slug": "Klaviyo",
    "tech_icon": "Klaviyo.svg",
    "category": "Email Marketing",
    "category_slug": "Email",
    "high_value": true
  }
}

high_value marks commercial tooling that people prospect on, such as payments, ecommerce and marketing platforms, as opposed to plumbing like frameworks and web standards.

The nightly sweep

1

You add a website

Watch a domain and it joins your watchlist. Alerts go to your account email address, and unwatching keeps the history.

2

We rescan it every night

Each watched domain is re-read and matched against the full fingerprint library. A domain we have not crawled before goes through a live scan first and becomes signal-eligible from the next run.

3

Only the differences are kept

The new reading is compared with the stack already on file. A technology that was there yesterday and is there today produces nothing. An appearance or a disappearance becomes a signal.

Recording rules

RuleWhat it means
Baseline is not a burstThe first successful scan of a site establishes what it runs. That is recorded as its stack, not reported as dozens of new signals.
One per tech per dayIf a site is scanned more than once in a day, a change is still recorded once. The same add or drop never appears twice.
Quiet night, no mailDigests are only built when something actually changed on a site you watch.
Flips onlyEvents come from a technology going live or going away. A technology present in both readings is not an event.

The digest email

One email per night covering every site you watch, rather than one message per change. Sites are grouped, each with the technologies it picked up and the ones it dropped, and each links to its full timeline. The subject line carries the counts.

Subject: Your watchlist: 3 added and 1 dropped across 2 domains - Technology Signals

Hi there, here's what changed on your watchlist:

getmodern.co (https://ful.io/technology-signals/getmodern.co)
  + Klaviyo (Email Marketing)
  + Segment (Customer Data Platform)

finledger.io (https://ful.io/technology-signals/finledger.io)
  + Stripe (Payment Processors)
  - Braintree (Payment Processors)

Where signals appear

SurfaceWhat it shows
Your watchlistEverything you watch in one place, with the latest change per site.
Site timelineEvery recorded add and drop for a single website, newest first.
Technology pagesRecently added and recently removed lists for the technology itself.
The live feedA rolling sample of recent signals across the index.

Endpoints

All endpoints are served from https://api.ful.io and return JSON. The feed and the type-ahead are open. The per-domain read is open but returns a shortened stack unless you are signed in, and the three watchlist endpoints act on your own account and require a session.

EndpointAuthPurpose
GET /signals/feedNo authRecent signals across the index.
GET /signals/domainPartialSignal history and stat tiles for one website. The full stack needs a signed-in session.
GET /signals/suggestNo authDomain type-ahead for the lookup box.
POST /signals/watchSigned inStart watching a domain.
POST /signals/unwatchSigned inStop watching a domain. History is kept.
GET /signals/watchlistSigned inEvery domain you watch, active first.

Recent signals

No auth
GET /signals/feed

The newest signals across the whole index, capped at two rows per domain so one freshly rescanned site cannot flood the window. The window is the last 7 days, widened to 30 when that is thin.

Query parameters

ParameterTypeDescription
limitintegerRows to return. Defaults to 50, capped at 200.
curatedflagReturn a cached sample of high-value changes over 30 days instead of the raw feed.

Example

curl "https://api.ful.io/signals/feed?limit=10"

Responses carry window_days and an events array of signal objects.

One website's history

Fuller when signed in
GET /signals/domain

Signal history and summary tiles for a single site. When a domain has no recorded events yet, the response carries a baseline array with the stack currently on file instead.

That baseline is the whole live stack, so signed-out callers receive the highest-value rows only, capped at eight, alongside baseline_total and baseline_truncated. Sign in and the full list comes back, with your watch state attached.

Query parameters

ParameterTypeDescription
urlstringRequired. The domain to read, with or without scheme or www.
limitintegerEvents to return. Defaults to 100, capped at 500.
offsetintegerSkip this many events, for paging.

Example

curl "https://api.ful.io/signals/domain?url=example.com&limit=20"

Response fields

FieldDescription
domainThe cleaned domain the response is for.
date_last_checkedWhen the site was last read.
statssignals_total, last_change, technologies_live, added_90d, removed_90d.
eventsSignal objects, newest first.
baselinePresent only when the domain has no events yet. Shortened for signed-out callers.
baseline_totalSigned-out only: how many technologies the full stack holds.
baseline_truncatedSigned-out only: true when the list above was shortened.
watchingPresent for a signed-in caller: whether you watch this domain.

Watchlist

Signed in
POST /signals/watch

Adds a domain to your watchlist. Watching an already-watched domain is treated as a no-op rather than an error, and unwatching keeps the row so history survives.

curl -X POST "https://api.ful.io/signals/watch" \
  -H "Content-Type: application/json" \
  -d '{"domain": "example.com"}'

Related

EndpointBodyReturns
POST /signals/unwatch{ "domain": "example.com" }404 when you were not watching it.
GET /signals/watchlistnonewatchlist array of domain, active, watching_since.

Errors

StatusMeaning
200Success.
201The watch was newly created.
400A required parameter is missing or malformed, such as a domain with no dot.
401The endpoint needs a signed-in session.
502 / 504The upstream signal service failed or timed out.
404Unwatching a domain you were not watching.