API v1EXAMPLE DATARead only, included with every shop

Does AlleyPulse have an API and MCP server for AI agents?

Yes. AlleyPulse has a read only REST API and a remote MCP server, so an owner's AI assistant can ask what changed around their shop this week and get the same tiered items as the Monday email, each with a dated source link. Create a key in the app. The hosts, keys, addresses and responses shown on this page are examples.

Last updated: 26 October 2026

What can an AI assistant do with AlleyPulse?

It reads the same weekly issue you get by email, so you can ask your assistant instead of opening the inbox. It cannot change anything, and it only sees your own shops.

Version
v1, read only, included with every shop subscription
REST base address
https://api.alleypulse.com/v1
MCP server
https://api.alleypulse.com/mcp over streamable HTTP
Sign in
Bearer API key, read only. OAuth for MCP clients is not part of v1.
Rate limit
60 requests per minute per key
Data
The same weekly issues as the email. Weekly, not real time.
Machine readable
An OpenAPI 3.1 file at /v1/openapi.json and a llms.txt file.
Questions an assistant could answer, and the call behind each one
QuestionMCP toolREST endpoint
What changed around my shop this week?get_latest_digestGET /shops/{id}/issues/latest
What should I act on before Friday?get_latest_digest (tier A)GET /shops/{id}/issues/latest?tier=A
Did a new listing appear near me in the last month?search_itemsGET /issues/{id}/items?category=new_listing
What did issue 4 say about the street market?get_itemGET /items/{id}
Does this address work with AlleyPulse?check_coveragePOST /coverage-check

How do I make the first request?

Create a read only key on the API and MCP screen in the app, then send it as a bearer token. These examples use the example key ap_live_EXAMPLE, and example shop and issue ids.

curl

curl
# Example only. The key is a placeholder: use your own key.
curl https://api.alleypulse.com/v1/shops/shp_EXAMPLE01/issues/latest \
  -H "Authorization: Bearer ap_live_EXAMPLE"

Read the latest issue for one shop. Replace the placeholder key and shop id with your own.

JavaScript

JavaScript
// Example only. The key is a placeholder: use your own key.
const res = await fetch(
  "https://api.alleypulse.com/v1/shops/shp_EXAMPLE01/issues/latest?tier=A",
  { headers: { Authorization: "Bearer ap_live_EXAMPLE" } }
);
if (!res.ok) throw new Error((await res.json()).error.message);
const issue = await res.json();
for (const item of issue.items) {
  console.log(item.tier, item.distance_m + " m", item.headline);
}

The same request with fetch. Filter to tier A to get only what needs action this week.

MCP

Claude Code
claude mcp add --transport http alleypulse https://api.alleypulse.com/mcp --header "Authorization: Bearer ap_live_EXAMPLE"

One command registers the server in Claude Code. Other clients are in the connect section below.

Response, issue (items shortened to one)
{
  "id": "iss_EXAMPLE06",
  "shop_id": "shp_EXAMPLE01",
  "number": 6,
  "published_at": "2026-10-26T07:00:00Z",
  "is_baseline": false,
  "scan": {
    "radius_m": 1000,
    "listings_scanned": 137,
    "scanned_on": "2026-10-25",
    "compared_with": "2026-10-18"
  },
  "tier_counts": { "A": 3, "B": 4, "C": 3 },
  "summary": "A nearby café started a morning promo aimed at your commuters, Saturday's street market will bring extra people past your door, and a bakery's rating dipped after complaints about waiting.",
  "items_url": "https://api.alleypulse.com/v1/issues/iss_EXAMPLE06/items",
  "items": [
    { "id": "itm_EXAMPLE01", "tier": "A", "headline": "A café 200 m away is offering two for one flat whites before 9am" }
  ]
}

The example issue has 10 items; the response above shows one. Fetch the rest from items_url.

Which REST endpoints are there?

Every data endpoint is a GET, so it is safe to retry. The two POST endpoints do not change your shop data. Responses are JSON, and the version is in the path.

Endpoints under https://api.alleypulse.com/v1
MethodPathReturnsNotes
GET/shopsThe shops this key can read.No parameters.
GET/shops/{id}One shop: name, address as you entered it, business type, radius, time zone, next issue date.
GET/shops/{id}/issuesIssues, newest first, without items.since, limit (default 10, maximum 52), cursor
GET/shops/{id}/issues/latestThe latest published issue with its items.Optional tier filters the embedded items.
GET/issues/{id}One issue: summary, tier counts, scan facts, items.
GET/issues/{id}/itemsItems of one issue, paginated.tier (A, B or C), category, max_distance_m, cursor
GET/items/{id}One item, with every field below.
POST/coverage-checkWhether an address is supported, has few listings, or is not supported.Address goes in the JSON body, never a query string. Free, limited to 10 requests per minute.
POST/webhooksSubscribes an HTTPS endpoint to issue.published. Returns the signing secret once.Also GET /webhooks and DELETE /webhooks/{id}.

Lists use cursor pagination: pass next_cursor from one response as cursor in the next request, and stop when has_more is false.

List response shape
{
  "data": [ { "id": "iss_EXAMPLE06", "number": 6, "published_at": "2026-10-26T07:00:00Z" } ],
  "next_cursor": "cur_EXAMPLE",
  "has_more": true
}

Address check example. The address is sent in the body so it never appears in a URL or an access log.

Address check
curl https://api.alleypulse.com/v1/coverage-check \
  -H "Authorization: Bearer ap_live_EXAMPLE" \
  -H "Content-Type: application/json" \
  -d '{"address": "12 Sample Street, Sampletown", "radius_m": 1000}'

What does an item contain?

Every item answers the same five questions as the email: what changed, where, why it matters, what to do this week, and the source. There is no field for review text or for the names of nearby businesses.

Item fields
FieldTypeMeaning
id, issue_id, issue_numberstring, string, integerIdentifiers. Issue number 1 is the baseline issue.
tierA, B or CA is act this week, B is worth knowing, C is skim.
categoryenumcompetitor_promo, competitor_rating, competitor_posts, new_listing, marked_closed, local_event, local_news, search_interest, weather, industry_trend, customer_mention, local_buzz. New values can be added within v1.
headlinestringOne line, in plain words, with an anonymized peer such as a café 200 m away.
what_changedstringWhat we saw and when, without quoting reviews.
distance_minteger or nullMeters from your address. Null for regional items such as weather or search interest.
why_it_mattersstring or nullWhy it could matter to a shop like yours. Null for some tier C items.
what_to_dostringOne suggested action for this week.
source_url, source_typestring, enumA dated source link and its kind: google_maps_listing, google_maps_post, events_calendar, news_page, weather_forecast, search_interest, trade_press or social_post.
first_seendateThe day our weekly scan first saw it. Not an opening date.
GET /items/itm_EXAMPLE01
{
  "id": "itm_EXAMPLE01",
  "issue_id": "iss_EXAMPLE06",
  "issue_number": 6,
  "tier": "A",
  "category": "competitor_promo",
  "headline": "A café 200 m away is offering two for one flat whites before 9am",
  "what_changed": "New post on its Google Maps listing, valid weekdays until Friday 6 November.",
  "distance_m": 200,
  "why_it_matters": "It targets the same commuters as your busiest window, 7 to 9am.",
  "what_to_do": "Do not match the price. Put your loyalty card or a coffee and pastry pairing in the window, and compare 7 to 9am sales with last week.",
  "source_url": "https://source.alleypulse.example/itm_EXAMPLE01",
  "source_type": "google_maps_post",
  "first_seen": "2026-10-24"
}

How do keys and sign in work?

  • Send Authorization: Bearer ap_live_... on every request. Keys never go in a URL.
  • A key is shown once when you create it and stored only as a hash. If you lose it, create a new one.
  • One scope in v1, read. A key can read all your shops or only the shops you choose.
  • Revoke a key in the app at any time. Requests with it fail straight away.
  • Keep keys out of browser code and public repositories. OAuth sign in for MCP clients is not part of v1.
Open the keys screen

What are the limits, versions and errors?

The limit is 60 requests per minute per key. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, and a 429 response adds Retry-After. Within v1 we may add fields and enum values without notice, so ignore what you do not recognize. Breaking changes ship as v2, with the old version kept running for at least 6 months.

Error codes
StatusCodeMeaning
400invalid_requestA parameter is missing or has the wrong shape.
401unauthorizedNo key, a wrong key or a revoked key.
403forbiddenThe key has no access to that shop.
404not_foundThe shop, issue or item does not exist, or belongs to someone else.
422unsupported_addressThe address check failed: Russia, Belarus or no listings found.
429rate_limitedMore than 60 requests in a minute for this key.
503unavailableA weekly scan is being published. Retry with the Retry-After header.
Error response
{
  "error": {
    "code": "rate_limited",
    "message": "The limit is 60 requests per minute for this key. Retry after 12 seconds.",
    "request_id": "req_EXAMPLE"
  }
}

How do webhooks work?

There is one event, issue.published, sent when the weekly issue for one of your shops is ready. The payload holds only ids, so fetch the items with the API. It is a weekly event, not a stream of live changes.

Webhook payload
{
  "id": "evt_EXAMPLE01",
  "type": "issue.published",
  "created_at": "2026-10-26T07:00:12Z",
  "data": {
    "shop_id": "shp_EXAMPLE01",
    "issue_id": "iss_EXAMPLE06",
    "issue_number": 6,
    "is_baseline": false
  }
}

Each delivery is signed. The header holds a timestamp and an HMAC SHA256 of t + "." + raw body, keyed with the endpoint secret you receive once when you subscribe. Reject deliveries whose timestamp is older than five minutes. Failed deliveries are retried up to 5 times over a day.

Signature header
AlleyPulse-Signature: t=1793000412,v1=EXAMPLE_HEX_DIGEST
Verify a signature, Node
// Example only. The secret is a placeholder.
import { createHmac, timingSafeEqual } from "node:crypto";

export function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const signed = parts.t + "." + rawBody;
  const expected = createHmac("sha256", secret).update(signed).digest("hex");
  const a = Buffer.from(expected);
  const b = Buffer.from(parts.v1 ?? "");
  return a.length === b.length && timingSafeEqual(a, b);
}

Which MCP tools are there?

A remote MCP server over streamable HTTP, signed in with the same read only API key. Every tool is read only and safe to repeat. No tool sends email, edits a shop or posts anywhere.

MCP server address
https://api.alleypulse.com/mcp
MCP tools
ToolArgumentsReturns
list_shopsnoneThe shops this key can read, with ids.
get_latest_digestshop_id (optional), tier (optional)The latest issue with its items. If shop_id is left out and the key reads one shop, that shop is used.
list_issuesshop_id, limitRecent issues, newest first, without items.
get_itemitem_idOne item with every field.
search_itemsquery, shop_id, since, tierItems whose headline or text match the query, newest first. Searches only your own issues.
check_coverageaddressWhether the address is supported, has few listings or is not supported.

One resource is available: alleypulse://shops/{id}/issues/latest, the latest issue of a shop, so a client can attach it to a conversation.

How do I connect a client?

Copy a snippet, replace the placeholder key with your own, and restart the client. Client configuration formats differ and change, so treat these as examples and check your client's current documentation.

Claude Code

Terminal
claude mcp add --transport http alleypulse https://api.alleypulse.com/mcp --header "Authorization: Bearer ap_live_EXAMPLE"

Run this in a terminal. Claude Code lists the server in its MCP settings afterwards.

Claude Desktop

claude_desktop_config.json
{
  "mcpServers": {
    "alleypulse": {
      "command": "npx",
      "args": [
        "-y", "mcp-remote",
        "https://api.alleypulse.com/mcp",
        "--header", "Authorization: Bearer ${AP_API_KEY}"
      ],
      "env": { "AP_API_KEY": "ap_live_EXAMPLE" }
    }
  }
}

Claude Desktop reaches remote servers through its connectors screen or a local bridge such as mcp-remote. This example uses the bridge in claude_desktop_config.json.

Cursor

.cursor/mcp.json
{
  "mcpServers": {
    "alleypulse": {
      "url": "https://api.alleypulse.com/mcp",
      "headers": { "Authorization": "Bearer ap_live_EXAMPLE" }
    }
  }
}

Save as .cursor/mcp.json in your project, or in your home folder for all projects.

Generic mcp.json

mcp.json
{
  "mcpServers": {
    "alleypulse": {
      "type": "http",
      "url": "https://api.alleypulse.com/mcp",
      "headers": { "Authorization": "Bearer ap_live_EXAMPLE" }
    }
  }
}

Many clients accept this shape. Field names differ between clients, so check yours.

What does a conversation look like?

An owner asks an assistant that has the MCP server connected. Here is an example. The assistant calls one tool and answers from the issue.

Example conversation. Nothing here was sent or received.EXAMPLE DATA
You

What changed around my shop this week?

Assistant calls a tool

get_latest_digest with {"tier": "A"}, returns 3 items from issue 6.

Assistant

Three things need action this week, from Monday's issue (example data):

  • A café 200 m away is offering two for one flat whites before 9am on weekdays until 6 November. It targets your 7 to 9am commuters, so the suggestion is to skip the price match and promote your loyalty card or a coffee and pastry pairing. Source: its Google Maps listing post, first seen 24 October.
  • A street market is on Sample Square this Saturday from 10:00 to 16:00, and Market Lane is closed to traffic. Consider moving Saturday's delivery to Friday. Source: the city events calendar, published 21 October.
  • A bakery 0.8 km away dropped from 4.6 to 4.4 stars after 9 new reviews in 7 days, and 5 of them mention waiting. Quick service is a gap you can fill, so make order ahead visible. Source: its Google Maps rating and review count.

This is the issue from 26 October. AlleyPulse is weekly, so new changes will appear next Monday. Each item above links to its source.

What are the data rules?

  • No raw review text. Items give counts, rating changes and short summarized themes, never quoted reviews or reviewer names.
  • Anonymized peers. Nearby businesses appear as a café 200 m away, not by name.
  • Sources linked. Every item has a source link, a source type and the day we first saw it.
  • Weekly, not real time. Data is a weekly snapshot and can be hours to days old when you read it.
  • The first issue is a baseline. It is flagged is_baseline: true and shows what is around you, not what changed. New and closed items begin in issue 2 and are reliable from about week 3 to 4.
  • New on Google Maps is not an opening. A closed item means marked closed on Google at scan time.
  • Same coverage as the email. Wherever Google Maps has business listings, except Russia and Belarus. See coverage.
  • For your own use. Use items in your own tools and assistants. The terms cover reuse and resale.

How do I get access, and what does it cost?

Every shop subscription includes read only API and MCP access to the same data as the email, at 60 requests per minute per key and up to 5 active keys per account. The address check is free for everyone at a lower limit. There is no extra charge for the API. The $39 per month per shop on the pricing page is a placeholder price, and we are not charging yet.

API and MCP questions

Does AlleyPulse have an API?

Yes. AlleyPulse has a read only REST API with bearer API keys, base address https://api.alleypulse.com/v1, that returns the same weekly issues and items as the Monday email. Every shop subscription includes it, and you create keys in the app.

Does AlleyPulse have an MCP server, and which AI assistants can connect?

Yes. The MCP server is a remote server over streamable HTTP at https://api.alleypulse.com/mcp, signed in with an API key. Any assistant or editor that supports remote MCP servers can connect, such as Claude Code, Claude Desktop through a bridge, or Cursor. Setup snippets for each are on this page, and client formats differ.

Is the API data the same as the weekly email?

Yes. The email, the web view, the API and the MCP server read the same weekly issues, so an assistant sees the same items, tiers, distances, suggested actions and source links you see in your inbox. It is a weekly snapshot, not a live feed.

Can my AI assistant ask what changed around my shop this week?

Yes, that is the main use. An assistant with the MCP server connected can call a tool such as get_latest_digest and answer from the latest issue, for example by listing the tier A items you should act on this week and quoting each source. Because issues are weekly, asking again before the next Monday returns the same issue.

Can the API or MCP server change anything or send messages?

No. Data access is read only. There are no endpoints to edit your shop, send email or post anywhere. The only writes are creating and deleting webhook endpoints, and the address check, which does not store your address.

How are API keys protected, and how do I revoke one?

A key is shown once when you create it and stored only as a hash on our side. Each key is read only and can be limited to chosen shops. You can revoke a key at any time in the app, and requests with a revoked key fail straight away. Keep keys out of browser code and public repositories.

What are the rate limits?

The limit is 60 requests per minute per key. Responses carry the headers X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, and a 429 response adds Retry-After. The free address check has a stricter limit of 10 requests per minute.

Does the API return Google review text or competitor names?

No. Items report counts, rating changes and short summarized themes, and nearby businesses are anonymized, for example as a café 200 m away. Every item links to its source type and a dated source link instead of copying third party text.

How much does API and MCP access cost?

Nothing extra. Read only API and MCP access is included with each shop subscription, with the same data as the email. The subscription price is $39 per month per shop, and we are not charging yet. The free address check is open to everyone at a lower limit.