Skip to content

Developer docs · REST API v1

Dermal Vectors Forecast API

Daily Dry Skin Index (DSI) forecasts for U.S. metro areas, ready for your own code, dashboards, automation tools and AI agents. Ask for a place by city location, state or metro code and get back a 7-day forecast in JSON or CSV. New to this? Start with the step-by-step guide.

Base URL
https://YOUR-DERMAL-VECTORS-SITE
Authentication
An organization API key in a header: Authorization: Bearer YOUR_KEY. A brand owner creates it on the Integrations page. The market list needs no key.
Formats
JSON (default) or CSV (format=csv)
Updates
A new forecast every day, normally ready by about 12:35 UTC
Coverage
371 U.S. metro areas in 50 states and DC, 7 days ahead
Limits
Monthly allowance per brand, plus a per-minute limit. No overage charges. Details
Spec
OpenAPI 3.1 (YAML)

Quick start

No codes needed. Ask for the metro nearest a location, like a weather API. Here is this week's Dry Skin Index for Boston (latitude 42.36, longitude −71.06):

curl -H "Authorization: Bearer $DV_API_KEY" \
  "https://YOUR-DERMAL-VECTORS-SITE/api/v1/products/daily_metro_dsi_forecast/latest?near=42.36,-71.06"

Keep your key in an environment variable, for example export DV_API_KEY="…", never in shared code. Each forecast call uses one read from your monthly allowance.

Products

ProductProduct IDStatusHow to call it
Daily Metro DSI Forecastdaily_metro_dsi_forecastAvailableGET /api/v1/products/daily_metro_dsi_forecast/latest · details
Dry-Skin Search Outlookdry_skin_search_outlookComingSame pattern once released; returns 503 until then
Humidifier Search Outlookhumidifier_search_outlookComingSame pattern once released; returns 503 until then

To check in code which products your brand can use right now, call GET /api/v1/products (one lookup, not a forecast read).

Daily Metro DSI Forecast

What it measures
Indoor drying stress on skin, on a 0–10 scale (higher = drier), from NOAA GFS temperature and humidity forecasts
Places
371 U.S. Census metro areas (CBSAs), not DMAs
Time
7 daily values per metro, starting on the issue date
Updated
Daily, about 12:35 UTC. Each day's forecast is an “issue” (like an edition) with a permanent ID, and is current for about 24 hours
Formats
JSON or CSV

Endpoints

CallWhat it returnsCounts as
GET /api/v1/products/daily_metro_dsi_forecast/latestToday's 7-day forecast for the places you choose (the newest “issue”)1 forecast read
GET /api/v1/products/daily_metro_dsi_forecast/issues/{issueId}A specific past forecast again, unchanged, using its ID (so a report can be re-checked with the same numbers)1 forecast read
GET /api/v1/marketsSupported metros: find codes by name, state or locationFree, no key

Choosing places

Use one of these per request. The response always lists the exact metro codes it used in markets.requested.

ParameterExampleWhich metros you get
nearnear=42.36,-71.06The single nearest supported metro to that latitude,longitude (like a weather API)
statestate=CTEvery supported metro in that state (metros that cross state lines count for each state)
marketsmarkets=14460,35620Exactly these CBSA codes, up to 100. Find codes
(none)/latestAll 371 metros

Examples

Every Connecticut metro, as JSON:

curl -H "Authorization: Bearer $DV_API_KEY" \
  "https://YOUR-DERMAL-VECTORS-SITE/api/v1/products/daily_metro_dsi_forecast/latest?state=CT"

Four Northeast metros by code:

curl -H "Authorization: Bearer $DV_API_KEY" \
  "https://YOUR-DERMAL-VECTORS-SITE/api/v1/products/daily_metro_dsi_forecast/latest?markets=14460,35620,37980,25540"

Other parameters

ParameterValuesMeaning
formatjson | csvJSON (default) or a CSV file download
viewdaily | summary | both7 daily rows per metro (default), one summary line per metro, or both
sortmean7 | excess | exposure65 | trendWith view=summary or both: highest first (trend: fastest rising first)
top1–400With view=summary or both: keep only the first N
issueIdin the pathOnly for /issues/{issueId}; copy it from product.issueId

What you get back

The response has two parts: information about the issue (which forecast this is, when it was made, where it came from) and rows: one row per metro per day. The arrows mark each part. This example is for near=42.36,-71.06 (Boston), shortened:

{
  "schemaVersion": "dv-product-response-v1",
  "product": {                                   ← which forecast issue this is
    "productId": "daily_metro_dsi_forecast",
    "issueId": "dsi-20261006T140100Z-3824fb7ca0b601ee",
    "issuedAt": "2026-10-06T14:01:00.000Z",
    "validFrom": "2026-10-06T00:00:00Z",
    "validUntil": "2026-10-07T14:01:00.000Z",
    "geography": "us_census_cbsa_metro",
    "coverage": { "expected": 371, "completed": 371 },
    "modelVersion": "residential-dsi-hierarchy-v1",
    "recipeVersion": null,
    "formats": ["json", "csv"]
  },
  "freshness": "current",
  "access": "full",
  "release": "customer_released",
  "geography": { "type": "us_census_cbsa_metro", "code": "5-digit CBSA",
                 "note": "U.S. Census metro areas, not DMAs." },
  "provenance": {                                ← where the numbers came from
    "runId": "signal-20261006T1401Z",
    "noaaCycle": "2026-10-06T00:00:00+00:00",
    "noaaModel": "gfs",
    "targetDates": ["2026-10-06", "2026-10-07", "…", "2026-10-12"],
    "catalogMetros": 384, "modeledMetros": 371,
    "manifestSha256": "3824fb7c…", "artifactSha256": "be261f7c…",
    "excludedCbsas": ["14100", "…"], "validationStatus": "shadow_verified"
  },
  "markets": { "requested": ["14460"], "returned": 1 },   ← the metros used
  "units": { "dsi": "Dry Skin Index (dimensionless, 0-10)", "leadDay": "1 = issue date",
             "forecastConfidence": "reduced from lead day 6", "coveredPopulation": "people" },
  "rows": [                                      ← the forecast: one row per metro per day
    { "cbsa": "14460", "metroName": "Boston-Cambridge-Newton, MA-NH", "date": "2026-10-06",
      "leadDay": 1, "forecastConfidence": "standard",
      "dsi": 5.915614, "dsiLow": 4.881779, "dsiHigh": 7.168575, "coveredPopulation": 4917438.333 },
    { "cbsa": "14460", "metroName": "Boston-Cambridge-Newton, MA-NH", "date": "2026-10-07",
      "leadDay": 2, "forecastConfidence": "standard",
      "dsi": 5.408925, "dsiLow": 4.482004, "dsiHigh": 6.527612, "coveredPopulation": 4917438.333 }
    … 5 more rows, one per day to 2026-10-12
  ]
}

Headers: X-DV-Issue-Id (same as product.issueId) and Cache-Control: private, no-store.

Full data dictionary, CSV headings and downloadable definitions

Data dictionary: rows

FieldMeaningUnit / valuesExample
cbsaU.S. Census metro code.5-digit text14460
metroNameOfficial metro name.textBoston-Cambridge-Newton, MA-NH
dateForecast date.YYYY-MM-DD2026-10-07
leadDayForecast day; 1 is the issue date.1–71
forecastConfidenceConfidence label; reduced from day 6.standard / reducedstandard
dsiModeled indoor drying stress on skin; higher means drier.index, 0–105.92
dsiLowLower end of the forecast range.index, 0–104.88
dsiHighUpper end of the forecast range.index, 0–107.17
coveredPopulationPopulation covered by the metro forecast.people4917438

Data dictionary: issue information

FieldMeaningUnit / valuesExample
product.issueIdPermanent ID of this forecast; the same ID always returns the same numbers. Cite it.textdsi-20261006T…
product.issuedAtWhen the issue was publishedUTC time2026-10-06T14:01Z
product.validFrom / validUntilWhen this issue counts as the current forecastUTC timeabout 24 hours
freshnesscurrent, or expired for an earlier issue you asked for by IDcurrent | expiredcurrent
markets.requested / returnedMetro codes used, and how many came backcodes / count["14460"] / 1
provenance.targetDatesThe 7 forecast datesdates2026-10-06 … 2026-10-12
provenance.noaaCycle / noaaModelThe NOAA weather run usedtime / namegfs
provenance.runId, …Sha256IDs for audits and reproducibilitytext—
unitsPlain-language units for the row fieldsobject—

CSV

With format=csv you get a file with one line per metro per day. Columns match the row fields in snake_case:

cbsa,metro_name,date,lead_day,forecast_confidence,dsi,dsi_low,dsi_high,covered_population
14460,"Boston-Cambridge-Newton, MA-NH",2026-10-06,1,standard,5.915614,4.881779,7.168575,4917438.333
14460,"Boston-Cambridge-Newton, MA-NH",2026-10-07,2,standard,5.408925,4.482004,6.527612,4917438.333
…

Summary measures (7-day)

Add view=summary to get one line per metro with the 7-day measures below, computed on our side from the same issue, instead of 7 daily rows you would have to add up yourself. It is smaller and faster to read for code and AI agents. Combine with sort and top to rank metros, for example the 10 driest in the country, in one read.

MeasureDefinitionUnit
mean7Average of the daily DSI valuesDSI, 0–10
peakHighest daily DSI and its date (earliest if tied)DSI and date
excessAbove4Sum over the days of (DSI − 4), counting only days above 4 (recipe cumulative-excess-v1)index-days above 4
exposure65plusexcessAbove4 × the metro's population aged 65+ (metro-wide, 2023 ACS 5-year, table B01001): how much above-4 dryness older adults are exposed to over the week65+ person-index-days
trendLeast-squares change in DSI per day over the week: rising (≥ +0.15/day, about +1 point a week), falling (≤ −0.15/day), otherwise steadyDSI per day + label

Examples

This week's summary for Boston:

curl -H "Authorization: Bearer $DV_API_KEY" \
  "https://YOUR-DERMAL-VECTORS-SITE/api/v1/products/daily_metro_dsi_forecast/latest?near=42.36,-71.06&view=summary"

The 10 driest metros in the country this week:

curl -H "Authorization: Bearer $DV_API_KEY" \
  "https://YOUR-DERMAL-VECTORS-SITE/api/v1/products/daily_metro_dsi_forecast/latest?view=summary&sort=mean7&top=10"

Texas metros with the highest 65+ exposure, as a spreadsheet:

curl -H "Authorization: Bearer $DV_API_KEY" -o texas-65plus-exposure.csv \
  "https://YOUR-DERMAL-VECTORS-SITE/api/v1/products/daily_metro_dsi_forecast/latest?state=TX&view=summary&sort=exposure65&top=5&format=csv"

Example response 200 OK real values, Sept 29 issue; shortened

{
  "schemaVersion": "dv-product-response-v1",
  "view": "summary",
  "summaryVersion": "dsi-summary-v1",
  "product": { "issueId": "dsi-20260929T191051Z-9d3005985574912e", "issuedAt": "2026-09-29T19:10:51Z", … },
  "freshness": "current",
  "markets": { "requested": ["14460"], "returned": 1 },
  "provenance": { "runId": "signal-delivery-20260929-1200", "targetDates": ["2026-09-29", "…", "2026-10-05"] },
  "units": { "mean7": "mean daily DSI, 0-10", "excessAbove4": "sum of max(DSI-4,0), index-days", … },
  "summaries": [
    { "cbsa": "14460", "metroName": "Boston-Cambridge-Newton, MA-NH", "days": 7,
      "firstDate": "2026-09-29", "lastDate": "2026-10-05",
      "mean7": 4.205,
      "peak": { "dsi": 4.595, "date": "2026-10-05" },
      "excessAbove4": 1.705,
      "population65plus": 818502,
      "exposure65plus": 1395836,
      "trend": { "slopePerDay": 0.107, "label": "steady" } }
  ]
}

With sort, each summary also has a rank. The summary CSV has one row per metro: rank,cbsa,metro_name,first_date,last_date,days,mean7,peak_dsi,peak_date,excess_above_4,population_65plus,exposure_65plus,trend_slope_per_day,trend. Full provenance (hashes, excluded metros) is in view=daily or view=both.

These are weather-derived summaries of the Dry Skin Index, not medical, sales or audience measures.

Find a market

Look up any supported metro and copy its code, or download the full list. No key is needed for either.

Download all 371 metros (CSV)

GET /api/v1/markets

The same list for your code. Public, cacheable, and not counted against your allowance.

ParameterExampleMeaning
qq=dallasPart of a metro name, or a code
statestate=TXMetros in a state (can be combined with q)
nearnear=42.36,-71.06Nearest metros first, with distanceKm (use on its own)
limitlimit=3Up to 400; default 5 with near, otherwise all
formatformat=csvJSON (default) or CSV
curl \
  "https://YOUR-DERMAL-VECTORS-SITE/api/v1/markets?near=42.36,-71.06&limit=2"
{
  "schemaVersion": "dv-markets-v1",
  "productId": "daily_metro_dsi_forecast",
  "geography": "us_census_cbsa_metro",
  "totalSupported": 371,
  "count": 2,
  "markets": [
    { "cbsa": "14460", "name": "Boston-Cambridge-Newton, MA-NH", "states": ["MA", "NH"],
      "latitude": 42.3739, "longitude": -71.141, "population": 4917661, "distanceKm": 7 },
    { "cbsa": "49340", "name": "Worcester, MA-CT", "states": ["MA", "CT"],
      "latitude": 42.2784, "longitude": -71.7038, "population": 861664, "distanceKm": 54 }
  ]
}

Recipes

This week for one city

curl -H "Authorization: Bearer $DV_API_KEY" \
  "https://YOUR-DERMAL-VECTORS-SITE/api/v1/products/daily_metro_dsi_forecast/latest?near=32.78,-96.80"

Which of several metros is driest this week

curl -H "Authorization: Bearer $DV_API_KEY" \
  "https://YOUR-DERMAL-VECTORS-SITE/api/v1/products/daily_metro_dsi_forecast/latest?markets=14460,35620,37980,25540&view=summary&sort=mean7"

The driest metros in the whole country (one read)

curl -H "Authorization: Bearer $DV_API_KEY" \
  "https://YOUR-DERMAL-VECTORS-SITE/api/v1/products/daily_metro_dsi_forecast/latest?view=summary&sort=mean7&top=10"

Where dryness is rising fastest

curl -H "Authorization: Bearer $DV_API_KEY" \
  "https://YOUR-DERMAL-VECTORS-SITE/api/v1/products/daily_metro_dsi_forecast/latest?view=summary&sort=trend&top=10"

Every metro in a state, as a spreadsheet

curl -H "Authorization: Bearer $DV_API_KEY" -o texas-dsi.csv \
  "https://YOUR-DERMAL-VECTORS-SITE/api/v1/products/daily_metro_dsi_forecast/latest?state=TX&format=csv"

Everything, as a spreadsheet

curl -H "Authorization: Bearer $DV_API_KEY" -o all-metros-dsi.csv \
  "https://YOUR-DERMAL-VECTORS-SITE/api/v1/products/daily_metro_dsi_forecast/latest?format=csv"

The same numbers again later

Each day's forecast is published as an issue, like a newspaper edition, with a permanent ID in product.issueId. /latest always returns the newest one. To get a specific past forecast again, unchanged (for example to re-check last week's report), put its ID in the address:

curl -H "Authorization: Bearer $DV_API_KEY" \
  "https://YOUR-DERMAL-VECTORS-SITE/api/v1/products/daily_metro_dsi_forecast/issues/dsi-20261006T140100Z-3824fb7ca0b601ee?markets=14460"

Errors

Errors use standard HTTP status codes and a JSON body with a stable code and a plain-language message that says when retrying won't help.

HTTP/1.1 422 Unprocessable Entity
{
  "error": {
    "code": "unsupported_market",
    "message": "Some requested markets are not supported CBSA metros in this issue.",
    "unsupportedMarkets": ["99999"]
  }
}
StatusCodeMeaning and what to do
400invalid_requestA parameter is malformed, more than one way of choosing places was used, or a key was sent in a URL or cookie. Fix the request.
400ambiguous_credentialsBoth a website session and a key were sent. Send only the key.
401invalid_api_keyMissing, unknown, revoked or expired key. Create a new key and update your code; retrying won't help.
403entitlement_requiredNo active trial or subscription. A brand owner subscribes in Billing.
403agent_access_not_enabledAPI access isn't enabled for this brand. Contact Dermal Vectors.
403read_only_latest_denied, issue_not_receivedAfter a subscription ends, only issues the brand already received can be read.
404unsupported_product, issue_not_foundUnknown product or issue ID.
409stale_issueToday's issue isn't published yet and the previous one has expired. Try again later.
422unsupported_marketSome codes aren't covered (see unsupportedMarkets), or a state has no supported metros.
429rate_limitedPer-minute limit. Wait Retry-After seconds (60 or less).
429allowance_exhaustedMonthly allowance used up. Retry-After points to the 1st of next month (UTC); retrying sooner won't succeed.
429too_many_failed_attemptsToo many failed keys from your address. Fix the key, then wait.
502artifact_invalidA forecast file failed its integrity check and was not served.
503product_unavailable, release_pending, source_unavailable, meter_unavailable, auth_unavailableTemporarily unavailable, or not yet released. Retry later.

Limits

  • Monthly allowance per brand, shared by every API key and AI app: forecast reads, lookups and data returned. Current usage is on the Integrations page. It resets on the 1st of each month (UTC). There are no overage charges; requests are refused until the reset.
  • Per-minute limit per brand. Wait for Retry-After.
  • Up to 100 metros per request (10 per AI-agent tool call). Leave places out to get all metros in one read.
  • The market list (/api/v1/markets) is free and needs no key.

Tip: one call without places returns every metro for one read. Fetch once a day after about 12:35 UTC and reuse your copy.

Use of forecasts, allowances and limits: Terms of Service and API and Data-use Terms.

For AI agents (MCP)

AI apps connected to https://YOUR-DERMAL-VECTORS-SITE/mcp see read-only tools with the same data and allowance, and receive a short briefing on what DSI means, citing the issue ID and saving allowance. Setup is in the guide.

ToolInputReturns
get_product_dictionaryOptional product; defaults to allField definitions, CSV/API mappings, units and examples; no forecast reads charged
list_forecast_productsnoneProducts your brand can use
get_product_coverageoptional query, state, near, limitSupported metros (filtered), with codes
get_dsi_forecastone of markets (1–10 codes), state, near; optional issue, view7-day summaries by default (daily rows with view=daily); issue ID; resolvedPlace for state/near
rank_metrosoptional by (mean7, excess, exposure65, trend), state, top (≤ 25)Top N metros nationwide or in a state, with their 7-day summaries
get_pilot_market_comparisonnoneThe brand owner's ten pinned pilot metros (five higher/lower DSI pairs) against the latest issue
get_search_outlookcategory; optional regions, query, sort, topWeekly search-interest outlook. Internal review only; listed by list_forecast_products only when available to your brand

Changes

  • 2026-10-06: 7-day summary measures (view=summary, sort, top): mean7, peak, excessAbove4, exposure65plus, trend; MCP returns summaries by default and adds rank_metros.
  • 2026-10-06: choose places by near or state; new public /api/v1/markets; separate allowance_exhausted and rate_limited codes; MCP tools accept places and send a briefing.