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

# Create Portfolio Submission

> Create a private, review-gated portfolio media submission and signed upload URL.

This route stages evidence only. Upload the media with the returned signed `PUT` URL, then call upload completion. The partner credential never writes directly to Sanity.


## OpenAPI

````yaml openapi-portfolio-intake.json POST /submissions
openapi: 3.1.0
info:
  title: TattooAPI Portfolio Intake
  version: 1.0.0
  description: >-
    Private, review-gated portfolio intake for approved partners and TattooAPI
    operators. These operations never publish directly to public surfaces.
servers:
  - url: https://api.tattooapi.com/api/private/portfolio-intake/v1
    description: Production private portfolio intake
security: []
paths:
  /submissions:
    post:
      summary: Create a governed portfolio submission
      description: >-
        Requires portfolio_intake:stage. Creates a private intake record and
        short-lived signed upload URL. It does not write directly to Sanity or
        any public surface.
      operationId: createPortfolioIntakeSubmission
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PortfolioSubmissionRequest'
      responses:
        '201':
          description: Submission created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PortfolioSubmissionResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
      security:
        - ApiKeyAuth: []
        - BearerAuth: []
components:
  schemas:
    PortfolioSubmissionRequest:
      type: object
      required:
        - idempotencyKey
        - tenantId
        - artistCanonicalId
        - source
        - fileName
        - mimeType
        - sizeBytes
        - rightsPosture
        - consentPosture
      properties:
        idempotencyKey:
          type: string
          minLength: 8
        tenantId:
          type: string
        studioCanonicalId:
          type: string
        artistCanonicalId:
          type: string
        source:
          type: string
          enum:
            - permanent_imessage
            - partner_api
            - operator_upload
        sourceMessageId:
          type: string
        fileName:
          type: string
        mimeType:
          type: string
          enum:
            - image/jpeg
            - image/png
            - image/webp
            - image/heic
        sizeBytes:
          type: integer
          minimum: 1
        title:
          type: string
        description:
          type: string
        styleIds:
          type: array
          items:
            type: string
        placement:
          type: string
        tags:
          type: array
          items:
            type: string
        rightsPosture:
          type: string
          enum:
            - owner_attested
            - artist_attested
            - review_required
        consentPosture:
          type: string
          enum:
            - client_consented
            - not_required
            - review_required
    PortfolioSubmissionResponse:
      type: object
      properties:
        success:
          type: boolean
          const: true
        data:
          type: object
          properties:
            submission:
              type: object
              properties:
                submissionId:
                  type: string
                intakeStatus:
                  type: string
                reviewStatus:
                  type: string
            upload:
              type: object
              properties:
                method:
                  type: string
                  const: PUT
                url:
                  type: string
                  format: uri
                expiresInSeconds:
                  type: integer
  responses:
    Unauthorized:
      description: Missing or invalid WorkOS credential
    Forbidden:
      description: Credential is unmapped, out of scope, or lacks the required permission
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: WorkOS organization API key mapped to a TattooAPI service actor.
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: WorkOS AuthKit bearer token mapped to a TattooAPI human actor.

````