vevee.canUse()POST /api/v1/can-usesk_live_

Read-only check. Returns whether the user is currently allowed to consume the given quantity, plus a per-group breakdown. Does not increment any counter - use for UI gating and pre-flight checks, not for enforcement.

Signatures

canUse(
  userId: string,
  event: string,
  quantity?: number,
  metadata?: EventMetadata,
): Promise<CanUseResponseData>;

// Shorthand - returns just the boolean
can(userId, event, quantity?, metadata?): Promise<boolean>;

Parameters

Identical to track(): userId, event, optional quantity (default 1), optional metadata.

Response

interface CanUseResponseData {
  allowed: boolean;
  matched: boolean;                   // false → no limit group covers this event,
                                      //   or the user has no subscription on file
  reasons: string[];                  // 'limit_reached' | 'unmatched_event' | 'no_subscription'
  details: {
    groupId: string;
    current: number;                  // current counter value
    quota: number;                    // limit
    resetsAt: string | null;          // ISO 8601, null for lifetime
  }[];
}
i
Fail-closed by default.If the event_type doesn't match any limit group on the user's plan, canUse returns { allowed: false, matched: false, reasons: ['unmatched_event'] }. Same for users with no subscription on file (no_subscription). The SDKconsole.warns in development so typos and missing limit groups surface immediately.

Examples

Boolean check (UI gating)

if (await vevee.can(userId, 'image.render')) {
  showGenerateButton();
} else {
  showUpgradePrompt();
}

Detailed check with reasons

const check = await vevee.canUse(userId, 'image.render', 1, { model: 'flux-pro' });

if (!check.allowed) {
  return res.status(429).json({
    error: 'limit_reached',
    reasons: check.reasons,
    details: check.details,
  });
}

Showing remaining quota in your UI

const { details } = await vevee.canUse(userId, 'image.render');
const group = details[0];
const remaining = group.quota - group.current;
// → "12 of 50 images left this month, resets Dec 1"
!
canUse is not a substitute for reserve. Two parallel requests can both pass canUse and then both call track, exceeding the limit. For enforcement under concurrency, use reserve / commit.

Errors

  • invalid_key (401)
  • requires_secret_key (403)
  • invalid_request (400)