---
title: "Upload Source Table"
method: POST
path: "/v1/source_tables/upload"
tags: ["source_tables"]
---

# Upload Source Table

`POST /v1/source_tables/upload`

Register an uploaded parquet relation and hand back a presigned PUT.

One call does both server-side halves of the upload flow: mint a presigned PUT
into the platform's own bucket and persist the ``source_table`` row pointing at
where the bytes will land. The caller then PUTs the parquet to ``upload_url``.

The row is a *managed* upload: ``connector_type`` is ``file_upload`` and
``credential_id`` is NULL — there is no per-upload connector. Reads resolve the
platform's own S3 credentials (``S3ConnectorService.managed_config``) off that
sentinel.

The parquet footer is *not* validated here (unlike ``create_source_table``) —
the object does not exist yet; the schema is derived on demand once the upload
lands.

## Request body

- CreateSourceTableUploadRequest
  - `table_name` string, required

## Response `201`

Successful Response

- CreateSourceTableUploadResponse
  - `source_table` SourceTableResponse, required
    - `id` union, required
      - string, uuid
      - string
    - `short_id` string, required
    - `table_name` string, required
    - `connector_type` 's3' | 'snowflake' | 'databricks' | 'file_upload', required
    - `location` union, required
      - S3SourceLocation
        - `uri` string, uri, required
        - `file_format` 'parquet'
      - SnowflakeSourceLocation
        - `database` string, required
        - `schema_name` string, required
        - `table_name` string, required
  - `upload_url` string, required
  - `content_type` string, required
  - `expires_in` integer, required

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.dev/outerproduct/apis/outerproduct-api.md) · [All operations](https://skmtc.dev/outerproduct/apis/outerproduct-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/outerproduct/outerproduct-api/revisions/a49cdafe7fba/schema)
