---
title: "Deployer activity timeline (launches, dev buys/sells/transfers, creator transfers, fees, funding)"
method: GET
path: "/deployer-hunter/{wallet}/activity"
tags: ["Deployer Hunter"]
---

# Deployer activity timeline (launches, dev buys/sells/transfers, creator transfers, fees, funding)

`GET /deployer-hunter/{wallet}/activity`

## Request

- Base URL: `https://madeonsol.com/api/v1`
- URL: `https://madeonsol.com/api/v1/deployer-hunter/{wallet}/activity`
- Auth: HTTP bearer

One newest-first timeline of what a deployer wallet did, from data MadeOnSol already holds. **The window applies to each event's own time** (`window.applies_to: event_time`): a sell yesterday of a token launched months ago is inside a 30-day window. Event types: `launch` (every launchpad we index; `fee_payer_is_creator` / `external_fee_payer` say whether the creator paid the create fee, null when unknown; `dev_buy_sol` / `dev_buy_tokens` / `dev_buy_supply_pct` from the create transaction when recorded), `dev_buy` / `dev_sell` (the deployer's own classified trades from the stored trade tape plus persisted realtime dev events where applicable; realtime rows can include activity below the ordinary trade persistence floor), `dev_token_transfer_out` / `dev_token_transfer_in` (persisted developer transfers of the attributed token; one public aggregate per transaction/mint/direction/actor, with raw amount/counterparty fields; recovered gap rows are REST history only and were never delivered live), `creator_transferred` (pump.fun creator rights moved to or from this wallet: the raw `from` / `to` of the event, `direction`, `initiated_by` creator | platform_admin | other_signer | unknown), `fee_claim` (creator-fee claims paid to the wallet), `funding_in` (one event per funder, timed by the latest transfer, `first_at` = first transfer; recorded only while the wallet is in the funding tracked set) and `capital_out` (one event per recipient address, timed by the latest transfer; recorded only when the wallet is a tracked high-signal source). Addresses in events are raw facts of the concrete event, not identity claims. Every event carries `time_basis` (chain | ingest | chain_or_ingest). `coverage.families.<family>` states each source, retention, scope, `truncated`, `complete`, `complete_from` and `archive_required_before`. **History is served from the online (Postgres) store; older trade months live only in the Parquet archive.** Archive reads for `dev_trades` are being rolled out for ULTRA and BUSINESS (PRO's 30-day window never reaches the archive). While they are off, a window that crosses that boundary is never reported as complete: `dev_trades` answers `complete: false`, `complete_from` = the earliest instant the online store covers completely, `archive_required_before` = the instant before which events exist only in the archive, and `coverage.status` is `partial`. If the boundary cannot be read, the family is `complete: false` with `boundary_known: false`. Fixed-retention families also carry `retention_boundary`: when the dev-event source is enabled, `dev_transfers` (SPL / Token-2022 transfers of the deployer's own token from the legacy watch + broad attributed-creator source) is held 30 days online, so a window starting before `retention_boundary` answers `complete: false` with `complete_from` = `retention_boundary` and `coverage.status: partial` (those rows are pruned, not archived). A wallet MadeOnSol has never attributed a launch to cannot have dev trades: `dev_trades` is then not queried and says `skipped_reason: no_attributed_launch`. `plan.history` separates the requested window (`requested`, `effective` after the tier clamp), the online coverage (`online`, served) and the archive-only range (`archive_only`, null when the window does not reach it). Without archive reads `archive_only` says `served: false`, `reason: archive_reads_not_enabled`. With archive reads, `coverage.families.dev_trades.archive` reports the read (`read` ok | not_needed | failed, `served`, `reason`, `missing_months`, `months_read`) and `archive_only.served` is true only when the archive answered for the whole range; `dev_trades` is then `complete: true` with `archive_required_before: null`. When an archive month is missing, `complete_from` / `archive_required_before` move to the end of the newest missing month (`reason: archive_months_missing`). If the archive is unavailable or times out, the online part is returned with `complete: false` and `reason` archive_unavailable | archive_timeout | archive_contract_mismatch | archive_ledger_unavailable, never an error and never a false complete. **An empty family is not evidence that nothing happened.** Paginate with `cursor` (opaque, ordered by (at, id), never skips equal timestamps). Server-side hard caps by plan (`plan` echoes them): PRO a 30-day window / 100 per page, ULTRA a 365-day window / 100 per page, BUSINESS an unbounded window / 500 per page; a larger `limit` is clamped (`pagination.limit_capped`) and an earlier `since` is clamped to the plan window. The ULTRA and BUSINESS windows normally reach past the online trade boundary, so their `dev_trades` coverage is usually partial (see above). ULTRA and BUSINESS responses carry an `identity` block, which currently answers `status: not_available` (identity stitching is not released; no linked wallets are reported, which says nothing about whether the wallet operates alone). PRO responses never carry an identity block or a fee-payer address. LIVE in production for PRO+. The capability flag remains a rollback guard; if an operator disables the feature the route answers 503 `feature_disabled` rather than returning a false empty timeline.

## Path parameters

- `wallet` string, required

## Query parameters

- `limit` integer
- `cursor` string
- `since` string, date-time
- `types` string

## Response `200`

OK

- object
  - `wallet` string
  - `is_deployer` boolean
  - `deployer` object, nullable
    - `tier` string, nullable
    - `first_deploy_at` string, nullable
    - `last_deploy_at` string, nullable
  - `plan` object
    - `entitlement` 'pro' | 'ultra' | 'business'
    - `window_days` integer, nullable
    - `max_limit` integer
    - `history` object
      - `requested` object
        - `from` string, nullable
        - `to` string, nullable
        - `source` 'since_param' | 'plan_default'
      - `effective` object
        - `from` string, nullable
        - `to` string, nullable
        - `clamped` boolean
        - `max_days` integer, nullable
      - `online` object
        - `from` string, nullable
        - `to` string, nullable
        - `served` boolean
      - `archive_only` object, nullable: Range held only in the Parquet archive. null when the window does not reach it. served:true only when the archive answered for the whole range (reason null); otherwise served:false with the reason (missing_months when month-shaped).
        - `from` string, nullable
        - `to` string, nullable
        - `served` boolean
        - `reason` 'archive_reads_not_enabled' | 'archive_unavailable' | 'archive_timeout' | 'archive_contract_mismatch' | 'archive_ledger_unavailable' | 'archive_months_missing' | 'null', nullable
        - `missing_months` string[]: YYYY-MM months of the range that are not served.
  - `window` object
    - `since` string, nullable
    - `until` string
    - `max_days` integer, nullable
    - `applies_to` 'event_time'
  - `events` object[]
    - `id` string, required
    - `type` 'launch' | 'dev_buy' | 'dev_sell' | 'dev_token_transfer_out' | 'dev_token_transfer_in' | 'creator_transferred' | 'fee_claim' | 'funding_in' | 'capital_out', required
    - `at` string, required
    - `time_basis` 'chain' | 'ingest' | 'chain_or_ingest', required
    - `mint` string, nullable
    - `name` string, nullable
    - `symbol` string, nullable
    - `launchpad` string, nullable
    - `bonded_at` string, nullable
    - `fee_payer_is_creator` boolean, nullable
    - `external_fee_payer` boolean, nullable
    - `dev_buy_sol` number, nullable
    - `dev_buy_tokens` number, nullable
    - `dev_buy_supply_pct` number, nullable
    - `own_token` boolean
    - `sol` number, nullable
    - `tokens` number, nullable
    - `price_usd` number, nullable
    - `actor_wallet` string, nullable: Realtime dev-event actor; direct developer or, for ULTRA+ identity projection, a proven linked wallet.
    - `actor_role` 'deployer' | 'linked_wallet' | 'null', nullable
    - `token_amount_raw` string, nullable: Exact base-unit amount for realtime dev events.
    - `supply_pct` number, nullable
    - `venue` string, nullable
    - `counterparty` string, nullable: Raw transfer counterparty; never an identity claim.
    - `counterparty_class` string, nullable
    - `feed` string, nullable: Timeline source/projection marker for dev events.
    - `first_at` string, nullable
    - `last_at` string, nullable
    - `aggregate` boolean
    - `from` string, nullable
    - `to` string, nullable
    - `direction` 'in' | 'out'
    - `initiated_by` 'creator' | 'platform_admin' | 'other_signer' | 'unknown'
    - `tx` string
    - `kind` 'direct' | 'social'
    - `amount_raw` string, nullable
    - `quote_mint` string, nullable
    - `source` string
    - `recipient` string
    - `asset` string
    - `decimals` integer, nullable
    - `transfer_count` integer
    - `sample_tx_ids` string[]
    - `first_tx` string, nullable
    - `counterparty_count` integer, nullable: Developer token transfers (dev-event source only): one event per (transaction, mint, direction, actor); `counterparty` is the largest counterparty, this is how many counterparties the aggregate has. Null on rows stored before 2026-10-06.
    - `recovered` boolean: Developer token transfers (dev-event source only): present and true when the event was recovered into stored history after a delivery gap (it was never delivered live on WS or webhook). `time_basis` says which clock `at` uses: re-derived from a confirmed block = chain block time (`time_basis: chain`); replayed from the producer spool = the original receive time (`time_basis: ingest`).
    - `recovered_at` string, nullable: With `recovered: true`: when the recovery stored the event (not the event's time).
    - `late_classified` boolean: Developer token transfers (dev-event source only): present and true when the event was received live but classified after a short creator lookup (a token minutes or seconds old). `at` stays the receive time.
  - `pagination` object
    - `limit` integer
    - `requested_limit` integer
    - `limit_capped` boolean
    - `next_cursor` string, nullable
    - `has_more` boolean
  - `coverage` object
    - `status` 'observed' | 'partial'
    - `families` object
    - `future_events_dropped` integer
    - `note` string
  - `identity` object: ULTRA and BUSINESS only; absent on PRO. Currently always `status: not_available` with `reason: identity_stitching_not_released` (identity stitching is not released). When released, the block is read from MadeOnSol's offline identity graph (one hop: the wallet's identity, with evidence and confidence) and answers `not_available` with another `reason` whenever that graph is not current or fails a consistency check (`builder_stale`: the graph is older than `builder.stale_after_seconds`; old links are never served as current). `not_available` never means the wallet operates alone.
    - `status` 'not_available' | 'linked' | 'no_strong_evidence'
    - `reason` 'identity_stitching_not_released' | 'builder_never_ran' | 'builder_stale' | 'builder_rule_mismatch' | 'builder_gate_failed' | 'identity_not_active' | 'identity_inconsistent' | 'evidence_missing' | 'member_excluded' | 'identity_lookup_failed': Only with status not_available.
    - `note` string: Only with status not_available.
    - `scope` 'builder_one_hop'
    - `rule_version` string
    - `identity_id` string, nullable
    - `wallet_count` integer: members + 1 (the asked wallet).
    - `anchor` string, nullable
    - `self` object, nullable
      - `role` string
      - `confidence` 'confirmed' | 'strong' | 'probable'
      - `path_len` integer
      - `best_evidence_class` string, nullable
      - `evidence_count` integer
      - `is_anchor` boolean
    - `members` object[]
      - `wallet` string
      - `role` string
      - `confidence` 'confirmed' | 'strong' | 'probable'
      - `path_len` integer
      - `best_evidence_class` string, nullable
      - `evidence_count` integer
      - `is_anchor` boolean
    - `related` object[]
      - `wallet` string
      - `evidence_class` string
      - `strength` 'context'
      - `basis` string
    - `evidence` object[]
      - `wallet_a` string
      - `wallet_b` string
      - `evidence_class` string
      - `direction` 'a_to_b' | 'symmetric'
      - `observed_at` string, date-time
      - `time_basis` 'chain' | 'ingest' | 'chain_or_ingest'
      - `tx_ids` string[]
      - `token_mint` string, nullable
      - `strength` 'confirmed' | 'strong' | 'probable' | 'context'
      - `basis` string
      - `rule_version` string
    - `builder` object
      - `run_id` integer
      - `built_at` string, date-time
      - `age_seconds` integer
      - `stale_after_seconds` integer
      - `hub_floor` integer, nullable
    - `disclaimer` string
    - `coverage_note` string

## Other responses

- `400`: Invalid wallet, limit below 1, unknown event type, malformed cursor, a cursor outside the effective window, or a malformed / future `since`
- `401`: Missing or invalid API key, or an expired free-tier key. Authentication-stage error: no `X-RateLimit-*` headers, no `_rid`.
- `403`: Forbidden. One of: the key's tier is below this endpoint's or parameter's gate (`tier_required` with an `upgrade` block); the public demo key used outside its allow-list (`demo_key_endpoint_not_allowed`); an invalid or revoked key; an origin-restricted key called from a disallowed origin (`code` `origin_not_allowed` / `origin_required`). `X-RateLimit-*` headers are present only on `tier_required`.
- `429`: Too many requests. Every 429 carries `Retry-After`. A quota 429 (`rate_limit_exceeded`, with `X-RateLimit-*`), a heavy-query concurrency 429 (`error_kind` `concurrency`/`capacity`), or the per-IP authentication-failure block (30 failed auths/min; plain `error` + `retry_after_seconds`, no `X-RateLimit-*`).
- `500`: Unexpected server error from the route (`Internal server error`, with `_rid`). Safe to retry with backoff. A failed API-key lookup is a 503 `auth_backend_unavailable`, never a 500.
- `503`: `code: feature_disabled` when the production capability is deliberately disabled/rolled back; no data keys and never a false empty result.

---

[API](https://skmtc.dev/madeonsol/apis/madeonsol-api.md) · [All operations](https://skmtc.dev/madeonsol/apis/madeonsol-api/llms.txt) · [OpenAPI document](https://skmtc.dev/madeonsol/apis/madeonsol-api/revisions/96ce84657f55?raw)
