ProjectR Docs
Backend (Convex)

API — dashboard

Generated catalog of Convex functions in convex/dashboard/. Regenerated by `bun run docs:api`.

Auto-generated from source. Do not edit by hand — run bun run docs:api.

query (26)

FunctionDescriptionArgs
dashboardGetAuditActionsThe action taxonomy the page filters by, straight from the registry in helpers/auditActions.ts, so every logged action can be filtered for.{}
dashboardGetAuditLogsGet audit logs for dashboard — paginated, filterable, with the acting admin's name resolved. The scan cap is reported separately from an empty result: a filter that finds nothing and a filter that ran out of budget look identical otherwise.{ action: v.optional(v.string()), /** * One AuditActionGroup name. Matches every action the registry files * under that group, which action alone cannot …
dashboardGetEnvironmentWhich deployment the dashboard is talking to and whether it may change the shared Shopify store. Rendered as a banner on the webhooks page and the voucher and Raya generation forms so an admin on dev or a preview knows why a store-changing button was refused (helpers/shopifyWrite.ts).{}
dashboardGetWebhookEventHealthCount webhook events per status for the delivery-health header. Each status reads by_status up to the cap and reports atCap when it hits it, so the page renders "200+" instead of a number the query never counted.{}
dashboardGetWebhookEventPayloadRead one webhook event's Shopify payload for the detail drawer. New events point at a webhookPayloads row; events written before that split still hold the JSON inline, so this follows payloadId first and falls back to the stored field, the same order webhooks/scheduled.ts resolves it in for replay.{ eventId: v.id("webhookEvents") }
dashboardGroupBySlugGet single group by slug (admin) Useful for URL-based lookups{ slug: v.string(), }
dashboardGroupsList product groups (admin){ groupType: v.optional(v.union( v.literal("featured"), v.literal("seasonal"), v.literal("category"), v.literal("promotion"), v.literal("custom") )), isPubli…
dashboardGroupWithProductsGet group with its products (admin){ groupId: v.id("productGroups"), limit: v.optional(v.number()), }
dashboardListIssuedVouchersIssued vouchers for the dashboard "Issued Vouchers" page, filtered and paged on the server. streamVouchers picks the narrowest index for the filters, so the list scales past the 5k cap on getAllVouchers. Every filter is applied while scanning rather than trimming an already loaded page, so a filter that rejects most rows costs more reading — not a short page that looks like the end of the data. Search matches a voucher code substring or the holder's name / email / phone / id.{ limit: v.optional(v.number()), cursor: v.optional(v.object({ ts: v.number(), id: v.string() })), status: v.optional(v.union( v.literal("active"), v.literal…
dashboardListWebhookEventsList webhook events newest first, optionally narrowed by status and topic. A status reads by_status_created; without one the scan reads by_created_at. Topic is a JS check over the index-bounded stream, so a topic search that finds nothing within the scan cap reports isTruncated rather than passing an exhausted budget off as an empty result.{ status: v.optional(schema.doc("webhookEvents").fields.status), topic: v.optional(v.string()), limit: v.optional(v.number()), cursor: v.optional(webhookEven…
dashboardProductGet single product with override (admin){ // Deep-link reachable (/products/<id>): accept any string and normalise, so a // malformed id renders "not found" instead of a validator error (rule 12). …
dashboardProductsList products with their overrides (admin){ isFeatured: v.optional(v.boolean()), hasOverride: v.optional(v.boolean()), status: v.optional(v.union(v.literal("active"), v.literal("archived"), v.literal…
dashboardVoucherKPIs—{ refreshKey: v.optional(v.number()), }
dashboardVoucherShopifyHealthShopify sync health for issued vouchers. Reports unsynced / orphaned counts on the last 5000 vouchers.{ refreshKey: v.optional(v.number()), }
getDashboardOverview—{ dateFrom: v.number(), // Unix timestamp ms dateTo: v.number(), // Unix timestamp ms refreshKey: v.optional(v.number()), }
getGamificationStatsGet gamification/loyalty statistics Returns stamp campaigns, vouchers, and shake-to-win stats{ dateFrom: v.number(), dateTo: v.number(), refreshKey: v.optional(v.number()), }
getOrderVolumeTrendGet order volume trend over time Returns time-series data with platform breakdown{ dateFrom: v.number(), dateTo: v.number(), bucket: v.optional(v.union(v.literal("day"), v.literal("week"), v.literal("month"))), refreshKey: v.optional(v.nu…
getPlatformDistributionGet platform distribution Returns breakdown of visitors by platform (iOS, Android, Web){ dateFrom: v.number(), dateTo: v.number(), refreshKey: v.optional(v.number()), }
getProductPerformanceGet top performing products Returns products ranked by revenue and engagement{ dateFrom: v.number(), dateTo: v.number(), limit: v.optional(v.number()), refreshKey: v.optional(v.number()), }
getRecentSalesGet recent sales Returns list of recent orders for the dashboard{ dateFrom: v.optional(v.number()), dateTo: v.optional(v.number()), limit: v.optional(v.number()), refreshKey: v.optional(v.number()), }
getRevenueTrendGet revenue trend over time Returns time-series data for revenue chart{ dateFrom: v.number(), dateTo: v.number(), bucket: v.optional(v.union(v.literal("day"), v.literal("week"), v.literal("month"))), refreshKey: v.optional(v.nu…
getShopifyWebhookByIdGet a single webhook subscription by Shopify ID{ shopifyWebhookId: v.string(), }
getShopifyWebhookStatsGet webhook subscription statistics{}
getUserGrowthTrendGet user growth trend over time Returns time-series data for user signups{ dateFrom: v.number(), dateTo: v.number(), bucket: v.optional(v.union(v.literal("day"), v.literal("week"), v.literal("month"))), refreshKey: v.optional(v.nu…
getVoucherStatsGet voucher statistics (admin dashboard){ dateFrom: v.optional(v.number()), dateTo: v.optional(v.number()), refreshKey: v.optional(v.number()), }
listShopifyWebhooksList all webhook subscriptions{}

mutation (26)

FunctionDescriptionArgs
addProductsToGroupAdd multiple products to a group{ groupId: v.id("productGroups"), productIds: v.array(v.id("shopifyProducts")), }
bulkGenerateVouchers—{ templateId: v.id("voucherTemplates"), userIds: v.array(v.string()), channel: v.optional(issueChannelArg), notes: v.optional(v.string()), }
bulkPublishOverridesBulk publish product overrides{ productIds: v.array(v.id("shopifyProducts")), }
bulkRegisterShopifyWebhooksBulk register all required webhooks{}
bulkRevokeVouchersBulk revoke vouchers (admin). Caps at 50 voucher ids per call and processes them inline. Each voucher gets the same cleanup as single revoke (counter dec + Shopify delete).{ voucherIds: v.array(v.id("vouchers")), reason: v.optional(v.string()), }
bulkSetBadgeSet product badge (bulk operation){ productIds: v.array(v.id("shopifyProducts")), badgeLabel: v.union(v.string(), v.null()), }
bulkSetFeaturedSet product as featured (bulk operation){ productIds: v.array(v.id("shopifyProducts")), featured: v.boolean(), }
createProductGroupCreate a product group{ name: v.string(), slug: v.string(), description: v.optional(v.string()), imageUrl: v.optional(v.string()), groupType: v.union( v.literal("featured"), v.lit…
deleteAllShopifyWebhooksDelete this deployment's own webhook subscriptions. Webhooks that call another deployment are skipped.{}
deleteProductGroupDelete a product group{ groupId: v.id("productGroups"), }
deleteProductOverrideDelete a product override{ overrideId: v.id("productOverrides"), }
deleteShopifyWebhookDelete a single webhook subscription{ shopifyWebhookId: v.string(), }
extendVoucherExpiryExtend a voucher's expiry (admin). Patches expiresAt locally; Shopify discount endsAt is not currently updated — Shopify discounts created via createShopifyDiscountForVoucher have a long endsAt window already (voucher.expiresAt + buffer). If finer sync is needed, follow up with discountCodeBasicUpdate.{ voucherId: v.id("vouchers"), newExpiresAt: v.number(), reason: v.optional(v.string()), }
issueVoucherToUserIssue a single voucher to a specific user (admin). Accepts channel + notes, increments the active-voucher counter and writes an audit log.{ templateId: v.id("voucherTemplates"), userId: v.string(), channel: v.optional(issueChannelArg), notes: v.optional(v.string()), }
publishProductGroupPublish a product group{ groupId: v.id("productGroups"), }
refreshShopifyWebhooksRefresh webhook list from Shopify{ baseUrl: v.optional(v.string()), }
reissueVoucherReissue a voucher (admin). Cancels the original (queueing removal of its Shopify code) and creates a fresh active voucher copy with a new code linked via notes referencing the previous code.{ voucherId: v.id("vouchers"), reason: v.optional(v.string()), }
removeProductsFromGroupRemove multiple products from a group{ groupId: v.id("productGroups"), productIds: v.array(v.id("shopifyProducts")), }
reorderGroupProductsReorder products within a group{ groupId: v.id("productGroups"), productOrder: v.array( v.object({ productId: v.id("shopifyProducts"), position: v.number(), }) ), }
revokeVoucherRevoke a voucher (admin) Marks voucher as cancelled, decrements activeVouchers counter, and (if the voucher has a Shopify discount node) enqueues a Shopify delete via shopifySyncPool so the code can no longer be redeemed at checkout.{ voucherId: v.id("vouchers"), reason: v.optional(v.string()), }
syncShopifyWebhookUrlsRe-point this deployment's own outdated webhooks (same host, stale path) at its current URLs. Webhooks that call another deployment are left alone.{}
unpublishProductGroupUnpublish a product group{ groupId: v.id("productGroups"), }
updateProductGroupUpdate a product group{ groupId: v.id("productGroups"), name: v.optional(v.string()), slug: v.optional(v.string()), description: v.optional(v.string()), imageUrl: v.optional(v.str…
updateProductLocalizationUpdate product override localization{ overrideId: v.id("productOverrides"), locale: v.string(), title: v.optional(v.string()), description: v.optional(v.string()), heroImageUrl: v.optional(v.st…
updateShopifyWebhookUrlUpdate a webhook's callback URL{ shopifyWebhookId: v.string(), callbackUrl: v.string(), }
upsertProductOverrideUpsert a product override (create or update){ productId: v.id("shopifyProducts"), isFeatured: v.optional(v.boolean()), isPublished: v.optional(v.boolean()), badgeLabel: v.optional(v.string()), marketin…

internalQuery (1)

FunctionDescriptionArgs
aggregateHealth—{}

On this page