> ## Documentation Index
> Fetch the complete documentation index at: https://docs.creem.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Preview usage events

> Dry-run of `POST /v1/events/ingest`: send the exact batch you would ingest and get a per-event report of what would happen — **nothing is stored**.
For each event: whether it passes validation (invalid events are reported in place instead of rejecting the batch, unlike ingest), the `event_id` it would be recorded under, whether it would deduplicate against an already-stored event or an earlier entry of the same batch (advisory — another writer can land between preview and ingest), the active meters that would consume it, and the same warnings ingest returns.
Usage events are immutable once ingested, so preview is the way to gain first-run confidence: wire your integration against preview, check `valid` is true and every event matches the meters you expect, then switch the path to `ingest`.



## OpenAPI

````yaml post /v1/events/preview
openapi: 3.0.0
info:
  title: Creem API
  description: >-
    Creem is an all-in-one platform for managing subscriptions and recurring
    revenue, tailored specifically for today's SaaS companies. It enables you to
    boost revenue, enhance customer retention, and scale your operations
    seamlessly.
  version: v1
  contact:
    name: Creem Support
    url: https://creem.io
    email: support@creem.io
  license:
    name: Commercial
    url: https://creem.io/terms
  termsOfService: https://creem.io/terms
servers:
  - url: https://api.creem.io
    description: Production — live API for processing real transactions and data.
    x-speakeasy-server-id: prod
  - url: https://test-api.creem.io
    description: Test — sandbox API for development and testing with no real charges.
    x-speakeasy-server-id: test
security: []
tags: []
externalDocs:
  description: Creem Documentation
  url: https://docs.creem.io
paths:
  /v1/events/preview:
    post:
      tags:
        - Events
      summary: Preview usage events
      description: >-
        Dry-run of `POST /v1/events/ingest`: send the exact batch you would
        ingest and get a per-event report of what would happen — **nothing is
        stored**.


        For each event: whether it passes validation (invalid events are
        reported in place instead of rejecting the batch, unlike ingest), the
        `event_id` it would be recorded under, whether it would deduplicate
        against an already-stored event or an earlier entry of the same batch
        (advisory — another writer can land between preview and ingest), the
        active meters that would consume it, and the same warnings ingest
        returns.


        Usage events are immutable once ingested, so preview is the way to gain
        first-run confidence: wire your integration against preview, check
        `valid` is true and every event matches the meters you expect, then
        switch the path to `ingest`.
      operationId: previewUsageEvents
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IngestUsageEventsApiRequestDto'
      responses:
        '200':
          description: Per-event report; nothing was stored
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PreviewUsageEventsApiResponseDto'
        '400':
          description: Bad Request - Invalid input parameters
        '401':
          description: Unauthorized - Invalid or missing API key
        '404':
          description: Not Found - Resource does not exist
        '422':
          description: >-
            The request envelope itself is malformed (e.g. no events array, or
            more than the batch maximum)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UsageMeteringErrorApiResponseDto'
      security:
        - ApiKey: []
components:
  schemas:
    IngestUsageEventsApiRequestDto:
      type: object
      properties:
        events:
          description: >-
            The batch of usage events to ingest (1–100). The whole batch is
            validated before anything is written.
          type: array
          items:
            $ref: '#/components/schemas/IngestUsageEventApiRequestDto'
      required:
        - events
    PreviewUsageEventsApiResponseDto:
      type: object
      properties:
        valid:
          type: boolean
          description: >-
            Whether the batch as submitted would be accepted by POST
            /v1/events/ingest (ingest validation is all-or-nothing)
        events:
          description: Per-event report, in submission order
          type: array
          items:
            $ref: '#/components/schemas/PreviewUsageEventReportApiDto'
      required:
        - valid
        - events
    UsageMeteringErrorApiResponseDto:
      type: object
      properties:
        error:
          description: Error details
          allOf:
            - $ref: '#/components/schemas/UsageMeteringErrorDetailApiDto'
      required:
        - error
    IngestUsageEventApiRequestDto:
      type: object
      properties:
        name:
          type: string
          description: The usage event name; must match a meter to be aggregated
          example: image.generated
          maxLength: 128
        customer_id:
          type: string
          description: The customer this usage is attributed to
          example: cust_abc123
        event_id:
          type: string
          description: >-
            Your idempotency key for this event, unique within your store.
            Re-sending the same event_id is a no-op. Generated for you when
            omitted — supply your own if you want retries to be safe.
          example: order-1234
        timestamp:
          type: string
          description: >-
            When the usage occurred (ISO 8601), on your clock. Defaults to the
            time of ingestion.
          example: '2026-08-15T10:30:00.000Z'
        properties:
          type: object
          description: >-
            Top-level structured fields carried by the event — this is where the
            value an aggregation reduces (e.g. "tokens") lives. At most 50 keys,
            keys at most 40 characters, string values at most 500 characters.
          example:
            tokens: 1200
        metadata:
          type: object
          description: >-
            Free-form metadata. Addressable by meter filter clauses without a
            prefix. Same limits as `properties`.
          example:
            tier: pro
      required:
        - name
        - customer_id
    PreviewUsageEventReportApiDto:
      type: object
      properties:
        valid:
          type: boolean
          description: Whether this event would pass ingest validation
        event_id:
          type: object
          description: >-
            The idempotency key the event would be recorded under — your
            `event_id`, trimmed. Null when the event is invalid, and also null
            when you omitted `event_id`: ingest generates a fresh id at accept
            time, so previewing one would be misleading.
          nullable: true
          example: order-1234
        error:
          description: Why the event is invalid. Null when valid.
          nullable: true
          allOf:
            - $ref: '#/components/schemas/PreviewUsageEventErrorApiDto'
        duplicate:
          type: object
          description: >-
            Advisory: would this event deduplicate against an already-stored
            event (or an earlier entry of this batch)? Null when the event is
            invalid. Racy by nature — a signal for debugging retries, not a
            guarantee.
          nullable: true
        matched_meters:
          description: >-
            Ids of the active meters that would consume this event, at preview
            time
          example:
            - mtr_abc123
          type: array
          items:
            type: string
        warnings:
          description: Advisory warnings — same semantics as ingest warnings
          type: array
          items:
            $ref: '#/components/schemas/PreviewUsageEventWarningApiDto'
      required:
        - valid
        - matched_meters
        - warnings
    UsageMeteringErrorDetailApiDto:
      type: object
      properties:
        type:
          type: string
          description: Error category
          enum:
            - invalid_request_error
            - api_error
            - authentication_error
            - rate_limit_error
          example: invalid_request_error
        code:
          type: string
          description: Machine-readable error code
          example: meter_name_taken
          nullable: true
        message:
          type: string
          description: Human-readable error message
          example: A meter named "Image generations" already exists in this store
        param:
          type: string
          description: The parameter related to the error, if applicable
          example: events[3].customer_id
          nullable: true
        details:
          type: object
          description: >-
            Structured, machine-readable context for errors that support an
            action, omitted entirely when there is none. Currently emitted for
            `meter_name_taken` when the colliding name is held by an ARCHIVED
            meter: `archived_holder` is true and `archived_holder_id` is that
            meter, which can be restored via POST /v1/meters/{id}/unarchive.
            Additive — treat unknown keys as ignorable.
          example:
            archived_holder: true
            archived_holder_id: mtr_abc123
        request_id:
          type: string
          description: Unique request identifier for support
          example: req_abc123def456
      required:
        - type
        - code
        - message
        - request_id
    PreviewUsageEventErrorApiDto:
      type: object
      properties:
        code:
          type: string
          description: Validation error code
          example: invalid_usage_event
        message:
          type: string
          description: What is wrong with the event
        param:
          type: object
          description: The offending field, named as you sent it
          example: customer_id
          nullable: true
      required:
        - code
        - message
    PreviewUsageEventWarningApiDto:
      type: object
      properties:
        code:
          type: string
          description: Warning code — same set as ingest warnings
          enum:
            - no_matching_meter
            - meter_archived
            - timestamp_outside_late_window
          example: no_matching_meter
        message:
          type: string
          description: Human-readable explanation
      required:
        - code
        - message
  securitySchemes:
    ApiKey:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        API key for authentication. You can find your API key in the Creem
        dashboard under Settings > API Keys.

````