# Sniper Module — Finradar API > Version: 3.61.0 | Generated: 2026-06-20 | Content Hash: dcb3cf20 > Fetch this file at: https://uat.finradarapi.com/llms/sniper-module.txt ## Authentication All endpoints require an API key. Pass it via query parameter `?apiKey=YOUR_KEY` or header `X-API-Key: YOUR_KEY`. WebSocket endpoints accept the key in the `token` auth payload or query parameter. --- ## Sniper Module High-level API for scheduling and managing automated filing detections. ### POST /api/v1/sniper/targets Create a new Sniper Target. **Token cost:** 0 (EXEMPT — auth / billing / account / admin / health) **Response fields:** - `target_id` (string): Unique target identifier (format: `tgt_`). Pass to [POST /api/v1/sniper/targets/{target_id}/stop](/docs/sniper/sniper-module/post-sniper-targets-target-id-stop) for early cancellation, or to [GET /api/v1/sniper/targets](/docs/sniper/sniper-module/get-sniper-targets) when paginating. - `ticker` (string): Echoed canonical hyphen-form ticker. - `status` (string): Lifecycle state — `CREATED` (target stored but `start_time` is in the future), `ACTIVE` (currently monitoring; this is the typical immediate-creation state), `STOPPED` (terminal — window expired, manual stop, or filing-hit fired). - `start_time` (string): ISO 8601 UTC start of the monitoring window. Either explicitly provided or set to creation time. - `end_time` (string): ISO 8601 UTC end of the monitoring window. Computed from `start_time + duration_minutes` when `duration_minutes` was provided. - `form_types` (array (nullable)): Echoed form-type filter array. Null when no filter was provided (fires on ANY new filing). - `webhook_url` (string (nullable)): Echoed webhook URL — either the explicit per-target URL or the account-level default. Null when no webhook is configured (the sniper still fires WS push but skips HTTP webhook). - `created_at` (string): ISO 8601 UTC creation timestamp (server-side). - `filing_uuid` (string (nullable)): Foreign key to `filings.uuid` once the hit has been parsed and ingested. Null until the 13F parse pipeline reaches the `parsed` or later `processing_state`. - `processing_state` (string (nullable)): Parse-pipeline stage, orthogonal to `status`. One of: `detected` (filing URL captured, parse queued), `parsing` (parser running), `parsed` (holdings extracted), `enriched` (OpenFIGI ticker enrichment complete), `no_holdings` (13F-NT or empty holdings table), `parse_failed` (parse error; sniper falls back to bare filing-URL notification). Null until the sniper has fired at least one hit. - `holdings_count` (integer (nullable)): Number of holdings rows extracted from `form_13f_holdings` when `processing_state` is `parsed` or later. Null when parse has not completed or the filing carries no holdings table (13F-NT). - `parsed_at` (string (nullable)): ISO 8601 UTC timestamp when the 13F parse pipeline completed (`processing_state` transitioned to `parsed`). Null until parse completes. - `enriched_at` (string (nullable)): ISO 8601 UTC timestamp when OpenFIGI ticker enrichment completed (`processing_state` transitioned to `enriched`). Null until enrichment completes or if enrichment is skipped. - `candidate_urls` (array (nullable)): Range-scan window of predicted filing URLs assembled at target creation time — array of `{ accession: string, url: string }` objects. Lets clients pre-render expected filing links before the sniper actually fires. Null when no range-scan was performed. **Since:** v1.0.0 **Utility:** Schedule a monitoring job for a specific ticker — the Sniper module fires WS push notifications + webhook callbacks the moment a matching SEC filing arrives for the ticker during the active window. Used for time-bounded high-conviction monitoring (e.g. 'watch TSLA for 10-K release tonight') rather than long-running watchlist subscriptions. Each target moves through a 3-state lifecycle: `CREATED` (target stored, not yet active) -> `ACTIVE` (within `start_time .. end_time` window, monitoring) -> `STOPPED` (window expired, manual stop, or filing-hit terminal). Pricing: `cost: 0` to create the target itself, but each TARGET COSTS A TIER PER ACTIVE PERIOD against the customer's plan — see the per-tier sniper allowance in the Account section. **Use case:** Setting up an automated buy trigger for TSLA immediately upon 10-K release — customer creates a sniper target with `ticker=TSLA`, `duration_minutes=120` to cover the expected after-market filing window. When the 10-K filing hits SEC EDGAR, the Sniper fires (a) a WS push to active connections, (b) an HTTP POST to the customer's configured webhook URL (see [Webhooks > POST {your_webhook_url}](/docs/webhooks/webhooks/post-webhook-url)). Also useful for activist-tracker workflows ('watch ULTA for 13D/G release in next 5 trading days'). **Parameters:** - `ticker` (body, required): Canonical hyphen-form ticker (e.g. `BRK-A` not `BRK.A`). Server applies the v3.14.2 ticker-normalization shim. Returns 400 when the ticker is unknown to the catalog (run [GET /api/v1/cusip/ticker/{ticker}](/docs/reference-data/cusip-api/get-cusip-ticker) to verify before creating the target). - `duration_minutes` (body, optional, default: 60): How long to monitor (1-1440). When `start_time` and `end_time` are both omitted, the target activates IMMEDIATELY and runs for `duration_minutes` from creation. When `start_time` is provided, runs from `start_time` for `duration_minutes`. Mutually exclusive with `end_time` (provide either `duration_minutes` OR `end_time`, not both). - `start_time` (body, optional): ISO 8601 UTC start time. Omit for immediate activation. Useful for scheduling monitoring of upcoming earnings windows (e.g. `start_time=2026-04-30T20:00:00Z` for an after-market AAPL 10-Q expected at 8pm UTC). - `end_time` (body, optional): ISO 8601 UTC end time. Mutually exclusive with `duration_minutes`. Server returns 400 when both are provided. Maximum window is 24 hours from `start_time`. - `form_types` (body, optional): Optional array of SEC form types to filter on. Omit to fire on ANY new filing for the ticker; provide to restrict (e.g. `["10-K", "10-Q"]` for earnings-only). - `webhook_url` (body, optional): Optional customer webhook URL to POST the event payload to when the sniper fires. Falls back to the customer's account-level default webhook URL if omitted (configured under `/account/settings/webhooks`). **Sample response:** ```json { "target_id": "tgt_abc123def456", "ticker": "TSLA", "status": "ACTIVE", "start_time": "2026-05-02T20:00:00Z", "end_time": "2026-05-02T22:00:00Z", "form_types": [ "10-K", "10-Q", "8-K" ], "webhook_url": "https://customer.example.com/sniper-callback", "created_at": "2026-05-02T19:58:42Z", "filing_uuid": null, "processing_state": null, "holdings_count": null, "parsed_at": null, "enriched_at": null, "candidate_urls": null } ``` ### GET /api/v1/sniper/targets List all active and past targets. **Token cost:** 0 (EXEMPT — auth / billing / account / admin / health) **Response fields:** - `targets` (array): Array of sniper target rows owned by the authenticated user. Order: by `created_at DESC` (newest first). Empty array on users who have never created a sniper. - `targets[].target_id` (string): Unique target identifier (format: `tgt_`). - `targets[].ticker` (string): Canonical hyphen-form ticker. - `targets[].status` (string): Lifecycle state — `CREATED` / `ACTIVE` / `STOPPED`. - `targets[].start_time` (string): ISO 8601 UTC start of monitoring window. - `targets[].end_time` (string): ISO 8601 UTC end of monitoring window. - `targets[].form_types` (array (nullable)): Form-type filter array (null = fires on any filing). - `targets[].webhook_url` (string (nullable)): Webhook URL configured for this target. Null when no webhook is configured. - `targets[].resolution_reason` (string (nullable)): Terminal-state resolution — `window_expired` / `manual_stop` / `filing_hit`. Null while target is `CREATED` or `ACTIVE`. - `targets[].last_event` (object (nullable)): Most-recent matching SEC filing event for this target — `{ accession_number: string, form_type: string, filed_at: string }` for `filing_hit` resolutions, null otherwise. - `targets[].created_at` (string): ISO 8601 UTC creation timestamp. - `targets[].filing_uuid` (string (nullable)): Foreign key to `filings.uuid` once the hit has been parsed and ingested. Null until the 13F parse pipeline reaches the `parsed` or later `processing_state`. - `targets[].processing_state` (string (nullable)): Parse-pipeline stage, orthogonal to `status`. One of: `detected` (filing URL captured, parse queued), `parsing` (parser running), `parsed` (holdings extracted), `enriched` (OpenFIGI ticker enrichment complete), `no_holdings` (13F-NT or empty holdings table), `parse_failed` (parse error; sniper falls back to bare filing-URL notification). Null until the sniper has fired at least one hit. - `targets[].holdings_count` (integer (nullable)): Number of holdings rows extracted from `form_13f_holdings` when `processing_state` is `parsed` or later. Null when parse has not completed or the filing carries no holdings table (13F-NT). - `targets[].parsed_at` (string (nullable)): ISO 8601 UTC timestamp when the 13F parse pipeline completed (`processing_state` transitioned to `parsed`). Null until parse completes. - `targets[].enriched_at` (string (nullable)): ISO 8601 UTC timestamp when OpenFIGI ticker enrichment completed (`processing_state` transitioned to `enriched`). Null until enrichment completes or if enrichment is skipped. - `targets[].candidate_urls` (array (nullable)): Range-scan window of predicted filing URLs assembled at target creation time — array of `{ accession: string, url: string }` objects. Lets clients pre-render expected filing links before the sniper actually fires. Null when no range-scan was performed. - `meta` (object): Pagination + summary block: `{ total: integer, limit: integer, offset: integer, active_count: integer, slots_available: integer }`. `slots_available` shows the user's remaining plan-allocated sniper budget (5 - active_count for Paid tier, 0 for Free tier). **Since:** v1.0.0 **Utility:** List all sniper targets owned by the authenticated user — active (`status=ACTIVE`), pending (`status=CREATED`), and historical (`status=STOPPED`). The natural backend for a sniper-management dashboard. Filter by status to surface only currently-active monitoring jobs, or list all for an audit trail. Each target row includes lifecycle metadata (status / start / end times), the configured `form_types` filter, the webhook URL, and — for STOPPED targets — the resolution_reason (`window_expired` / `manual_stop` / `filing_hit`) and any associated `last_event` payload summary. **Use case:** Displaying a dashboard of ongoing monitoring tasks — show the user their currently-active snipers, snipers scheduled to start soon, and recently-stopped snipers with their resolution outcomes. Also useful for SLA audits ('did the sniper for our TSLA earnings target fire correctly?') and for plan-budget visibility ('how many of my 5 paid-tier sniper slots are currently active?'). **Parameters:** - `status` (query, optional): Filter by lifecycle state — `CREATED` (pending future start) / `ACTIVE` (currently monitoring) / `STOPPED` (terminal). Omit for all states. - `ticker` (query, optional): Filter by ticker (canonical hyphen form). Useful for 'show me all snipers I've ever created on AAPL' history queries. - `limit` (query, optional, default: 50): Max targets returned (1-200). - `offset` (query, optional, default: 0): Pagination offset for chunked retrieval. **Sample response:** ```json { "targets": [ { "target_id": "tgt_abc123def456", "ticker": "TSLA", "status": "ACTIVE", "start_time": "2026-05-02T20:00:00Z", "end_time": "2026-05-02T22:00:00Z", "form_types": [ "10-K", "10-Q", "8-K" ], "webhook_url": "https://customer.example.com/sniper-callback", "resolution_reason": null, "last_event": null, "created_at": "2026-05-02T19:58:42Z", "filing_uuid": null, "processing_state": "detected", "holdings_count": null, "parsed_at": null, "enriched_at": null, "candidate_urls": [ { "accession": "0000320193-26-000101", "url": "https://www.sec.gov/Archives/edgar/data/320193/000032019326000101/0000320193-26-000101-index.htm" } ] }, { "target_id": "tgt_xyz789uvw012", "ticker": "AAPL", "status": "STOPPED", "start_time": "2026-05-01T20:00:00Z", "end_time": "2026-05-01T22:00:00Z", "form_types": [ "10-Q" ], "webhook_url": "https://customer.example.com/sniper-callback", "resolution_reason": "filing_hit", "last_event": { "accession_number": "0000320193-26-000064", "form_type": "10-Q", "filed_at": "2026-05-01T20:14:32Z" }, "created_at": "2026-05-01T19:30:00Z", "filing_uuid": "f3a1bc82-7d4e-4c12-9e5f-2a8b6d3c10f7", "processing_state": "enriched", "holdings_count": 284, "parsed_at": "2026-05-01T20:16:04Z", "enriched_at": "2026-05-01T20:17:31Z", "candidate_urls": null } ], "meta": { "total": 2, "limit": 50, "offset": 0, "active_count": 1, "slots_available": 4 } } ``` ### POST /api/v1/sniper/targets/{target_id}/stop Stop an active sniper target. **Token cost:** 0 (EXEMPT — auth / billing / account / admin / health) **Response fields:** - `target_id` (string): Echoed target identifier. - `ticker` (string): Echoed canonical hyphen-form ticker. - `status` (string): Always `STOPPED` after this call (terminal state). - `resolution_reason` (string): Always `manual_stop` for stop calls (vs `window_expired` for natural-end stops or `filing_hit` for filing-fired stops). - `stopped_at` (string): ISO 8601 UTC timestamp of the stop event (server-side). - `slots_available` (integer): Updated remaining plan-allocated sniper-slot budget after the stop. Useful for refreshing the 'X of 5 slots used' indicator in the UI immediately on stop response. **Since:** v1.0.0 **Utility:** Cancel an active or pending sniper target — moves the target to terminal `STOPPED` state with `resolution_reason='manual_stop'`. Frees the plan-allocated sniper slot for another target. Idempotent (calling stop on an already-STOPPED target returns 200 with the same body, NOT a 409 conflict). Use when (a) the customer has already manually traded the news, (b) the underlying trade thesis has changed, or (c) the customer needs to free a sniper slot for a higher-priority target. Server-side: cancels the underlying timer + queues, removes the target from the active-monitoring set, and (if `webhook_url` is configured) does NOT fire a stop notification to the webhook (stop events are not webhook-broadcasted). **Use case:** Stopping a sniper monitor early — common scenario: customer set up a TSLA earnings sniper for an after-market window, but TSLA pre-announced earlier and the customer manually traded the news. Stop the sniper to free the plan-allocated slot. Also useful in 'I created the wrong sniper' rollback flows ('I meant AAPL not AAPL.MX'). **Parameters:** - `target_id` (path, required): Target ID (format: `tgt_`). From [POST /api/v1/sniper/targets](/docs/sniper/sniper-module/post-sniper-targets) creation response or [GET /api/v1/sniper/targets](/docs/sniper/sniper-module/get-sniper-targets) listing. Returns 404 when the target_id is unknown OR is owned by a different user (no information leak about other users' targets). **Sample response:** ```json { "target_id": "tgt_abc123def456", "ticker": "TSLA", "status": "STOPPED", "resolution_reason": "manual_stop", "stopped_at": "2026-05-02T21:42:18Z", "slots_available": 5 } ```