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

# Create an attachment upload URL

> Create a short-lived, builder-scoped S3 PUT URL for an image up to 40 MiB. Upload the bytes directly with the declared Content-Type, then use the returned attachment reference when creating or bulk-upserting photos.

Requires a valid authenticated request for the builder. No resource-specific
scope is required.

Creates a short-lived, builder-scoped S3 upload URL for an image up to 40 MiB.
The endpoint returns `200 OK` because it creates an upload intent rather than a
persisted BuildPass resource.
Send the image bytes directly to the returned `uploadUrl` with `PUT` and the
exact returned `uploadHeaders`. Then use the returned
`{ key, regionId, type }` attachment reference when creating or bulk-upserting
photos.

The External API validates the image bytes, type, and final size when the
attachment reference is consumed.

## Sending the upload

Server-side clients should send every returned `uploadHeaders` value verbatim:

```ts theme={null}
await fetch(uploadUrl, {
  method: "PUT",
  headers: uploadHeaders,
  body: imageBytes,
});
```

Do not append parameters such as `charset` to `Content-Type`, because changing
a signed header makes S3 reject the request. Browser Fetch APIs do not allow
JavaScript to set `Content-Length`; in a browser, send the returned
`Content-Type`, use the original `File` as the body, and ensure `File.size`
exactly matches the `size` used to create the upload URL. The browser will
derive the matching content length.


## OpenAPI

````yaml POST /builders/{builderId}/attachments/presign
openapi: 3.0.0
info:
  title: BuildPass API
  description: >-
    Approved integrators can connect to the BuildPass API on behalf of builders
    to build connections between a wide range of construction platforms.
  version: 1.0.0
servers:
  - url: https://api.buildpass.global
    description: Production server
security:
  - OAuth2: []
paths:
  /builders/{builderId}/attachments/presign:
    post:
      tags:
        - Attachments
      summary: Create an attachment upload URL
      description: >-
        Create a short-lived, builder-scoped S3 PUT URL for an image up to 40
        MiB. Upload the bytes directly with the declared Content-Type, then use
        the returned attachment reference when creating or bulk-upserting
        photos.
      parameters:
        - name: builderId
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - contentType
                - fileName
                - size
                - type
              properties:
                contentType:
                  type: string
                  example: image/jpeg
                fileName:
                  type: string
                  example: site-photo.jpg
                size:
                  type: integer
                  minimum: 1
                  maximum: 41943040
                type:
                  type: string
                  enum:
                    - attachment
      responses:
        '200':
          description: Attachment upload URL created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AttachmentPresignResponse'
      security:
        - OAuth2: []
components:
  schemas:
    AttachmentPresignResponse:
      allOf:
        - $ref: '#/components/schemas/AttachmentUploadReference'
        - type: object
          required:
            - contentType
            - fileName
            - maxSize
            - uploadHeaders
            - uploadUrl
          properties:
            contentType:
              type: string
            fileName:
              type: string
            maxSize:
              type: integer
              example: 41943040
            uploadHeaders:
              type: object
              additionalProperties:
                type: string
              example:
                Content-Length: '41943040'
                Content-Type: image/jpeg
            uploadUrl:
              type: string
              format: uri
    AttachmentUploadReference:
      type: object
      required:
        - key
        - type
      properties:
        key:
          type: string
          example: external-uploads/ckbuilder123456789012345678/photo.jpg
        regionId:
          type: string
          nullable: true
          example: au1
        type:
          type: string
          enum:
            - attachment
  securitySchemes:
    OAuth2:
      type: oauth2
      flows:
        clientCredentials:
          tokenUrl: https://api.buildpass.global/oauth/token
          scopes:
            read:subcontractors: Read subcontractors
            write:subcontractors: Write subcontractors
            read:prequalifications: Read prequalifications
            write:prequalifications: Write prequalifications
            read:insurances: Read insurances
            write:insurances: Write insurances
            read:contacts: Read contacts
            read:swms: Read SWMS
            read:timesheets: Read timesheets
            read:inductions: Read inductions
            read:meetings: Read meetings
            write:meetings: Write meetings
            read:photos: Read photos and photo folders
            write:photos: Create, update, delete, and sync photos and photo folders

````