TORQUEDocs

Data Sources

Register the user activity an incentive measures — custom events, on-chain program instructions, and Dune Analytics queries

Every recurring incentive is powered by a data source. Torque supports three kinds:

  • Custom Events — off-chain activity you send to Torque via the ingestion API (signups, social actions, purchases, game events).
  • IDL & On-Chain Programs — Solana Anchor IDLs uploaded for tracking specific program instructions.
  • Dune Event Sources — a saved Dune Analytics query registered as a daily-ingested event source.

Token activity (swap, bonding curve, hold) is already indexed and requires no registration — skip straight to the Query Builder.

Custom Events

Custom events let you track off-chain user activity and use that data to power incentives. An event is a reusable schema; ingested events accumulate in Torque and become queryable once at least one event has been received.

create_custom_event

Create a reusable custom event schema for off-chain activity. Event schemas are project-independent — this does not auto-attach the event to the active project; follow with attach_custom_event.

Requires: authentication

ParameterTypeRequiredDescription
eventNamestringYesUnique identifier for the event
namestringYesDisplay name
fieldsarrayYesField definitions (see below)
confirmedbooleanNoSet to true to execute. Omit to preview first.

Field schema:

PropertyTypeRequiredDescription
fieldNamestringYesField name
type"string" | "number" | "boolean"YesData type
labelstringNoDisplay label
descriptionstringNoField description

userPubkey (wallet address) is always a top-level property on ingested events — never part of the event schema you define here. Same for timestamp. Your custom fields go inside data.

list_custom_events

List custom events. Behavior depends on scope:

  • scope: "project" (default) — events attached to the active project (including events attached by other admins).
  • scope: "owned" — all events you own across every project, attached or not.

Requires: authentication (active project also required when scope: "project")

ParameterTypeRequiredDescription
scope"project" | "owned"NoDefault: "project"

Events must be ingested at least once before they become query-ready for generate_incentive_query. The list output shows whether each event has been ingested.

attach_custom_event

Attach an existing custom event to the active project so it can be used in incentives. Idempotent. Requires the caller to be a project admin; non-admins receive a 403.

Requires: authentication, active project

ParameterTypeRequiredDescription
customEventIdstringNoID of the event to attach. Omit to receive a pick list of events you own.

Use list_custom_events with scope: "owned" to find a customEventId, or create a new event with create_custom_event first.

API Keys

API keys are needed to send custom events to the Torque ingestion pipeline. Keys are user-scoped (not project-scoped) — one key works across every project you own.

list_api_keys

List your API keys. Keys are shown masked.

Requires: authentication

No parameters.

create_api_key

Create a new API key.

Requires: authentication

ParameterTypeRequiredDescription
namestringNoDisplay name. If omitted, the API generates a default.

The full key is shown once at creation and cannot be retrieved later. Copy it immediately.

Sending Events

Once you have an API key and an attached event schema, send events to the ingestion endpoint:

curl -X POST https://ingest.torque.so/events \
  -H "Content-Type: application/json" \
  -H "x-api-key: your-api-key" \
  -d '{
    "userPubkey": "<wallet address>",
    "timestamp": 1234567890000,
    "eventName": "your_event_name",
    "data": {
      "field1": "value",
      "field2": 123
    }
  }'

userPubkey and timestamp are required top-level properties on every event. Your custom fields go inside data.

IDL & On-Chain Programs

Upload a Solana Anchor IDL to track specific program instructions, then use them as data sources for incentives.

create_idl

Two-phase tool.

Phase 1 — preview (confirmed: false): parses the IDL file locally, lists available instructions with their field and account counts. Runs entirely on your machine — no authentication, no active project, no API call. Use this to inspect an IDL before committing.

Phase 2 — commit (confirmed: true): uploads the IDL and registers tracking for the instructions you select. Requires authentication and an active project.

Requires: preview — none; commit — authentication and active project.

ParameterTypeRequiredDescription
filePathstringNoAbsolute path to an Anchor IDL JSON file. Preferred for large files.
idlobjectNoFull Anchor IDL JSON content. Use filePath for large IDLs.
confirmedbooleanNofalse (default) for local preview; true to upload + register.
programAddressstringNoOverride the program address from the IDL's address field. Required if the IDL has no address field.
displayNamestringNoDisplay name for the program.
descriptionstringNoDescription of the program.
selectedInstructionsarrayNo (commit)Instructions to track. See shape below.

selectedInstructions shape:

[
  {
    "instructionName": "buy_exact_in",
    "fields": [
      { "fieldName": "amount_in", "type": "number" },
      { "fieldName": "config.feeRate", "type": "number" }
    ],
    "accounts": ["payer", "pool"]
  }
]

Each field is { fieldName, type, label?, description? }. Dot-path field names (e.g. config.feeRate) are supported.

Provide either filePath or idl, not both.

Uploading an IDL for a program address that already has one in the project returns a specific error — use create_instruction to add instructions to an existing IDL instead of re-uploading.

create_instruction

Add a single instruction to an already-uploaded IDL, without re-uploading the whole IDL. Instruction names must be unique within the IDL.

Requires: authentication, active project

ParameterTypeRequiredDescription
idlIdstringNoID of the existing IDL. Omit to receive a pick list.
instructionNamestringYesInstruction name from the IDL (e.g. buy_exact_in)
labelstringNoDisplay label (defaults to title-cased instruction name)
fieldsarrayYesFields to track (same shape as create_idl)
accountsstring[]YesAccount names to track

Use list_idls to find idlId, or call create_idl with confirmed: false against the IDL file to discover available instructions, fields, and accounts.

list_idls

List uploaded IDLs on the active project with their tracked instructions (program name, address, active/inactive status, and per-instruction field and account counts).

Requires: authentication, active project

No parameters.

Dune Event Sources

A Dune event source is a saved Dune query registered to run daily against Torque's ingestion pipeline. Each day's result set becomes available as an event source for generate_incentive_query.

Requires the Dune MCP installed alongside Torque MCP so the assistant can inspect the saved query and validate its shape before and after registration.

Query requirements

Before registering a Dune query, confirm:

  • The query is saved and non-temp (has a stable query id on Dune).
  • The query returns exactly one day of results per run.
  • The query is scoped by a single string parameter cast to DATE (e.g. {{date}}) so Torque can iterate daily ingestion.
  • The result set includes a column mapping to a Solana wallet address (used as userPubkey at ingestion time).

Preferred WHERE pattern on a date-partitioned table:

WHERE <date_partition_column> = TRY_CAST({{dateParamName}} AS DATE)

Fallback when only a timestamp column exists (half-open range):

WHERE <ts_column> >= TRY_CAST({{dateParamName}} AS TIMESTAMP)
  AND <ts_column> < TRY_CAST({{dateParamName}} AS TIMESTAMP) + INTERVAL '1' DAY

Do not use BETWEEN, sliding windows, - INTERVAL '1' DAY offsets, or hard-coded dates.

register_dune_event_source

Register a saved Dune query as a daily-ingested event source on the active project.

Requires: authentication, active project, Dune MCP installed

ParameterTypeRequiredDescription
duneQueryIdnumber (int, positive)YesDune query id (from the query URL, e.g. https://dune.com/queries/<id>)
queryNamestringYesHuman-friendly name for this Dune source
fieldsarrayYesTracked value fields (see shape below; at least one required)
userPubkeyFieldstringYesDune result column containing the user wallet address
eventTypeFieldstringYesDune result column containing the event type (buy/sell/swap/etc.). Required — drives the value_daily aggregation breakdowns
timestampFieldstringYesDune result column containing the event timestamp. For aggregated queries, fill with the date of aggregation
dateParamNamestringYesDune query parameter name for date scoping (e.g. date)
txHashFieldstring | nullNoTransaction hash column. Null only for queries that produce aggregated results
usdValueFieldstring | nullNoUSD value column. Null only to disable USD tracking
confirmedbooleanNoSet to true to execute. Omit to preview first.
acknowledgeIncompleteConfigbooleanNoRequired when txHashField or usdValueField is null. Assistants should warn the user before setting this — incomplete configs make query building harder.

fields shape:

[
  {
    "duneColumn": "volume_usd",
    "fieldName": "volume_usd",
    "type": "number"
  }
]
  • duneColumn — the column name returned by the Dune query.
  • fieldName — the tracked field name to store in Torque. Must match ^[a-z0-9_]+$ (lowercase alphanumeric + underscores).
  • type"number", "string", or "boolean".

The tool returns a duneEventQueryId (a Torque-side UUID). Pass this — not the numeric duneQueryId — to generate_incentive_query when building an incentive against this source.

Daily ingestion starts after registration. At least one ingestion run must complete before the source is query-ready — expect up to 24 hours before you can preview or create an incentive against it. generate_incentive_query rejects Dune sources until their column mapping is populated.

Typical workflow

  1. Save and publish your query on Dune, parameterized by a single string DATE-cast param.
  2. register_dune_event_source — register it on the active project (preview, then confirmed: true).
  3. Validate the Dune query via the Dune MCP — executeQueryById with a recent date for dateParamName, then getExecutionResults. Confirm the execution succeeds and returns rows with the expected columns. Fix the query via Dune MCP if not.
  4. Wait for at least one daily ingestion run (column mapping populated).
  5. generate_incentive_query with source: "dune_query" and the returned duneEventQueryId — build the SQL query.
  6. preview_incentive_query — (optional) validate results.
  7. create_recurring_incentive — create the reward program.

See the Dune Query Incentive guide for a full walkthrough.

Data Sources - Torque Docs