---
title: "Assign resources to a shared template page"
method: POST
path: "/projects/{projectId}/template-assignments/{pageId}"
tags: ["Assignments"]
---

# Assign resources to a shared template page

`POST /projects/{projectId}/template-assignments/{pageId}`

## Request

- Base URL: `https://studio.weaverse.io/api/v1/content`
- URL: `https://studio.weaverse.io/api/v1/content/projects/{projectId}/template-assignments/{pageId}`
- Auth: HTTP bearer

Assigns many Shopify resources to one existing template page: the shared-template model (one page, many assignments). Each resource becomes its own assignment row pointing at `pageId`, so the template content stays shared, not copied. To create an independent, editable copy per resource, use `POST /projects/{projectId}/pages` instead.

- The target must be a live page assigned to this project. Its type is derived from its existing assignments and must be resource-backed (`PRODUCT`, `COLLECTION`, `PAGE`, `BLOG`, `ARTICLE`); any other type returns `400`.
- Send 1-100 entries in `assignments`. `handle` is the Shopify resource handle (trimmed, kept verbatim); `locale` defaults to the global assignment (`""`).
- A resource already assigned to this page is an idempotent no-op, reported under `existing`.
- **All-or-nothing.** Every handle is checked first. If any handle already belongs to a different live page, the whole request returns `409 CONFLICT` with the clashing handles in `details.conflicts`, and nothing is written. A resource is never repointed away from another page: unassign it from its current template, then retry.
- New rows are created in a single transaction. All lookups and writes are scoped to `projectId`.

Required scope: `content:write`

## Path parameters

- `projectId` string, required
- `pageId` string, required

## Request body

- TemplateAssignmentRequest
  - `assignments` object[], required: Shopify resources to assign to this template page. Each becomes its own assignment row pointing at the same page — no page copies are created.
    - `handle` string, required: Shopify resource handle (trimmed, kept verbatim).
    - `shopifyResourceId` string: Optional non-empty Shopify resource id (gid) bound to the assignment.
    - `locale` string: Optional assignment locale. Defaults to the global/default assignment ("").

## Response `200`

Assignments applied. `created` = new rows; `existing` = idempotent no-ops.

- TemplateAssignmentResult
  - `object` 'template_assignments'
  - `pageId` string
  - `type` string
  - `requested` integer
  - `created` object[]: Newly created assignment rows pointing at this page.
    - `handle` string
    - `locale` string
    - `assignmentId` string
  - `existing` object[]: Resources already assigned to this page (idempotent no-op).
    - `handle` string
    - `locale` string
    - `assignmentId` string

## Other responses

- `400`: Invalid params, or the page cannot carry resource assignments
- `401`: Unauthorized
- `403`: Forbidden
- `404`: Project or template page not found in this project
- `405`: Method not allowed
- `409`: A handle already belongs to a different live page (or a concurrent write won the race); nothing was assigned. `details.conflicts` lists the clashing handles.
- `500`: Unexpected server error

---

[API](https://skmtc.dev/weaverse/apis/weaverse-content-api.md) - [All operations](https://skmtc.dev/weaverse/apis/weaverse-content-api/llms.txt) - [OpenAPI document](https://skmtc.dev/weaverse/apis/weaverse-content-api/revisions/d189794169bb?raw)
