Skip to content

Complete reference for openapi.yaml — the single source of truth for Redocly-rendered API documentation. The backend team uses a Python codegen script to auto-generate their schema; this guide defines every convention so the generated output matches the file exactly.

The backend stage branch serializers are the source of truth for schemas and field names.


1. Top-level file structure

openapi: 3.0.3
info:
  title: Core API Concepts
  version: 1.0.0
  description: '...'              ← multi-line markdown, single-quoted YAML
paths:                             ← all endpoint definitions, ordered by sidebar position
  /public/v1/.../
    post: / get:
components:
  schemas:                         ← all request/response models (alphabetical)
  securitySchemes:
    Bearer:
      type: http
      scheme: bearer
      bearerFormat: JWT
servers:
- url: https://api-dashboard.influencers.club
  description: Production
tags:                              ← tag definitions (name + optional description)
x-tagGroups:                       ← sidebar navigation groups (CRITICAL for visibility)

Rules

  • OpenAPI version: always 3.0.3. Not 3.1.0, not 3.0.0.
  • info.description: single-quoted YAML string with markdown. Bold headers (**Discovery**), paragraphs separated by blank lines. Escape literal single quotes by doubling: can''t.
  • servers: one entry only — production URL. No staging/dev servers.
  • securitySchemes: exactly Bearer: { type: http, scheme: bearer, bearerFormat: JWT }. No other schemes.
  • Paths ordering: Creator Content → Enrichment → Discovery → Batch → Account (matches sidebar order).
  • Schemas ordering: alphabetical by schema name.

2. POST endpoint template

  /public/v1/creators/your/route/:
    post:
      operationId: public_v1_creators_your_route_create
      description: 'Single-line summary of what the endpoint does.


        **What you get**

        - First bullet describing the primary return value.

        - Second bullet with additional detail.


        **Credits**

        - X credits per successful request. If no data is returned, no credits
        are deducted.


        <div class="ic-ai-prompt-root" data-endpoint="your-endpoint-key"></div>'
      summary: Your Endpoint Name
      tags:
      - Your Endpoint Name
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/YourInputSchema'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/YourInputSchema'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/YourInputSchema'
        required: true
      security:
      - Bearer: []
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/YourResponseSchema'
          description: ''
      x-credits: X credits per successful request.

3. GET endpoint template

  /public/v1/discovery/classifier/languages/:
    get:
      operationId: public_v1_discovery_classifier_languages_list
      description: 'Retrieve a list of supported languages...


        **Credits**

        - 0 credits. This endpoint does not deduct credits.'
      summary: Languages
      tags:
      - Dictionary
      security:
      - Bearer: []
      responses:
        '200':
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Language'
          description: ''
      x-credits: 0 credits. This endpoint does not deduct credits.

GET endpoints use parameters: instead of requestBody::

      parameters:
      - in: path
        name: batch_id
        schema:
          type: string
        description: Unique batch identifier
        required: true
      - in: query
        name: format
        schema:
          type: string
          enum:
          - csv
          - json
          default: csv
        required: false
      - in: query
        name: search
        schema:
          type: string
        description: Search string to filter results
        required: false
      - in: query
        name: offset
        schema:
          type: integer
        description: Cursor offset for pagination
        required: false

The search + offset pagination pattern applies to classifier endpoints: audience-brand-categories, audience-brand-names, audience-interests, audience-locations.


4. Path entry rules

Trailing slash

All paths end with /: /public/v1/creators/socials/ not /public/v1/creators/socials.

operationId convention

  • POST: public_v1_{path_segments_with_underscores}_create
  • GET list: public_v1_{path_segments_with_underscores}_list
  • GET single resource: public_v1_{path_segments_with_underscores}_retrieve
  • Exception: account_credits_usage_retrieve (does not follow the public_v1_ prefix)

summary = tag name

summary must match the tag name exactly — it becomes the sidebar label. Multiple endpoints can share one tag (e.g. all batch endpoints use Batch enrichment).

description field

  • Always a single-quoted YAML string.
  • Content is indented 8 spaces (relative to the description: key).
  • Escape single quotes by doubling: can''t renders as can't.
  • Opens with a summary sentence, then bold section headers.

Required description sections

Every endpoint must have What you get and Credits. Exception: simple classifier endpoints where Credits alone suffices if the summary is self-explanatory.

Optional description sections

Add only when needed: When to use, How it works, Limits, Requirements, Output formats, Error Responses, Result format, Response fields, Supported content types per platform, Checking completion, Request.

HTML in descriptions

  • &nbsp;&nbsp; for indentation in sub-bullets:
    &nbsp;&nbsp;**Instagram** — fixed at 12 posts per page
  • AI prompt div must be the last thing before the closing ':
    <div class="ic-ai-prompt-root" data-endpoint="your-key"></div>'
    The data-endpoint value is kebab-case and matches the ENDPOINTS array in copy-for-ai.js.

requestBody content types

Standard POST endpoints: all three content types pointing to the same $ref:

  • application/json
  • application/x-www-form-urlencoded
  • multipart/form-data

Batch file upload exception: only multipart/form-data.

security

Always - Bearer: [].

Authorization header parameter

Some endpoints include an explicit in: header Authorization parameter alongside security: - Bearer: []:

      parameters:
      - in: header
        name: Authorization
        schema:
          type: string
        description: Bearer << Client JWT Token >>
        required: true

This applies to: Similar Creators POST, and all batch GET/POST endpoints (download, status, resume).

x-credits

Plain-text string after responses. Describes credit cost. Examples:

  • 0.03 credits per successful request. If no data is returned, no credits are deducted.
  • 0.01 credits per creator returned. If no creators are returned, no credits are deducted.
  • 0 credits. This endpoint does not deduct credits.
  • Multi-line for batch: 'Credits are deducted when batch records are processed successfully. Pricing follows the same credit model as the corresponding enrichment type: Handle enrichment (raw): 0.03 credits per successful record...'

5. Response conventions

200 response (default)

Most 200 responses have description: '' (empty string):

      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/YourResponseSchema'
          description: ''

200 with non-empty description

Two exceptions:

  • Batch download: description: CSV or JSON file with enriched results depending on the \format` query parameter.`
  • Account credits: description: OK

Error responses

Use type: object with additionalProperties: {}:

        '400':
          content:
            application/json:
              schema:
                type: object
                additionalProperties: {}
          description: Bad Request - Invalid input
        '403':
          content:
            application/json:
              schema:
                type: object
                additionalProperties: {}
          description: Forbidden - Insufficient permissions
        '404':
          content:
            application/json:
              schema:
                type: object
                additionalProperties: {}
          description: Not Found - Invalid batch ID
        '429':
          content:
            application/json:
              schema:
                type: object
                additionalProperties: {}
          description: Too Many Requests - Rate limit exceeded

Currently used on: batch create (400/403/429), batch download (400/404), batch resume (400/403/404), batch status (404).

Binary/file download response

Batch download returns two content types:

        '200':
          description: CSV or JSON file with enriched results...
          content:
            text/csv:
              schema:
                type: string
                format: binary
                description: Default CSV file with enriched results
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    input_value:
                      type: string
                    status:
                      type: string
                    enrichment_data:
                      type: object
                      additionalProperties: true

Response wrapper pattern

Most endpoints wrap their result in a standard envelope:

    SomeResponse:
      type: object
      properties:
        credits_cost:
          type: number
          nullable: true
        result:
          $ref: '#/components/schemas/SomeResult'
      required:
      - result

Variations:

  • AudienceOverlapResponse adds credits_left, status, success, and uses basics/details instead of result.
  • DiscoveryAPIResponse uses credits_left (format: decimal), total, limit, accounts (array).
  • response_meta is internal and not documented.

Inline response schemas

The account credits endpoint defines its response schema inline in the path, not via $ref:

      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  credits_available:
                    type: number
                  credits_used:
                    type: number
                required:
                - credits_available
                - credits_used
              example:
                credits_available: 0
                credits_used: 0

A named schema AccountCreditsUsageResponse also exists in components but is not referenced by the path.


6. Schema conventions

DRF serializer → OpenAPI mapping

Backend (Django REST Framework)OpenAPI 3.0.3
serializers.CharField()type: string
serializers.CharField(required=True)type: string, minLength: 1 + in required array
serializers.CharField(allow_blank=True)type: string (no minLength)
serializers.IntegerField()type: integer
serializers.FloatField()type: number, format: double
serializers.DecimalField(max_digits=N, decimal_places=M)type: string, format: decimal, pattern: ^-?\d{0,N}(?:\.\d{0,M})?$
serializers.BooleanField()type: boolean
serializers.DateTimeField()type: string, format: date-time
serializers.URLField()type: string, format: uri
serializers.EmailField()type: string, format: email
serializers.FileField()type: string, format: binary
serializers.DictField()type: object, additionalProperties: {}
serializers.ListField(child=CharField())type: array, items: { type: string }
serializers.ListField() (no child)type: array, items: {}
serializers.ChoiceField(choices=[...])type: string, enum: [...]
allow_null=TrueAdd nullable: true
required=FalseDo NOT include in required array
required=True (or default)Include in required array
default=valueAdd default: value
min_length=N on ListFieldminItems: N
max_length=N on ListFieldmaxItems: N
min_length=1 on CharFieldminLength: 1
help_text="..."description: '...'
Nested SomeSerializer()$ref: '#/components/schemas/Some'
Nested SomeSerializer(many=True)type: array, items: { $ref: '#/components/schemas/Some' }
Nested with allow_null=TrueallOf: [{ $ref }] + nullable: true (see composition patterns)

Pydantic BaseModel → OpenAPI mapping

PydanticOpenAPI
Field(default=None)nullable: true, not in required
Optional[str]type: string, nullable: true
Optional[int]type: integer, nullable: true
Optional[bool]type: boolean, nullable: true
Optional[list[str]]type: array, items: { type: string }, nullable: true
validation_alias=AliasChoices(...)Use the first alias as the field name

Field names

Use the exact field names from the backend serializer. If the serializer uses snake_case, the schema uses snake_case. If it uses camelCase, the schema uses camelCase. Do not rename fields.

Platform-native field names are kept as-is:

  • Twitch: profileImageURL, displayName, isPartner, panelsUrls
  • Twitter: userid (no underscore)
  • ConnectedSocial: userId, fullname

Identifier field descriptions

Any field that acts as an identifier (handle, creators, email, post_id, etc.) must have a description explaining exactly what values are accepted. Check the backend view to see how the field is processed.

        handle:
          type: string
          description: 'Creator identifier — username, profile URL, or YouTube channel ID (UC...).'

Never leave identifier fields with just type: string and no description.

Schema suffix naming conventions

SuffixWhen to useExample
RequestInput schemas for request bodiesAudienceFilterRequest, SortRequest
RequestRequestDRF auto-gen when serializer name already ends in RequestEnrichFullHandleRequestRequest
ResponseTop-level response wrappersHandleFullPlatformResponse
ResultInner result data objectCreatorPostsResult, HandleFullResultResponse
QueryInput for query-style POST endpointsCreatorPostsQuery, ConnectedSocialsQuery
InputInput for specific action endpointsAudienceOverlapInput
ModelSub-schema representing a data entityPostItemModel, EngagementModel
DocsRequestPlatform-specific variant for documentation displayDiscoveryAPISearchInputInstagramDocsRequest
(none)Utility/reference schemasBrand, Language, YouTubeTopic

Duplicate *RequestRequest naming

When a backend serializer is named SomeRequestSerializer, DRF auto-generation appends Request, producing SomeRequestRequest. This is expected behavior. Keep these names as-is to match backend codegen output. Current examples: EnrichFullHandleRequestRequest, EnrichRawHandleRequestRequest, EnrichBasicEmailRequestRequest, EnrichSimilarCreatorsRequestRequest, DiscoveryAPISearchInputRequestRequest.


7. Schema composition patterns

Simple $ref

For non-nullable required nested objects:

        user:
          $ref: '#/components/schemas/OverlapUser'

allOf + $ref + nullable

OAS 3.0.3 cannot put nullable: true on a $ref directly. Use allOf:

        gender:
          allOf:
          - $ref: '#/components/schemas/AudienceGenderFilterRequest'
          nullable: true

allOf + $ref + description

Adding a description alongside a $ref:

        creator_has:
          allOf:
          - $ref: '#/components/schemas/CreatorHasRequest'
          description: 'Supported platforms: Instagram, YouTube, TikTok, Twitch, Twitter, OnlyFans'

allOf + $ref + nullable + default + description

The most complex form, combining all modifiers:

        subscriber_growth:
          allOf:
          - $ref: '#/components/schemas/GrowthRequest'
          nullable: true
          default:
            growth_percentage: null
            time_range_months: 3
          description: 'Supported platforms: YouTube'

oneOf + discriminator (platform switching)

Used for the Discovery API to show platform-specific request bodies:

    DiscoveryAPISearchInputRequestRequest:
      oneOf:
      - $ref: '#/components/schemas/DiscoveryAPISearchInputInstagramDocsRequest'
      - $ref: '#/components/schemas/DiscoveryAPISearchInputYouTubeDocsRequest'
      - $ref: '#/components/schemas/DiscoveryAPISearchInputTikTokDocsRequest'
      - $ref: '#/components/schemas/DiscoveryAPISearchInputTwitchDocsRequest'
      - $ref: '#/components/schemas/DiscoveryAPISearchInputTwitterDocsRequest'
      - $ref: '#/components/schemas/DiscoveryAPISearchInputOnlyFansDocsRequest'
      discriminator:
        propertyName: platform
        mapping:
          instagram: '#/components/schemas/DiscoveryAPISearchInputInstagramDocsRequest'
          youtube: '#/components/schemas/DiscoveryAPISearchInputYouTubeDocsRequest'
          tiktok: '#/components/schemas/DiscoveryAPISearchInputTikTokDocsRequest'
          twitch: '#/components/schemas/DiscoveryAPISearchInputTwitchDocsRequest'
          twitter: '#/components/schemas/DiscoveryAPISearchInputTwitterDocsRequest'
          onlyfans: '#/components/schemas/DiscoveryAPISearchInputOnlyFansDocsRequest'

Each platform DocsRequest constrains platform to a single-value enum and references platform-specific filters. The description on each explains the pattern:

Redocly can''t dynamically show/hide fields based on `platform`, so we expose
a `oneOf` discriminator in the view schema that points to per-platform request variants.

oneOf for union types

Fields accepting either string or integer:

        last_post:
          oneOf:
          - type: string
          - type: integer
          nullable: true
          description: 'Supported platforms: Instagram, TikTok, Twitter'

additionalProperties

PatternWhen to useExample
additionalProperties: {}Flexible object, any key-value (DictField, error responses)Error schemas, metadata, income_data
additionalProperties: trueExplicit open-ended objectAudienceDataResponse, batch enrichment_data
additionalProperties: { type: string }Object with string values onlyCreatorContentDetailsResponse.result

8. Format specifiers

FormatTypeWhen to useExample fields
format: doubletype: numberFloat/engagement percentages, rates, min/max rangesengagement_percent, credits_cost, min, max
format: decimaltype: stringPython Decimal fields (serializes to string)credits_left, credits_used
format: date-timetype: stringTimestamp fieldscreated_at, started_at, estimated_completion
format: uritype: stringURL fieldspicture, profile_pic_url, links_in_bio items
format: emailtype: stringEmail fieldsemail in enrichment responses
format: binarytype: stringFile upload/downloadfile in batch input, CSV download response

Important: format: decimal always pairs with a pattern regex and type: string (not type: number):

        credits_left:
          type: string
          format: decimal
          pattern: ^-?\d{0,8}(?:\.\d{0,2})?$

9. Field constraints

minLength: 1

Applied to required CharField fields that cannot be empty:

        handle:
          type: string
          minLength: 1

minItems / maxItems

Applied to list fields:

        creators:
          type: array
          items:
            type: string
          minItems: 2
          maxItems: 10

nullable: true

Only add if the backend serializer explicitly has allow_null=True or Pydantic uses Optional[...]. Do not add by default.

default values

Must match the backend exactly:

  • Boolean: default: false (e.g. has_videos, exclude_role_based_emails, include_lookalikes)
  • Numeric: default: 1 (e.g. min_pct on audience filters), default: 3 (time_range_months)
  • String: default: csv, default: relevancy, default: desc, default: ok, default: preferred
  • Object: default: { growth_percentage: null, time_range_months: 3 }

pattern (regex)

For decimal-formatted string fields:

        credits_used:
          type: string
          format: decimal
          pattern: ^-?\d{0,8}(?:\.\d{0,2})?$

enum

Lowercase values. Can be on the property directly or on array items:

        platform:
          enum:
          - instagram
          - youtube
          - tiktok
          type: string
        exclude_platforms:
          type: array
          items:
            enum:
            - instagram
            - youtube
            - tiktok
            type: string

10. Redocly extensions

x-expandLevel: 2

Applied to response schemas with deeply nested $ref structures. Tells Redocly to auto-expand 2 levels deep in the response panel. Place directly under the schema name:

    BatchEnrichmentResponse:
      type: object
      x-expandLevel: 2
      properties:
        ...

Schemas that have x-expandLevel: 2:

  • BatchEnrichmentResponse
  • BatchEnrichmentStatusResponse
  • CreatorContentDetailsResponse
  • HandleEmailPlatformResponse
  • HandleEmailResponse
  • HandleFullPlatformResponse
  • HandleFullResultResponse
  • HandleRawPlatformResponse
  • HandleRawResultResponse
  • AccountCreditsUsageResponse

x-credits

See section 4 (path entry rules).

x-tagGroups

See section 13 (x-tagGroups rules).


11. Special patterns

Platform-specific response schemas

Three tiers of per-platform schemas:

  • HandleRaw[Platform]Response — 12 platforms: Instagram, YouTube, TikTok, OnlyFans, Twitter, Twitch, Facebook, Pinterest, Reddit, Snapchat, Discord, LinkedIn. Collected via HandleRawResultResponse.
  • HandleFull[Platform]Response — 7 platforms: Instagram, YouTube, TikTok, OnlyFans, Twitter, Twitch, LinkedIn. Collected via HandleFullResultResponse.
  • HandleEmail[Platform]Response — 6 platforms: Instagram, YouTube, TikTok, OnlyFans, Twitter, Twitch. Collected via HandleEmailPlatformResponse.

Each platform response has platform-native field names. Twitch uses camelCase (profileImageURL, displayName). Do not rename.

CreatorHasRequest pattern

Large schema with 50+ boolean fields for platform/service presence filtering:

        has_amazonaffiliates:
          type: boolean
          nullable: true
          default: false

All fields follow has_[platform_or_service] naming. Schema ends with example: {}.

Discovery filters nesting

AudienceFilterRequest is nullable: true and contains sub-schemas:

  • location — array of AudienceLocationFilterRequest
  • genderallOf: [AudienceGenderFilterRequest], nullable
  • language — array of AudienceLanguageFilterRequest
  • age — array of AudienceAgeFilterRequest
  • interests — array of AudienceInterestFilterRequest
  • Plus simple fields: brands, brand_categories, credibility (enum)

Each sub-filter has min_pct with default: 1.

Batch multi-endpoint workflow

Four related endpoints under the Batch enrichment tag:

  1. POST /public/v1/enrichment/batch/ — create (multipart only, error responses 400/403/429)
  2. GET /public/v1/enrichment/batch/{batch_id}/status/ — check status
  3. POST /public/v1/enrichment/batch/{batch_id}/resume/ — resume paused job
  4. GET /public/v1/enrichment/batch/{batch_id}/ — download results (CSV/JSON)

Empty items: {} for untyped arrays

Raw platform data arrays where item type is unconstrained:

        post_data:
          type: array
          items: {}

example field on schemas

Used sparingly on request and response schemas:

    EnrichFullHandleRequestRequest:
      type: object
      ...
      example:
        handle: cristiano
        platform: instagram
        email_required: preferred
        include_lookalikes: false
        include_audience_data: false

Also used on CreatorHasRequest (example: {}) and inline response schemas (account credits).


12. Result schemas — use named, expanded models

Every endpoint should have a dedicated named Result schema (e.g. CreatorPostsResult, AudienceOverlapResponse) rather than inlining the response structure. Break nested objects into their own schemas so Redocly renders them as expandable sections.

Good — each nested object is its own schema:

    CreatorPostsResult:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/PostItemModel'
        num_results:
          type: integer

    PostItemModel:
      type: object
      properties:
        pk:
          type: string
        engagement:
          $ref: '#/components/schemas/EngagementModel'
        user:
          $ref: '#/components/schemas/UserInfoModel'

Bad — everything inlined in one flat schema:

    CreatorPostsResult:
      type: object
      properties:
        items:
          type: array
          items:
            type: object
            properties:
              pk:
                type: string
              likes:
                type: integer

Follow the backend serializer structure — if the backend has a nested serializer, create a corresponding named schema.


13. Parameter descriptions and examples (future iteration)

Note: This is planned for a future iteration. When updating or adding endpoints, start applying this pattern where practical.

Every request parameter should include:

  • A description explaining what the field does and what values are accepted.
  • An example value showing a realistic input.
        handle:
          type: string
          description: 'Creator identifier — username, profile URL, or YouTube channel ID (UC...).'
          example: 'cristiano'
        platform:
          type: string
          enum:
          - instagram
          - tiktok
          - youtube
          description: 'Social platform to query.'
          example: 'instagram'

14. Tags section

Located after servers:, before x-tagGroups. Each endpoint's tag must be listed here.

tags:
- name: Discovery API
- name: Similar Creators
- name: Audience Overlap
- name: Dictionary
  description: |
    Provides the complete set of supported filter values used by the Discovery
    and Similar Creators endpoints...
- name: Connected Socials
- name: Enrich by handle full
- name: Enrich by handle raw
- name: Enrich by email
- name: Batch enrichment
  description: 'Bulk enrichment jobs: create, check status, resume, and download results.'
- name: Creator Posts
- name: Post Details
- name: Account credits & usage
  description: Account-level endpoints (credits, usage).

Rules:

  • Tags without descriptions: - name: TagName
  • Multi-line descriptions: pipe literal | block scalar
  • Single-line descriptions: single-quoted string
  • Add description: only when the tag name alone isn't self-explanatory

15. x-tagGroups (sidebar navigation)

Located at the very bottom of the file. Every tag must be listed here or it will not appear in the sidebar.

x-tagGroups:
- name: Creator Discovery
  tags:
  - Discovery API
  - Similar Creators
  - Audience Overlap
  - Dictionary
- name: Creator Enrichment
  tags:
  - Connected Socials
  - Enrich by handle full
  - Enrich by handle raw
  - Enrich by email
  - Batch enrichment
- name: Creator Content
  tags:
  - Creator Posts
  - Post Details
- name: User Info
  tags:
  - Account credits & usage

To add a new endpoint: add its tag under the correct existing group. To create a new group: check with the team first — do not invent groups.


16. Common mistakes

  1. Endpoint not in sidebar — tag missing from x-tagGroups.
  2. Tag undeclared — tag in x-tagGroups but missing from tags: section.
  3. Schema field mismatch — field name doesn't match backend serializer (e.g. camelCase vs snake_case).
  4. Invented constraints — do not add enum, minItems, maxItems, description, or any constraint not in the backend serializer.
  5. Missing content types — POST requestBody must have all 3 (except batch: multipart only).
  6. Broken YAML string — unescaped single quote in single-quoted description. Use ''.
  7. Missing trailing slash — paths must end with /.
  8. Wrong operationId — must follow public_v1_{path}_{method} convention.
  9. Forgetting AI prompt div<div class="ic-ai-prompt-root" data-endpoint="..."></div> at end of every description.
  10. Nullable without allow_null — only add nullable: true if backend has allow_null=True.
  11. $ref with nullable directly — OAS 3.0.3 cannot put nullable on a $ref. Must use allOf: [{ $ref }] with nullable: true.
  12. Wrong format for DecimalField — must be type: string, format: decimal, NOT type: number.
  13. Missing minLength: 1 — required CharField fields should have minLength: 1.
  14. Missing x-expandLevel: 2 — response schemas with nested $ref should have this for proper Redocly rendering.
  15. Renaming platform-native fields — camelCase fields like profileImageURL, displayName, isPartner, userId must be kept as-is.