# Japan Public Tender Alerts (kkj.go.jp) (`aflame_brigantine/kkj-tender-alert`) Actor

官公需情報ポータル(kkj.go.jp)の入札公告をキーワード・都道府県・日付で検索し、前回実行からの新着差分を構造化データで返します。

- **URL**: https://apify.com/aflame\_brigantine/kkj-tender-alert.md
- **Developed by:** [Kameda Hyper](https://apify.com/aflame_brigantine) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 new tender records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Japan Public Tender Alerts (kkj.go.jp)

Track new public-sector tender announcements published on Japan's [government procurement portal (官公需情報ポータルサイト, kkj.go.jp)](https://www.kkj.go.jp/s/), operated by Japan's Small and Medium Enterprise Agency (中小企業庁). This Actor is an independent tool and is **not affiliated with or endorsed by** kkj.go.jp or any Japanese government agency.

日本の中小企業庁が運営する[官公需情報ポータルサイト（kkj.go.jp）](https://www.kkj.go.jp/s/)の公開 API を使い、入札公告をキーワード・都道府県・日付で検索し、**前回実行からの新着差分**を構造化データで返す Actor です。本 Actor は非公式のツールであり、kkj.go.jp や日本政府機関とは無関係です。

### What does this Actor do?

- Queries the official kkj.go.jp search API (public, no API key required) for tender announcements (入札公告)
- Filters by free-text keywords, prefecture, category (goods/construction/services), and announcement date
- Tracks which tenders you've already seen across runs, so scheduled runs only charge for genuinely new items
- Strips likely personal contact details (phone numbers, emails, staff names) from the announcement text by default

キーワード・都道府県・カテゴリー（物品/工事/役務）・公告日で絞り込み、前回実行以降に初めて見つかった案件だけを新着として返します（`onlyNew` を `false` にすると全件返します）。既定では公告文に含まれがちな担当者の電話番号・メール・氏名をマスクします。

### Why use it?

Commercial tender-tracking services in this space (nSearch, bJAMP, etc.) typically cost ¥8,000–¥20,000/month per prefecture. This Actor lets you build the same alerting into your own workflow — combined with a scheduled run and Apify's webhook/Slack/Zapier/Make integrations, you get a free-data-source alternative you fully control, paying only per new record found.

nSearch・bJAMP等の有料入札情報サービスは月8,000〜20,000円/都道府県が相場です。本 Actor はスケジュール実行とApifyのWebhook/Slack/Zapier/Make連携を組み合わせることで、公開APIを使った低コストな代替手段になります。

### How to use it

1. Set `keywords` and/or `prefectures` to narrow your search (leave both empty for nationwide, all-category results).
2. Set `publishedAfter` (defaults to 7 days before the run) to control how far back to look.
3. Schedule the Actor to run daily or weekly. With `onlyNew: true` (default), you'll only be charged for tenders you haven't seen in a previous run.
4. Optionally set `webhookUrl` to receive a POST with new tenders as soon as a run finds them — or use Apify's built-in webhook/Slack/Zapier/Make integrations instead.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `keywords` | string\[] | `[]` | Full-text search terms (OR). Empty = no keyword filter. |
| `prefectures` | string\[] | `[]` | Japanese prefecture names (e.g. `東京都`). Empty = nationwide (fetched per-prefecture and merged so large result sets aren't silently dropped). |
| `category` | string | `""` | `物品` (goods) / `工事` (construction) / `役務` (services). The underlying API only supports one category per run. |
| `publishedAfter` | string (`YYYY-MM-DD`) | 7 days before run | Only tenders announced on/after this date. |
| `onlyNew` | boolean | `true` | Only output/charge for tenders not seen in a previous run. |
| `includeContact` | boolean | `false` | Keep the raw announcement text as-is. When `false`, phone numbers, emails, and staff names are redacted. |
| `maxItems` | integer | `20` | Max records per run. If you search a single prefecture, note that a single request is capped at 200 records for memory safety — searching multiple prefectures (or nationwide) fetches per-prefecture and merges, so `maxItems` can go higher there. |
| `webhookUrl` | string (URL) | — | If set, new tenders are POSTed here as JSON. |

### Output

```json
{
  "id": "kkj:c2VhcmNoL3BfcG9ydGFsLzIwMjYvMDkvMjAyNjA5MTFfNzkwMzAK",
  "title": "令和８年度中小企業実態調査事業…",
  "organization": "経済産業省",
  "prefecture": "北海道",
  "category": "役務",
  "procedureType": "一般競争入札",
  "announcedAt": "2026-09-11T00:00:00+09:00",
  "openingAt": "2026-10-05T00:00:00+09:00",
  "sourceUrl": "https://www.p-portal.go.jp/pps-web-biz/UAA01/OAA0101",
  "isNew": true
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel from the Output tab.

| Field | Description |
|---|---|
| `title` | Tender project name (件名) |
| `organization` | Issuing government body (発注機関) |
| `prefecture` / `city` | Location of the issuing body |
| `category` | 物品 (goods) / 工事 (construction) / 役務 (services) |
| `procedureType` | e.g. 一般競争入札 (open competitive bidding) |
| `announcedAt` | Announcement date (公告日) |
| `openingAt` | Bid opening date (開札日), when available |
| `description` | Full announcement text (contact details redacted unless `includeContact: true`). Very long announcements are capped at 50,000 characters. |
| `descriptionTruncated` | `true` if the announcement text was cut off because it exceeded the 50,000-character cap. |
| `attachments` | Linked documents (specs, drawings), when available |
| `sourceUrl` | Original announcement URL. For some issuing systems this is a generic portal search entry page rather than a deep link to the specific announcement — kkj.go.jp does not guarantee deep-link stability. |
| `isNew` | Whether this is the first time this Actor has seen the tender |

#### Run summary (key-value store `OUTPUT`)

Besides the dataset, each run writes a small JSON summary to its default key-value store under `OUTPUT`, including `totalSearchHits`, `searchTruncated`, and `skippedLgCodes` — a list of prefecture codes that had to be skipped this run (e.g. because a response exceeded the memory safety limit described above). Check this if a prefecture you expect to see data from is consistently missing.

### Pricing

Pay-per-event: **$0.05** per run (`actor-start`) + **$0.003** per new tender record (`tender-record`, charged only for new items when `onlyNew: true`).

Example: running weekly (~4 times/month) and finding 50 new tenders per run costs 4 × $0.05 + 4 × 50 × $0.003 = $0.20 + $0.60 = **$0.80/month**.

The default `maxItems` (20) is intentionally small to keep a first trial run cheap — raise it once you know how many new tenders your filters typically return per run.

### Tips

- Narrow by `prefectures` and `keywords` to reduce noise and cost on broad categories.
- Set `maxItems` to a level your `maxTotalChargeUsd` run budget can cover — if the budget is reached mid-run, the remaining new tenders are simply picked up on the next run (nothing is lost or double-charged).
- If a run's `SearchHits` total exceeds what was returned, the run log will say so and the Output's `searchTruncated` flag will be `true` — narrow `publishedAfter` or raise `maxItems` if that happens often for your search.
- A handful of records on kkj.go.jp are, as published, extremely large (observed up to hundreds of MB for a single record). To protect the run's memory, this Actor skips any prefecture whose response exceeds a safety size limit for that run (logged as a warning, and reflected in `searchTruncated`) rather than crashing. This is rare and only affects the specific prefecture/date-range combination that triggers it.
- Use Apify's Schedule feature with a weekly or daily interval for ongoing monitoring.

### FAQ, disclaimers, and support

- This Actor only reads publicly published tender announcements (公告) via kkj.go.jp's official public API — no login, scraping, or circumvention of access controls is involved.
- Data accuracy and availability depend entirely on kkj.go.jp; this Actor does not guarantee completeness or timeliness.
- Source links (`sourceUrl`) may point to pages requiring login (p-portal.go.jp) for full bid submission — this Actor itself never accesses login-gated content.
- Found a bug or have a feature request? Open an issue on the Actor's Issues tab.

# Actor input Schema

## `keywords` (type: `array`):

全文検索語（いずれかを含む案件を取得、OR検索）。空欄なら全国・全件を対象にします。

## `prefectures` (type: `array`):

絞り込む都道府県名（複数選択可）。空欄なら全国。

## `category` (type: `string`):

業種区分で絞り込みます（API は単一選択のみ対応）。空欄なら全カテゴリー。

## `publishedAfter` (type: `string`):

公告日の下限（YYYY-MM-DD）。既定は実行日の7日前。

## `onlyNew` (type: `boolean`):

前回実行以降に初めて見た案件だけを出力・課金対象にします。

## `includeContact` (type: `boolean`):

公告文（ProjectDescription）を無加工のまま含めます。オフの場合は電話番号・メールアドレスらしき文字列を除去します。

## `maxItems` (type: `integer`):

1 run あたりの最大取得件数（新着課金の上限にもなります）。都道府県を絞らない場合は都道府県ごとに分割取得してこの件数までマージします。メモリ保護のため1都道府県あたりの取得件数は200件に制限されるので、1都道府県のみを対象にする検索では実質200件が上限になります（複数/全国を対象にする場合は都道府県ごとに最大200件ずつ集めてから、全体でこの件数に絞り込みます）。既定値は初回実行の課金を抑えるため小さめにしています。

## `webhookUrl` (type: `string`):

新着があれば、新着一覧をこの URL に POST します（任意）。

## Actor input object example

```json
{
  "keywords": [
    "除雪"
  ],
  "prefectures": [],
  "category": "",
  "publishedAfter": "",
  "onlyNew": true,
  "includeContact": false,
  "maxItems": 50,
  "webhookUrl": ""
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "keywords": [
        "除雪"
    ],
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("aflame_brigantine/kkj-tender-alert").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "keywords": ["除雪"],
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("aflame_brigantine/kkj-tender-alert").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "keywords": [
    "除雪"
  ],
  "maxItems": 50
}' |
apify call aflame_brigantine/kkj-tender-alert --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,aflame_brigantine/kkj-tender-alert"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/T5HKPi1BQHhg33mNP/builds/9K6pINhx1Fn292pur/openapi.json
