Execute Superleap Object Query
Analytics Query APIs
Execute Superleap Object Query
Runs a read-only SQL analytics query against a Superleap object.
POST
Execute Superleap Object Query
Overview
Run a Superleap Object Query against a Superleap object and return the resulting records - for analytics and reporting use cases such as field selection, counts, grouped summaries, and filtered datasets.Replace
<domain> with your Superleap workspace domain. For example, app.superleap.com, sandbox.superleap.dev, or your tenant-specific domain.Authentication
Bearer token scoped to the Superleap organization.Headers
string
required
Bearer token for authentication. Click here to generate one.
string
default:"application/json"
required
Must be
application/json.Request Body
string
required
Raw PostgreSQL
SELECT query to execute. The top-level FROM table must exactly match slug.string
required
Base CRM object slug used in the query’s top-level
FROM clause, for example account, contact, deal, or another object slug from your workspace.Query Rules
Thequery field is written in the Superleap Query Language, a PostgreSQL-compatible SELECT syntax that understands your objects and their relations.
Structure
OnlySELECT queries are accepted. The top-level FROM must be the object slug exactly as returned by list_objects ('lead', never 'leads'), and it must match the request’s slug. Always end the query with a LIMIT; use LIMIT 100 when you have no specific number in mind.
Dates and times
Every date and datetime field stores epoch milliseconds as a bigint. Compare epoch to epoch inWHERE clauses, and compute the boundaries inside the SQL instead of pasting precomputed numbers, date strings, CURRENT_DATE, or to_timestamp(...) comparisons:
AT TIME ZONE twice; with only one, the boundary silently lands at 05:30 IST instead of midnight.
For grouping and display, use date_trunc('day', to_timestamp(field/1000) AT TIME ZONE 'Asia/Kolkata'). Avoid DATE(...), interval-offset timezone tricks, and selecting raw epoch values in result columns.
Fields whose data_type is 'date' are stored as UTC-midnight epochs: build the same epoch boundaries but without AT TIME ZONE, and display them with to_timestamp(field/1000)::date.
Relations
Dot notation (owner.name) is always safe in SELECT, WHERE, and GROUP BY. Most objects carry id, name, created_at, updated_at, owner, created_by, and updated_by; confirm the rest with describe_object.
One caution: IN subqueries (in either direction) fail on columns whose relationship_type is 'virtual'. The failure is silent, the subquery yields raw NULLs and the query returns 0 rows with no error. Use dot notation or a correlated EXISTS for those (see Working with Relationships).
Multi-select fields
Multi-select values are arrays. Use array operators, not string functions:array_length and array subscripts are not supported.
Supported SQL surface
JOIN, UNION, CTEs (WITH), EXTRACT, FILTER (WHERE ...), casts other than ::date, and pg_* system references are not supported. The available functions are: count, sum, avg, min, max, lower, upper, concat, trim, abs, round, coalesce, date_trunc, to_timestamp, date_part, if, case. For conditional counts, use COUNT(CASE WHEN condition THEN 1 END).
Style: keep identifiers bare (never double-quote them), quote strings with single quotes, use ILIKE for case-insensitive matching, and write booleans as 0/1. Do not add is_deleted filters; deletion handling is automatic.
Currency units
Convert amounts inside the SQL so results come back ready to display:ROUND(SUM(amount)/10000000, 2) for crore, ROUND(SUM(amount)/100000, 2) for lakh.
Good Query Patterns
Field selection
Count by owner
Date grouping
Unsupported Query Patterns
Working with Relationships
Superleap objects reference each other through relation fields. There are two kinds - direct (to-one) and virtual (one-to-many) - and each supports a few query styles. Pick based on what you are computing.Direct (to-one) relations
A lookup field on the row itself (owner, account): each row points to at most one related record. Dot notation reads or filters the related record, and hops can be chained:
Virtual (one-to-many) relations
A reverse link from a parent to its children (associated_opportunities on lead). Three supported ways to use them:
1. Dot notation - filter parents by a child field:
COUNT(DISTINCT id) for counts and SELECT DISTINCT id for row lists whenever a virtual relation appears in the query.
2. Correlated EXISTS / NOT EXISTS - a semi-join with no fan-out, so plain COUNT(id) is fine. Recommended for “has none” checks and for combining conditions across two different virtual relations:
FROM the child; every hop up is to-one, so there is no fan-out and the scan is smaller:
Recommendations for virtual relations
- To check that a parent has no children, prefer
NOT EXISTS(or count the complement:|no child| = |all| − |has child|) overIS NULLon the relation field - the explicit forms are unambiguous about “no child rows exist”. - To combine conditions on two different virtual relations with
OR, preferORof twoEXISTSsubqueries, or split into one query per relation and merge with inclusion-exclusion (below). A single dot-notationORacross two virtual relations is expensive on large objects and may hit the execution timeout. ANDacross two virtual relations in dot notation is fine.
Performance Patterns
Many metrics in one scan
Compute related metrics as conditional aggregates in a single pass instead of one query per metric - the scan dominates the cost, extra CASE columns are nearly free:Capped counts with LIMIT
SELECT id ... LIMIT N stops scanning once N rows are found. Paired with the count endpoint, this answers “at least N?” quickly on huge cohorts: if the returned count equals the limit, show “N+”; if below, it is already the exact count. Useful for dashboards where big tiles can display a capped value with an on-demand exact count.
Unions via inclusion-exclusion
For counts across two virtual relations, running the parts separately and combining arithmetically is often the fastest reliable approach:General tips
- Long queries are terminated at the execution timeout - decompose work so every query finishes with margin, and retry transient failures with backoff.
- Keep concurrent heavy analytics queries from one client low (around 2); the replica slows under parallel heavy scans.
- All date fields are epoch ms bigint (rule 2).
data_type 'date'fields are stored as UTC-midnight epochs - use epoch boundaries WITHOUTAT TIME ZONEfor those.
Response
boolean
true when the request succeeds.object
Execute result payload.
Example Request
Example Response
Error Responses
400
429
504