Primary Route Files
/server/routes/auth.ts/server/routes/deals.ts/server/routes/contacts.ts/server/routes/tasks.ts/server/routes/teams.ts/server/routes/public.ts/server/routes/screenshots.ts/server/routes/shortener.ts/server/routes/shortener-v1.ts/server/routes/agent.ts/server/routes/agent-oauth.ts/server/routes/agent-readiness.ts/server/routes/settings.ts/server/routes/ai-schema.ts
Mounted Families
GET/POST/... /api/auth/*GET/POST/... /api/deals/*GET/POST/... /api/contacts/*GET/POST/... /api/tasks/*GET/POST/... /api/teams/*GET /api/public/*(public-facing)GET/POST /api/screenshots/*(auth protected)GET/POST /api/shorten/*andGET /r/*GET/POST/... /api/shortener/v1/*(standalone AI-agent shortener)GET/POST/... /api/agent/*(provider-neutral MCP bridge, including read-only templates under/api/agent/templates/*)POST /api/agent/oauth/register|device_authorization|tokenGET /.well-known/*,GET /openapi.json, andGET /docs/api(public agent discovery)GET/PUT /api/settingsandGET /api/settings/agent-connectionGET /api/ai/schema|entities|actions
Agent Discovery Surface
DealDash publishes machine-readable agent discovery before static SPA fallback so unknown well-known URLs return real 404s instead of the app shell.GET /.well-known/api-catalog:application/linkset+json, points agents to OpenAPI docs, health, OAuth metadata, MCP server card, and Agent Skills.GET /openapi.json: generated OpenAPI 3.1 description for the public agent route family and OAuth bootstrap routes.GET /docs/api: redirects tohttps://docs.drdj.me/backend/api-surface.GET /.well-known/oauth-authorization-server: OAuth Authorization Server Metadata for public agent clients.GET /.well-known/openid-configuration: compatibility alias that mirrors the OAuth metadata and notes that DealDash does not issue ID tokens.GET /.well-known/oauth-protected-resource: OAuth Protected Resource metadata for/api/agent.GET /.well-known/jwks.json: empty JWKS because agent access tokens are opaque and server-validated.GET /.well-known/mcp/server-card.json: MCP server card for the DealDash Agent Bridge.GET /.well-known/mcp/drdj-shortener/server-card.json: shortener-only MCP server card.GET /.well-known/agent-card.json: A2A Agent Card advertising the existing DealDash Agent Bridge as an authenticated HTTPS JSON agent interface.GET /.well-known/agent-skills/index.json: Agent Skills index with a SHA-256 digest.GET /.well-known/agent-skills/dealdash-agent-bridge/SKILL.md: public skill instructions for agents.GET /.well-known/agent-skills/drdj-shortener/SKILL.md: standalone shortener skill for one-call drdj.me link creation.GET /.well-known/http-message-signatures-directory: Web Bot Auth key directory. It returns an empty JWKS unless production Ed25519 key material is configured withWEB_BOT_AUTH_PUBLIC_JWK_JSONorWEB_BOT_AUTH_JWKS_JSON; whenWEB_BOT_AUTH_PRIVATE_KEY_PEMorWEB_BOT_AUTH_PRIVATE_KEY_BASE64is present, the response is signed with HTTP Message Signatures.
Link: </.well-known/api-catalog>; rel="api-catalog"; type="application/linkset+json"Link: </docs/api>; rel="service-doc"Link: </openapi.json>; rel="service-desc"; type="application/openapi+json"Content-Signal: ai-train=no, search=yes, ai-input=yes
Accept: text/markdown content negotiation and
return Content-Type: text/markdown; charset=utf-8 plus Vary: Accept.
DealDash does not expose agent-commerce protocols by default. x402, MPP, UCP,
ACP, and AP2 should be added only when DealDash has a real payable API or
checkout surface to advertise.
Agent Bridge Contract
/api/agent/* is the canonical backend surface for MCP-capable agents. It is shared by Claude Code, OpenAI/Codex or ChatGPT MCP clients, OpenClaw adapters, and future agent hosts.
GET /api/agent/schemareturns the tool-family schema and approval tiers.- Login-link auth starts with
POST /api/agent/auth/start; the user opens/agent/authorize/:requestId; the agent pollsGET /api/agent/auth/status/:requestId?deviceCode=.... - Public OAuth clients register with
POST /api/agent/oauth/register, start device authorization withPOST /api/agent/oauth/device_authorization, and exchange approved device codes withPOST /api/agent/oauth/token. - Login-link status may report
connectionState: "token_already_claimed"in MCP output when a previous agent process already claimed the token. Agents should start a fresh approval link for the current session instead of claiming they are connected. - Tool calls authenticate with
Authorization: Bearer <DEALDASH_AGENT_ACCESS_TOKEN>for login-link tokens orAuthorization: Bearer <DEALDASH_AGENT_SERVICE_SECRET>for operator-managed adapters. - Unauthenticated
/api/agent/*responses includeWWW-Authenticate: Bearer resource_metadata="https://dealdash.neonoir.ai/.well-known/oauth-protected-resource". - Login approval links prefer
APP_ORIGIN;RENDER_EXTERNAL_URLandSHORT_LINK_DOMAINare fallback origins only. - Agents without MCP installed may start login-link auth directly by posting to
https://dealdash.neonoir.ai/api/agent/auth/start; normal setup does not require service secrets, default user IDs, or deployment provider keys. - Validate MCP setup with
pnpm agent:mcp-install:check --jsonbefore copying install instructions. The check also verifies any installed local Codex plugin cache mirrors the repo bundle solinkshot_evidenceremains available to agents. - Tool calls require
x-dd-request-id. Operator-managed service-secret auth also requiresx-dd-acting-user-id;x-dd-channelandx-dd-actor-ididentify the adapter. - Agent-routed deal create/update calls use the same persisted deal routes as the dashboard. Successful writes leave the normal domain activity row with payload-safe agent metadata (
agentSource, request id, actor id, channel, operation, approval tier, and approval id) and a separate payload-safeagent_tool_callrow with request metadata plus response-derived deal IDs, deal name, promo code, status, and LinkShot bulk-import summary IDs/counts when available. Agent-routed screenshot reserve/upload/link writes add payload-safe proof handles such asscreenshotId,shortId,dealId,videoId,sourceUrl,platform,detectedViews,pending, anduploaded, without logging raw image data, storage paths, public image URLs, or renderedshortUrl/directUrlvalues. - Repo-local MCP tool calls return successful object payloads both as
structuredContentand as serialized JSON text for backward compatibility. MCP error results useisError: truewith safe JSON text and must not echo authorization headers, service secrets, image data, or stored login tokens. - Sensitive writes require
x-dd-approval-idby default. DEALDASH_AGENT_WRITE_CONFIRMATION_MODE=allow_non_delete_writesallows non-delete Tier 2 writes to run without approval; delete operations always require approval.- Approval confirmation is restricted to trusted adapters with
x-dd-approval-confirm-secret. - OpenClaw policy belongs in channel adapters; the backend remains provider-neutral.
dealdash.read dealdash.write.low_risk dealdash.memory; existing already-issued
tokens with no stored scope remain legacy-compatible. dealdash.read authorizes
read routes, dealdash.write.low_risk authorizes Tier 1 operational writes,
and dealdash.write.sensitive or mcp is required for sensitive routes before
the existing approval gate is considered. The approval page displays the stored
request snapshot: client name, client URL, requested scopes, expiration, and a
full-bridge warning when mcp is requested.
The public GET /api/agent/schema contract also advertises the default scope,
supported scopes, metadata endpoints, and route-scope policy so agent clients do
not need to infer authorization behavior from prose docs.
Allowlisted V1 families are short links, screenshots, deals, payments, tasks, contacts, influencers, activity, suggestions, templates, context, memory, and approvals. Admin/auth/team, runtime/filesystem, and bulk destructive tools are excluded.
Standalone AI Shortener
/api/shortener/v1/* is the tiny drdj.me shortener surface for agents that only need URL or photo short links.
GET /api/shortener/v1/health: public health + discovery hints for agents (no login).POST /api/shortener/v1/links: creates guest URL links without auth, or registered-agent links with customization and ownership.POST /api/shortener/v1/photos: registered-agent-only photo-to-short-link upload.GET /api/shortener/v1/links/:shortId: minimal public-safe metadata, with private fields returned only to the owner agent withshortener.links:read.GET /api/shortener/v1/links/:shortId/stats/public: public-safe stats for guest/public links only.GET /api/shortener/v1/links/:shortId/stats: private stats for the owner agent.POST /api/shortener/v1/agent/register|device_authorization|token: shortener-scoped agent registration and approval.GET /api/shortener/v1/agentsandGET /api/shortener/v1/settings: authenticated DealDash dashboard control-plane data.
drdj-shortener skill or /plugins/drdj-shortener MCP server when an agent only needs short links. Use the full DealDash Agent Bridge for CRM, deals, contacts, payments, tasks, broad screenshots, LinkShot view checks, context, memory, and approvals.
Registered shortener calls require exact shortener.* scopes. Broad bridge scopes such as mcp or dealdash.read do not authorize standalone shortener actions.
Shortener Examples
Guest URL create:invalid_target_url: target URL is malformed, private, local, or uses an unsafe scheme.reserved_slug: custom slug collides with app routes or reserved words.auth_required_for_customization: guest callers attempted custom slug, campaign, tags, private stats, or photo upload.rate_limited: guest create budget exceeded.shortener_scope_not_authorized: registered agent token is missing the requiredshortener.*scope.not_found: link does not exist or caller cannot access private metadata.
/migrations/extend-shortener-for-ai-agents.sql before
routing real traffic to /api/shortener/v1/*.
Agent Context And Memory
These endpoints make existing DealDash data easier for MCP clients to find before they call narrower tools.GET /api/agent/context/resources: Tier 0 read that returns MCP resource hints such asdealdash://context/search,dealdash://linkshot/view-logs, anddealdash://memory/active.GET /api/agent/context/search: Tier 0 read across deals, screenshots, LinkShot view logs, short links, contacts, influencers, and active agent memory. Filters:q,scope,types,limit, andoffset.GET /api/agent/memory: Tier 0 read for human-visible account-scoped memories.POST /api/agent/memory: Tier 1 write to create a durable memory after user approval.PATCH /api/agent/memory/:id/archive: Tier 1 reversible write. Memory is archived, not hard-deleted.
agent_memories, are scoped by user_id, and include source fields, tags, confidence, actor/channel provenance, and status. This is the controlled memory layer. pgvector semantic search is the next upgrade after embedding generation and cost/retention rules are configured.
Agent Template Reads
These endpoints give agents first-class read access to reusable templates instead of forcing them to guess through context search.GET /api/agent/templates/message: Tier 0 read for message templates. Filters:tag,q,limit, andoffset.GET /api/agent/templates/message/latest: Tier 0 latest message template, optionally filtered bytag.GET /api/agent/templates/message/latest-story: Tier 0 latest message template taggedstory.GET /api/agent/templates/message/:id: Tier 0 read for one message template.GET /api/agent/templates/deal: Tier 0 read for reusable deal templates. Filters:q,limit, andoffset.GET /api/agent/templates/deal/latest: Tier 0 latest deal template.GET /api/agent/templates/deal/:id: Tier 0 read for one deal template.
LinkShot Data Visibility
The authenticated/screenshots page uses LinkShot data and adds review
surfaces for screenshots, due view checks, and view logs. LinkShot
bulk-import writes share the same /api/deals/bulk-import/process path across
the extension, website, and agent bridge so manual imports and agent imports
create view-check videos consistently.
Screenshots
GET /api/screenshots defaults to owned-only records.
Optional query:
scope=mine-and-shared: include screenshots owned by the signed-in user plus screenshots shared through active team membership.
Due Views
GET /api/deals/due-views keeps its default extension-compatible response.
Optional query:
scope=mine-and-shared: include owned deal videos plus authorized team-shared deal records.includeLogs=true: attach recent parsed LinkShot view-log context.includeScreenshots=true: attach authorized screenshot references and counts.
View Logs
GET /api/deals/view-logs lists LinkShot view checks. The authenticated
website can correct owned rows by using the existing
PATCH /api/deals/:dealId/views/:viewId route. Team-shared rows are editable
only when the current user is team owner/admin for the shared deal; ordinary
team-shared rows remain read-only.
PATCH/PUT /api/deals/:dealId/views/:viewId validates update payloads before
mutation. value must be a finite non-negative integer, checkedAt must be a
valid date when supplied, sourceUrl must be a bounded valid URL or null,
note is bounded, and unknown fields are rejected with 400 VALIDATION_ERROR.
Supported filters:
scopedealIdvideoIdlogIdfromtoqlimitoffset
copyText in the LinkShot extension completed-copy format. The response also includes copyText, copyTextScope: "returned_logs", and copyTextFormat: "linkshot-extension-completed-copy-v1" for the returned page/filter. Agents can use logId to fetch and copy one exact view-log row; website deep links with tab=logs&logId=... open that row and select it for copying. If the operator clears the focused selection, refreshes do not reselect it unless the URL focuses a different logId. Date-only from and to filters cover full checked days, so to=2026-04-10 includes logs checked later on April 10. Screenshot previews are returned only when the current user owns the screenshot or has an explicit screenshot share; otherwise the row reports a redacted attachment reference.
Bulk View-Check Imports
POST /api/deals/bulk-import/process adds LinkShot view-check videos from pasted URL groups.
Request body:
postDate: required date for the video post.collections: optional array of URL groups. Each group hasurls, optionalpromoCode, optionalname, and optional deal details (price,viewsTarget,promoLink,contact, andnotes, either at the group level or insidedealDetails).linksText: optional pasted text. Blank lines separate people/groups.
- Matched owned active deals receive new
deal_videosrows. - Unmatched groups without promo codes are returned in
needsPromoCodewithnextAction.retryParams, required fields, optional fields, and an agent prompt for collecting the missing deal details. - Groups with promo codes reuse an owned active deal by promo code when possible; otherwise an active owned deal is created with the supplied optional details and the video is added. The promo code identifies the target deal, so DealDash does not silently fall back to a different URL-matched deal.
- Team-shared deal matches remain read-only and are returned for promo-code review instead of being mutated.
POST /api/agent/deals/bulk-import/process exposes the same path as deals.bulk_add_view_checks. It is a Tier 1 logged operational write for adding LinkShot view-check videos and can run without approval. Agents should not use generic deals.create or deals.update for this workflow; when unmatched links return needsPromoCode, ask for the missing promo code plus any available deal details, then retry deals.bulk_add_view_checks with the supplied data.
Screenshot upload endpoints accept base64 raster images as PNG, JPEG/JPG, WebP, GIF, AVIF, or BMP. The default binary image limit is 40MB, with a 64MB JSON body limit for base64 request headroom. SCREENSHOT_MAX_IMAGE_BYTES, DEALDASH_AGENT_MAX_IMAGE_BYTES, and API_JSON_BODY_LIMIT can raise or lower limits per deployment. SVG, HEIC, and TIFF should be converted by clients or messaging adapters before upload.
External Shares
POST /api/shares/external and PUT /api/shares/external/:id validate
payloads before ownership checks and database writes. entityType is limited to
deal, contact, or influencer; entityId must be a UUID; expiresAt must
be a valid date or null; maxViews must be a positive bounded integer or null;
visibleFields must be a bounded string array or boolean map; isActive must
be boolean; and password strings must be sane length when present. Invalid
payloads return 400 VALIDATION_ERROR; ownership checks remain unchanged.
Agent Bridge
/api/agent/deals/view-logs exposes the same read-only data and copy-text
contract as a Tier 0 deals.view_logs operation for MCP-capable agents. Agent
calls use either the login-link access token or an internal operator-managed
service secret, and the backend applies the same user/team visibility rules as
the website.
The MCP linkshot_evidence tool is a read-only proof-normalization layer for
searched or captured video evidence. Use plan_video_search, follow the
returned requestReadiness and browserSearchTargets, fill
rankingInputTemplate for each raw candidate, call
audit_browser_candidate_intake before ranking, call
extract_transcript_cues when transcript/caption/first-comment text is
available, then call rank_search_results or rank_candidates, then call
plan_proof_capture to produce explicit screenshot jobs, then pass current
captures as proofScreenshots, then call plan_direct_proof_review before
claiming confirmation, then call workflow_report.
requestReadiness uses linkshot-grillme-request-readiness-v1 to block
under-specified /grillme browser/search handoffs until the known date plus a
promo/query/account anchor are explicit, and it returns missing fields, the
operator question, ready command templates, and the no-write boundary.
Transcript/caption matches are ranking and navigation evidence only; persistent
view-log writes require direct 1xBet logo or spoken promo proof, source video
URL, screenshot id/share URL, view count, and observedPromoAtSeconds. The mock
validation commands are pnpm agent:smoke:linkshot-workflow --mock --json for
the MCP evidence chain and pnpm agent:smoke:linkshot-browser --mock --json for
browser-visible candidate extraction into that chain. Use
the final MCP report/readiness actions’ top-level verificationRows and
verificationLinks for machine-readable operator handoff because they keep each
source video URL beside its screenshot id/link and write-gate state without
requiring agents to parse Markdown report text. Use
pnpm agent:preflight:linkshot-live --mock --json to validate the no-write live
preflight shell. Add --from-due-views when the agent should seed candidate
URLs from read-only deals.due_views context instead of requiring a pasted
--url, or run it with explicit --url, --requested-date, and --promo-code
values to inspect real platform pages without screenshots, uploads, short
links, platform search, or persistent view-log writes. The
preflight returns proofCapturePlan.jobs for the next screenshot handoff while
keeping liveWrites and proofCapture false.
Separately, the default pnpm agent:readiness:check --json gate also runs
pnpm agent:native-automation:check --json and
pnpm agent:smoke:primitives --mock --json. The native automation catalog emits
nativeAutomationFormat: dealdash-native-automation-catalog-v1, verifies the
DJA-130 native/local replacement paths for MCP install, action coverage,
bounded collection, preflight, proof rehearsal, historical inventory, direct
HTTPS fallback, GBrain-safe context, setup-kit parity, and DB audit coverage,
and keeps liveWrites=false plus persistentViewLogWrites=false. It also
checks the Apify policy remains documented: native/local first, exact
Actor/resource verification before any Apify use, no invented actor names, and
escalation after one blocked retry. The primitive JSON contract must expose
each core capability separately: contextSearch, dueViews, viewLogs,
urlShortLink, imageUploadShortLink, screenshotCapture, and a three-row
verificationLinks set. This keeps the source URL, returned short link,
uploaded image short link, and specified screenshot capture proof visible before
a larger /grillme search can claim readiness.
Add --from-plan-targets --discover-candidates only when
plan_video_search.browserSearchTargets includes a URL-bearing account_page
target. The preflight reports planTargetSeed, opens only supplied URLs plus
planned account-page URLs, and does not run broad platform/web search.
Add --discover-candidates only when the supplied URLs are explicit
account/search pages to inspect for linked video cards; discovery rows are
deduped by video URL and must still pass the same no-write intake, ranking,
proof-capture, and direct-proof review gates.
Add --enrich-discovered-candidates only when sparse discovered cards need a
bounded detail-page read. It opens discovered candidate URLs up to
--enrich-limit (default 5) to fill caption, first-comment, transcript,
view-count, and direct-proof fields, while keeping screenshots, short links, and
persistent view-log writes disabled.
Use pnpm agent:collect:linkshot-candidates --url <account-or-search-page> --requested-date YYYY-MM-DD --promo-code CODE --json
when a bounded browser/search agent needs to collect compact candidate rows from
supplied pages before the preflight. The collector blocks local/private targets
unless explicitly allowed, performs no screenshots, uploads, short links, or
persistent writes, and emits linkshot-candidate-json-v1 rows for
--candidate-json. Rows may include screenshotSelector, waitForSelector,
or captureClip hints so later proof capture can target the views card or a
known region. If a supplied account/search page has no linked video candidate,
the collector reports no candidate instead of treating the page as a source
video.
Detail-page extraction reads visible DOM first and then falls back to structured
video metadata from JSON-LD or known app-state/player JSON scripts for source
URL, account, title, caption/description, transcript, published date, video id,
and view count. When visible/structured transcript text is missing, it can read
standard caption/subtitle track files from DOM <track> tags or
app-state/player JSON such as YouTube timed-text captionTracks, and mark
candidates with transcriptSource: caption_track, track URL, kind, label,
language, and track source. Structured and caption-track transcript cues remain
navigation-only.
With explicit --capture-proof, the command consumes those jobs, captures proof
through screenshots.capture_url, and passes the returned screenshot metadata
into workflow_report as proofScreenshots. This mode may create screenshot
proof records and short screenshot links, but it keeps
persistentViewLogWrites: false. Per-candidate screenshotSelector,
waitForSelector, and captureClip hints from imported or extracted rows are
preserved on matching proof-capture jobs as candidateCaptureHint; an explicit
CLI --selector still overrides selector choice at capture time. If the
screenshot capture response omits sourceUrl, the preflight carries forward the
source video URL from the capture job/params before building verification rows.
The CI-stable proof-capture handoff rehearsal is
pnpm agent:readiness:check --only proof_capture_rehearsal --json. It imports
compact candidate rows through --candidate-json, captures one proof screenshot
in mock mode, matches workflow_report rows, reports
directProofReviewPlan, keeps source video links beside screenshot links, and
still leaves persistent view-log writes disabled. Use
pnpm agent:preflight:linkshot-live --mock --discover-candidates --enrich-discovered-candidates --capture-proof --capture-limit 1 --json
only when the environment has Playwright browsers installed and the operator
also needs to exercise supplied page discovery plus capped detail enrichment
before capture.
The preflight also exposes verificationRowsFormat: linkshot-live-preflight-verification-row-v1 and top-level verificationRows
so agents can present each source video URL beside its screenshot id/link, view
count/source, direct-proof status, direct-proof review status, suggested seek
seconds, review window seconds, no-write reason, missing write requirements, and
row-level verification links without parsing nested report text.
Use
pnpm agent:preflight:linkshot-live --mock --from-plan-targets --discover-candidates --json
to validate planned account-page discovery without broad search or writes.
Use
pnpm agent:preflight:linkshot-live --mock --mock-structured-metadata --json
to validate structured metadata fallback extraction without screenshots, short
links, or view-log writes.
Use
pnpm agent:preflight:linkshot-live --mock --mock-caption-track --json
to validate caption/subtitle track cue extraction without screenshots, short
links, or view-log writes.
Use
pnpm agent:preflight:linkshot-live --mock --mock-app-state-caption-track --json
to validate app-state/player JSON caption-track extraction without screenshots,
short links, or view-log writes.
The default pnpm agent:readiness:check --json gate runs both focused
browserless caption-track preflights; use
pnpm agent:readiness:check --only preflight_caption_track,preflight_app_state_caption_track --json
when validating transcript cue handling alone. These checks import
deterministic caption-track candidate fixtures instead of launching Playwright,
must keep persistentViewLogWrites and proofCapture false, and summarize
transcript cue counts without treating the cue as direct proof. The raw
--mock-caption-track and --mock-app-state-caption-track commands remain the
browser-backed extraction checks for runners with Playwright browsers installed.
The repo-local pnpm agent:inventory:linkshot-screenshots command is the
metadata-only inventory shell for historical screenshot examples. The default
readiness gate runs
pnpm agent:inventory:linkshot-screenshots --mock --include-view-logs --date 2026-04-10 --json
so dated history selection, metadata-only output, verificationRows, and
linkshot-extension-completed-copy-v1 copy text stay covered by the main
/grillme health check.
See LinkShot Extension for the website
quick view and DealDash Agent Bridge Plugin
for MCP usage.
Agent Connection Settings
GET /api/settings/agent-connection is an authenticated, read-only Settings endpoint for Bring Your Own Agent setup. It returns safe status, the single DealDash Agent Bridge model, MCP setup instructions, direct HTTPS fallback endpoints, permission tiers, tool groups, future AI feature slots, and recent agent_tool_call logs scoped to the current user.
The safe setup payload includes a human guide URL, the private DealDash Agent Kit repo URL for authorized install/examples only, an agent-optimized docs URL, the MCP command/config path, and direct /api/agent/* fallback URLs. Public and browser-visible responses expose names and links only, never secret values.
The endpoint returns env names and boolean configuration flags only. It must not expose service secret values, approval confirmation secret values, raw request payloads, image data, payment payloads, or cross-account logs.
The payload includes writePolicy.mode, nonDeleteWritesRequireApproval, and deleteWritesAlwaysRequireApproval so agents and users can see whether write tools can run without repeated confirmation. Deletes must remain approval-gated in every mode.
Validation Rule
When changing any route family:- run targeted integration tests
- run
pnpm check - update docs for endpoint behavior changes
- include risk note for auth/public exposure changes