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

# Crear sesión de subida

> Crea un enlace de subida de fotos alojado en RoofKit para una foto del propietario. Comparte la `url` devuelta con el propietario como un enlace normal. El enlace abre una página de RoofKit, nunca un iframe. Cuando el propietario sube una foto, RoofKit elimina los metadatos de la foto, guarda la foto de forma privada e inicia un render facturable con el estilo de esta solicitud. Consulta la sesión periódicamente para leer el resultado. El enlace caduca después de `expires_in_minutes` y acepta una foto. Solo la API key que crea la sesión puede leerla.

**Scopes requeridos:** `sales_visualizer.use`


## OpenAPI

````yaml /es/api-reference/openapi.yaml post /api/v1/upload-sessions
openapi: 3.1.0
info:
  title: RoofKit Partner API
  version: 1.0.0
  summary: API REST JSON para integraciones externas de socios de RoofKit.
  contact:
    name: RoofKit Engineering
  description: >-
    RoofKit Partner API v1 autentica solicitudes con API keys del workspace. Las
    API keys vinculan cada solicitud exactamente a un workspace; las rutas de
    Partner API no aceptan roofer_id, workspace_id ni identificadores de tenant.
    Los endpoints autenticados están limitados a 60 solicitudes por minuto por
    API key, método y plantilla de ruta; los intentos de autenticación inválidos
    se limitan por separado a 20 solicitudes por minuto por cliente y endpoint.
    Los parámetros y campos de fecha/hora aceptan ISO 8601 con Z o un desfase
    ±HH:MM, por ejemplo 2026-09-07T04:00:00Z o 2026-09-07T00:00:00-04:00. Ambos
    indican el mismo instante y devuelven el mismo resultado. Codifica + como
    %2B en una query string. Las respuestas usan UTC.


    Una fecha/hora sin desfase, por ejemplo 2026-09-07T04:00:00, está obsoleta.
    Hasta la fecha de retiro, 2027-01-10T00:00:00Z, se interpreta como UTC, y la
    respuesta incluye un header `Deprecation` (RFC 9745) y un header `Sunset`
    (RFC 8594). A partir de la fecha de retiro, se requiere Z o un desfase
    ±HH:MM. Desde entonces, una fecha/hora sin desfase devuelve 400 con el
    código `VALIDATION_ERROR`, y la respuesta no incluye ningún header
    `Deprecation` ni `Sunset`.


    Cada API key tiene solo los scopes que un propietario o administrador del
    workspace eligió al crear la key, y sus scopes nunca cambian. Cada operación
    indica los scopes que requiere en `x-required-scopes`. Una key nueva en
    Configuración empieza con el nivel predefinido Solo lectura: `leads.read`,
    `analytics.read`, `reports.read` y `data_objects.read`. Una key de Solo
    lectura puede llamar a todas las operaciones de lectura excepto las
    exportaciones, las lecturas de Sales Visualizer y los Data Objects en
    papelera, y no puede llamar a ninguna operación de escritura. Una llamada
    que necesita un scope que la key no tiene devuelve 403 `FORBIDDEN`, y
    `error.details.required_scope` indica un scope faltante.
servers:
  - url: https://api.roofkit.ai
    description: Origen canónico de RoofKit Partner API
security:
  - ApiKeyBearer: []
tags:
  - name: Foundation
    description: Endpoints base de autenticación y contrato.
  - name: Leads
    description: Endpoints de sincronización de leads para CRM de socios.
  - name: Attribution
    description: >-
      Endpoints de atribución de marketing, analíticas de campañas e ingesta de
      eventos para socios.
  - name: Pipeline
    description: Metadatos del pipeline de leads legibles para socios.
  - name: Reports
    description: >-
      Endpoints para importar, listar, obtener, exportar y descargar reportes de
      socios.
  - name: Visualizer
    description: >-
      Endpoints de Partner para crear Sales Visualizer, generar visualizaciones,
      crear enlaces alojados de subida de fotos, leer imágenes, consultar el
      historial de sesión y crear enlaces compartidos.
  - name: Estimates
    description: >-
      Creación y lectura de Budget Estimates de Partner para el workspace
      vinculado a la key.
  - name: Objects
    description: >-
      Endpoints de Partner para descubrimiento, esquema, registros, relaciones,
      vistas y administración de Data Objects.
paths:
  /api/v1/upload-sessions:
    post:
      tags:
        - Visualizer
      summary: Crear sesión de subida
      description: >-
        Crea un enlace de subida de fotos alojado en RoofKit para una foto del
        propietario. Comparte la `url` devuelta con el propietario como un
        enlace normal. El enlace abre una página de RoofKit, nunca un iframe.
        Cuando el propietario sube una foto, RoofKit elimina los metadatos de la
        foto, guarda la foto de forma privada e inicia un render facturable con
        el estilo de esta solicitud. Consulta la sesión periódicamente para leer
        el resultado. El enlace caduca después de `expires_in_minutes` y acepta
        una foto. Solo la API key que crea la sesión puede leerla.
      operationId: Create upload session
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UploadSessionCreateRequest'
      responses:
        '201':
          description: Sesión de subida creada.
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/RateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/RateLimitRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/RateLimitReset'
            Idempotency-Replayed:
              $ref: '#/components/headers/IdempotencyReplayed'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UploadSessionResponse'
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '403':
          $ref: '#/components/responses/Forbidden'
        '409':
          $ref: '#/components/responses/Conflict'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: true
      description: >-
        Un valor único para cada solicitud nueva, como un UUID. Envíe el mismo
        valor para reintentar una solicitud de forma segura. La misma clave y el
        mismo payload repiten la primera respuesta con `Idempotency-Replayed:
        true`.
      schema:
        type: string
        minLength: 1
        maxLength: 160
  schemas:
    UploadSessionCreateRequest:
      type: object
      additionalProperties: false
      required:
        - material_name
        - color_name
      properties:
        session_id:
          type:
            - string
            - 'null'
          maxLength: 200
          description: >-
            Sesión opcional de Sales Visualizer que agrupa el render. Por
            defecto es `upload_session:{id}`.
        material_name:
          type: string
          maxLength: 100
          example: Architectural Shingle
        color_name:
          type: string
          maxLength: 100
          example: Charcoal
        color_hex:
          type: string
          pattern: ^#[0-9A-Fa-f]{6}$
          example: '#333333'
        shape_name:
          type:
            - string
            - 'null'
          maxLength: 100
        selected_material_id:
          type:
            - string
            - 'null'
          maxLength: 150
        selected_color_id:
          type:
            - string
            - 'null'
          maxLength: 150
        selected_shape_id:
          type:
            - string
            - 'null'
          maxLength: 150
        locale:
          type: string
          enum:
            - en
            - es
          default: en
          description: Idioma de la página de subida del propietario.
        expires_in_minutes:
          type: integer
          minimum: 5
          maximum: 1440
          default: 60
    UploadSessionResponse:
      type: object
      additionalProperties: false
      required:
        - upload_session
      properties:
        upload_session:
          $ref: '#/components/schemas/UploadSession'
    UploadSession:
      type: object
      additionalProperties: false
      required:
        - id
        - status
        - url
        - session_id
        - locale
        - expires_at
        - style
        - visualization_id
        - visualization
        - failure_code
        - uploaded_at
        - completed_at
        - created_at
        - updated_at
      properties:
        id:
          type: string
          format: uuid
        status:
          type: string
          enum:
            - awaiting_upload
            - processing
            - completed
            - failed
            - expired
        url:
          type:
            - string
            - 'null'
          format: uri
          description: >-
            Página de subida del propietario. Presente solo mientras `status` es
            `awaiting_upload`.
        session_id:
          type: string
        locale:
          type: string
          enum:
            - en
            - es
        expires_at:
          type: string
          format: date-time
        style:
          $ref: '#/components/schemas/UploadSessionStyle'
        visualization_id:
          type:
            - string
            - 'null'
        visualization:
          oneOf:
            - $ref: '#/components/schemas/Visualization'
            - type: 'null'
        failure_code:
          description: >-
            Por qué no terminó el render. Presente solo cuando `status` es
            `failed`.
          oneOf:
            - type: string
              enum:
                - INSUFFICIENT_CREDITS
                - WORKSPACE_UNAVAILABLE
                - GENERATION_FAILED
            - type: 'null'
        uploaded_at:
          type:
            - string
            - 'null'
          format: date-time
        completed_at:
          type:
            - string
            - 'null'
          format: date-time
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    ErrorResponse:
      type: object
      additionalProperties: false
      required:
        - error
      properties:
        error:
          type: object
          additionalProperties: false
          required:
            - code
            - message
            - request_id
          properties:
            code:
              $ref: '#/components/schemas/ErrorCode'
            message:
              type: string
            request_id:
              type: string
            details:
              type: object
              additionalProperties: true
    UploadSessionStyle:
      type: object
      additionalProperties: false
      required:
        - material_name
        - color_name
        - color_hex
        - shape_name
        - selected_material_id
        - selected_color_id
        - selected_shape_id
      properties:
        material_name:
          type: string
        color_name:
          type: string
        color_hex:
          type:
            - string
            - 'null'
        shape_name:
          type:
            - string
            - 'null'
        selected_material_id:
          type:
            - string
            - 'null'
        selected_color_id:
          type:
            - string
            - 'null'
        selected_shape_id:
          type:
            - string
            - 'null'
    Visualization:
      type: object
      additionalProperties: false
      required:
        - id
        - session_id
        - source
        - landing_id
        - landing_name
        - landing_slug
        - selected_material_id
        - selected_color_id
        - selected_shape_id
        - original_image_url
        - processed_image_url
        - processing_status
        - processing_started_at
        - processing_completed_at
        - processing_error
        - created_at
        - updated_at
      properties:
        id:
          type: string
        session_id:
          type: string
        source:
          type: string
          const: sales_visualizer
        landing_id:
          type:
            - string
            - 'null'
        landing_name:
          type:
            - string
            - 'null'
        landing_slug:
          type:
            - string
            - 'null'
        selected_material_id:
          type:
            - string
            - 'null'
        selected_color_id:
          type:
            - string
            - 'null'
        selected_shape_id:
          type:
            - string
            - 'null'
        original_image_url:
          type: string
        processed_image_url:
          type:
            - string
            - 'null'
        processing_status:
          $ref: '#/components/schemas/VisualizationProcessingStatus'
        processing_started_at:
          type:
            - string
            - 'null'
          format: date-time
        processing_completed_at:
          type:
            - string
            - 'null'
          format: date-time
        processing_error:
          type:
            - string
            - 'null'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    ErrorCode:
      type: string
      enum:
        - UNAUTHORIZED
        - FORBIDDEN
        - RATE_LIMITED
        - VALIDATION_ERROR
        - NOT_FOUND
        - CONFLICT
        - INSUFFICIENT_CREDITS
        - INTERNAL_ERROR
    VisualizationProcessingStatus:
      type: string
      enum:
        - pending
        - processing
        - completed
        - failed
  headers:
    RateLimitLimit:
      description: Cantidad máxima de solicitudes permitidas en la ventana actual.
      schema:
        type: string
    RateLimitRemaining:
      description: Solicitudes restantes en la ventana actual.
      schema:
        type: string
    RateLimitReset:
      description: Timestamp ISO cuando se reinicia la ventana actual de rate limit.
      schema:
        type: string
        format: date-time
    IdempotencyReplayed:
      description: >-
        Presente y true cuando se reprodujo una respuesta de escritura exitosa
        almacenada.
      schema:
        type: string
        enum:
          - 'true'
    RetryAfter:
      description: Segundos hasta que el llamador debería reintentar.
      schema:
        type: string
  responses:
    ValidationError:
      description: El payload, query o header requerido de la solicitud no es válido.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Unauthorized:
      description: API key ausente, malformada, revocada, eliminada o desconocida.
      headers:
        WWW-Authenticate:
          schema:
            type: string
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    InsufficientCredits:
      description: El workspace no puede cubrir el cargo de créditos de esta operación.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Forbidden:
      description: >-
        La API key no tiene un scope requerido, o el workspace no está activo.
        Un fallo de scope indica un scope faltante en `details.required_scope`.
        Cuando la búsqueda de la key rechaza la llamada,
        `details.missing_scopes` lista cada scope requerido que la key no tiene.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            missing_scope:
              summary: Una key de Solo lectura llama a una operación de escritura
              value:
                error:
                  code: FORBIDDEN
                  message: 'API key does not include the required scope: leads.write.'
                  request_id: req_123
                  details:
                    required_scope: leads.write
                    missing_scopes:
                      - leads.write
    Conflict:
      description: >-
        La solicitud entra en conflicto con la idempotencia o la identidad del
        evento externo.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    RateLimited:
      description: >-
        Rate limit excedido para esta key y endpoint o para el bucket de
        autenticación inválida.
      headers:
        X-RateLimit-Limit:
          $ref: '#/components/headers/RateLimitLimit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/RateLimitRemaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/RateLimitReset'
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    InternalError:
      description: Error interno de autenticación o del servidor.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  securitySchemes:
    ApiKeyBearer:
      type: http
      scheme: bearer
      bearerFormat: RoofKit API key
      description: 'Usa `Authorization: Bearer rk_live_...`.'

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.