# Find companies expanding into a new market with Pubrio's API

Pubrio's Market Expansion API finds companies moving into a target market and returns each company's expansion stage and existing footprint there, built from dated signals such as local hiring, new offices and entities, localized ads and news. Every expansion call is 5 credits, $0.05. Send `POST https://agents.pubrio.com/zcj/jnq5mvn61id6/expansions/search` with `tos` and `froms` as ISO 3166-1 alpha-2 country codes. The storefront answers with a 402 price quote, which you pay and retry, so nothing is charged until you pay.

## At a glance

- **Endpoint:** `POST https://agents.pubrio.com/zcj/jnq5mvn61id6/expansions/search`
- **Body:** `tos` (target markets) and `froms` (origin markets), arrays of ISO 3166-1 alpha-2 codes such as `["JP"]`, plus optional filters, `query`, `page` and `per_page`
- **Price:** 5 credits per call at $0.01, which is $0.05. On Scale it is $0.009.
- **Payment:** a 402 quote paid over x402 (Base USDC) or MPP (Tempo USDC), then the same request retried with the proof. No account or API key.
- **Response:** `data.companies`, each with company fields, a `stage` block and a `presence` block, plus `data.pagination`
- **Limits:** up to 25 results per page
- **Full purchase flow:** [the buyer skill](https://agents.pubrio.com/zcj/jnq5mvn61id6/SKILL.md)

## Search for companies entering a market

1. Send the search. This example asks for companies expanding from the United States into Japan:

   ```bash
   curl -sS -X POST https://agents.pubrio.com/zcj/jnq5mvn61id6/expansions/search \
     -H 'Content-Type: application/json' \
     -d '{"froms": ["US"], "tos": ["JP"], "per_page": 5}'
   ```

   The storefront returns a 402. Its body carries `payment.amountUsd` and a `protocols` block with a challenge for each rail.

2. Pay the challenge with an x402 or MPP client and retry the identical request. The proof goes in `x-payment` for x402, or in `Authorization: Payment <credential>` for MPP.

3. Read the 200 response. This is the first result of the example search, trimmed:

   ```json
   {
     "data": {
       "pagination": {"page": 1, "per_page": 5, "total_entries": 2932, "total_pages": 587, "total_display_pages": 250, "is_timeout": false, "is_estimated": false},
       "companies": [
         {
           "domain_search_id": "<domain_search_id>",
           "domain": "alaskaair.com",
           "company_name": "Alaska Airlines",
           "home_country_code": "US",
           "target_country_code": "JP",
           "industry": "Airlines and Aviation",
           "employees_count": 12615,
           "stage": {"slug": "scaling", "expansion_score": 0.926, "scope": "entering_new_market", "direction": "advancing", "freshness": "fresh", "signal_count": 6, "distinct_type_count": 4, "has_known_presence": false},
           "presence": {"level": "none", "local_people_count": 0, "established_min": 10, "share_of_detected": 0, "has_known_office": false, "matched_rule": null},
           "read": null
         }
       ]
     }
   }
   ```

   The example search matched 2,932 companies, paid $0.05 and returned in 8.7 seconds.

## Read each result

| Field | What it holds |
| --- | --- |
| `stage.slug` | The expansion stage: `exploring`, `committing`, `expanding` or `scaling` |
| `stage.expansion_score` | The score for this company and market, from 0 to 1 on search results |
| `stage.scope` | `entering_new_market`, `expanding_within_presence` or `established_only` |
| `stage.direction` | The trajectory: `advancing`, `steady`, `retreating` or `new` |
| `stage.freshness` | Evidence recency: `fresh` (about 30 days), `cooling` (30 to 60), `stale` (60 to 90), `cold` (over 90) |
| `presence.level` | How settled the footprint in the market already is: `established`, `emerging`, `none` or `no_data`. This is the footprint, not the stage. |
| `presence.local_people_count` | Employees located in the target market |
| `presence.matched_rule` | The signal that set the level, such as `office`, `headcount` or `share`. `null` when no rule matched. |
| `read.code` | `scaling`, `deepening`, `active` or `establishing`. `null` when there is no local presence to read. |

Pass a result's `domain_search_id` to the profile lookup below.

## Narrow the search

| To find | Send |
| --- | --- |
| A stage | `stages`, such as `["committing", "expanding"]` |
| A trajectory | `momentum`: `advancing`, `steady` or `pulling_back` |
| Recent evidence only | `freshness`, such as `["fresh"]` |
| New entries rather than deeper presence | `scopes`: `["entering_new_market"]` |
| Evidence of a kind | `signal_types`, such as `["HIRE", "OFFICE", "ENTITY"]` |
| A recent window, or companies moving fast | `window_days`, `min_markets` (new markets entered in the window), `ahead_of_pace` |
| A firmographic profile | `employees`, `revenues`, `founded_dates`, `keywords` |
| A described buyer, in plain words | `query` |
| An explanation per company | `is_explain_match: true`, which adds `match_summary` to each company |

With `query`, `metadata.filters` shows the filters the text was read as. When the text holds no recognizable criteria, the list is empty and `metadata.nl_note` says so.

Filter values are case-sensitive and are not validated. On `stages`, `freshness`, `scopes` and `momentum`, an unrecognised value drops the whole filter and the search returns unfiltered results. On `signal_types`, an unrecognised value makes the filter match nothing. Either way the response looks normal. Use the lowercase and uppercase slugs above exactly. `momentum` takes only `advancing`, `steady` and `pulling_back`; sending the response values `retreating` or `new` turns the filter off. If a total looks wrong, compare `data.pagination.total_entries` with the same call without the filter.

## Read one company's expansion profile

Send the company's `domain_search_id` and the market. `summary_only` returns the stage summary and skips the paginated signal list:

```bash
curl -sS -X POST https://agents.pubrio.com/zcj/jnq5mvn61id6/expansions/companies/lookup \
  -H 'Content-Type: application/json' \
  -d '{"domain_search_id": "<domain_search_id>", "country_code": "JP", "summary_only": true}'
```

The response contains `data` with the market's `stage` block, `stage_name` and `stage_rank`; `company` with the description, website and social URLs; `markets_summary`, one entry per market with its stage, signal counts and score; `signal_weekly_totals` by signal type; `recent_signals`, each with its type, source, polarity, `evidence_url` and `event_date`; a top-level `expansion_score`; and `summary`. The example profile for the first company in the search paid $0.05 and returned in 5.5 seconds. Add `query` with `is_explain_match: true` to fill `summary` with one summary grounded in the company's signals, with `[n]` citations.

## Other expansion operations

Each is 5 credits.

| Question | Operation |
| --- | --- |
| How do several companies' footprints compare? | `POST https://agents.pubrio.com/zcj/jnq5mvn61id6/expansions/companies/compare` |
| Which company and market pairs score highest? | `POST https://agents.pubrio.com/zcj/jnq5mvn61id6/expansions/companies/rankings` |
| Which signal events drive one company's expansion? | `POST https://agents.pubrio.com/zcj/jnq5mvn61id6/expansions/companies/pulse_events` |
| What is the ready-made summary for up to 25 companies? | `POST https://agents.pubrio.com/zcj/jnq5mvn61id6/expansions/companies/summaries` |
| Which markets and corridors are busiest? | `POST https://agents.pubrio.com/zcj/jnq5mvn61id6/expansions/dashboard` |
| Which raw signals match? | `POST https://agents.pubrio.com/zcj/jnq5mvn61id6/expansions/signals/search` |

## Limits

- One call is one page of up to 25 companies. More results means more calls, each charged.
- A 402 you have not paid charges nothing, so it is safe to stop there.
- Card pays only calls of $0.55 or more, so a 5-credit call is paid over x402 or MPP, or drawn from prepaid credit.

## Errors

| Status | Meaning | Action |
| --- | --- | --- |
| `402` | The price quote | Pay it and retry the same request, or stop |
| `400` | Malformed body or invalid parameter | Check `code` and `message`, fix the body |
| `416` (`41676`) | `per_page` above the limit | Send `per_page` of 25 or less |
| `429` | Rate limit reached | Wait for the window to reset, then retry |
| `settlement_failed` | The payment did not settle | Fix the wallet and send a fresh request |

## Frequently asked questions

### How do I find companies expanding into Japan?

Send `POST https://agents.pubrio.com/zcj/jnq5mvn61id6/expansions/search` with `"tos": ["JP"]`. Add `froms`, such as `["US"]`, to limit it to one origin, and `scopes: ["entering_new_market"]` for companies new to the market.

### How much does a market expansion search cost?

Every expansion call is 5 credits, $0.05 pay as you go. The 402 states the exact amount before you pay.

### Does a misspelled filter value return an error?

No. Values are not validated. A wrong value in `stages`, `freshness`, `scopes` or `momentum` silently widens the search, and a wrong `signal_types` value matches nothing.

### Can the API explain why a company matched?

Yes. Set `is_explain_match: true` on the search for a `match_summary` per company, or send `query` with `is_explain_match: true` to the profile lookup for a summary with `[n]` citations to the company's signals.

### Do I need an account or API key?

No. Each call is paid on its own through the 402. An agent identity is needed only for prepaid plans and the free trial.

## Keep reading

- [The buyer skill](https://agents.pubrio.com/zcj/jnq5mvn61id6/SKILL.md): the full purchase flow
- [How to pay](https://agents.pubrio.com/zcj/jnq5mvn61id6/payment.md): rails, plans and top-ups
- [Market Expansion service](https://agents.pubrio.com/zcj/jnq5mvn61id6/services/expansion): price by plan
- [Error reference](https://agents.pubrio.com/zcj/jnq5mvn61id6/errors.md): every storefront error

---

Updated 2026-11-04. All Pubrio guides: https://agents.pubrio.com/guides.md. Storefront: https://agents.pubrio.com/zcj/jnq5mvn61id6/llms.txt.
