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

# 创建产品

> 创建一个产品及其一个价格。

请使用属于目标组织、且为全部权限或勾选了 `products:products:write` 权限的 API 密钥进行认证。只有 `Owner` 和 `Admin` 角色可以授予该权限。

* 参数与控制台中创建产品相同：一个产品，一个价格。
* 与控制台不同，该接口不会创建支付链接。如需可分享的链接，请为该产品[创建支付链接](https://docs.anyway.sh/zh/api-reference/endpoint/create-product-payment-link.md)，或通过结账会话销售该价格（见下文）。
* 必填请求头 `Idempotency-Key`（1–255 个 ASCII 字符，范围为 `0x21` 至 `0x7E`，不允许空格），规则与结账会话相同。相同的键加相同的请求体，返回第一次创建的产品（`201`），不会重复创建。相同的键但请求体不同，返回 `409`。如果该键创建的产品之后被删除，重试也会返回 `409`，请换一个新的键。
* `pricingType` 为 `ONE_TIME` 或 `SUBSCRIPTION`。`pricing` 是以主单位表示的字符串，如 `"19.99"`。不传 `pricing` 即为灵活的“自定义金额”价格，仅限 `ONE_TIME`，此时 `minAmount` 和 `maxAmount` 可选。
* `SUBSCRIPTION` 价格必须提供 `billingInterval`（`DAY`、`MONTH` 或 `YEAR`）。`billingIntervalCount` 可选，默认为 `1`。
* `status` 为 `PUBLISHED`（默认）、`DRAFT` 或 `ARCHIVED`。`DRAFT` 状态的产品之后无法[发布](https://docs.anyway.sh/zh/api-reference/endpoint/publish-product.md)或[归档](https://docs.anyway.sh/zh/api-reference/endpoint/archive-product.md)。如果暂时不想上架，请以 `ARCHIVED` 状态创建，准备好后再发布。
* 未知字段会被拒绝，返回 `400`。
* 销售固定价格时，请将返回的 `pricing.pricingId` 作为 `pricingId` 传给[创建结账会话](https://docs.anyway.sh/zh/api-reference/checkout-sessions.md)。结账会话不支持灵活金额；灵活金额请[创建支付链接](https://docs.anyway.sh/zh/api-reference/endpoint/create-product-payment-link.md)。

| 状态码 | 错误码 | 含义 |
| - | - | - |
| `400` | | 校验失败：货币无效、订阅缺少计费周期、灵活价格的订阅、金额小于或等于 0、未知字段，或缺少 `Idempotency-Key` 或其无效。 |
| `401` | | API 密钥缺失或无效。 |
| `403` | `INSUFFICIENT_SCOPE` | 密钥缺少 `products:products:write`。 |
| `409` | `PRODUCT_CONFLICT` | `Idempotency-Key` 已用于不同的请求体，或它创建的产品已被删除。 |
| `413` | `PAYLOAD_TOO_LARGE` | 请求体超过 64 KB。 |


## OpenAPI

````yaml api-reference/openapi.json POST /v1/product
openapi: 3.0.3
info:
  description: >-
    Organization-scoped commerce API for merchant backends: create and manage
    checkout sessions, and query commerce records.
  title: Anyway Merchant API
  contact: {}
  version: '1.0'
  x-source: anyway-backend-go
servers:
  - url: https://merchant-api-prod.anyway.sh
security: []
paths:
  /v1/product:
    post:
      tags:
        - products
      summary: Create a product
      description: >-
        Creates one product with one price, the same as creating a product in
        the dashboard. Requires Full access or the `products:products:write`
        permission. Send a unique `Idempotency-Key` (required): the same key
        with the same body returns the product created the first time (201); the
        same key with a different body, or a product deleted since, returns 409
        PRODUCT_CONFLICT. Unknown request fields return 400. To sell a fixed
        price, pass the returned `pricing.pricingId` as `pricingId` to `POST
        /v1/checkout-sessions`; a flexible amount needs a payment link.
      parameters:
        - description: >-
            Unique creation request key: 1-255 ASCII characters in the range
            0x21-0x7E (no spaces or control characters)
          name: Idempotency-Key
          in: header
          required: true
          schema:
            type: string
            minLength: 1
            maxLength: 255
      requestBody:
        required: true
        description: Product and price
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/product.CreateRequest'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/response.ApiResponse-product_CreatedProductResponse
        '400':
          description: >-
            Bad Request. Invalid currency, a subscription without a billing
            interval, a flexible subscription, an amount of 0 or less, an
            unknown field, or an invalid Idempotency-Key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/response.ApiResponse-any'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/response.ApiResponse-any'
        '403':
          description: >-
            Forbidden. The API key lacks the required permission
            (INSUFFICIENT_SCOPE).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/response.ApiResponse-any'
        '409':
          description: >-
            Conflict. The Idempotency-Key was already used with a different body
            (PRODUCT_CONFLICT).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/response.ApiResponse-any'
        '413':
          description: Request body larger than 64 KB (`PAYLOAD_TOO_LARGE`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/response.ApiResponse-any'
      security:
        - APIKeyAuth: []
components:
  schemas:
    product.CreateRequest:
      type: object
      required:
        - name
        - pricingType
        - currency
      properties:
        name:
          type: string
          description: Product name
        description:
          type: string
        pricingType:
          $ref: '#/components/schemas/product.PricingType'
        currency:
          type: string
          description: Currency code, for example USD
        pricing:
          type: string
          description: >-
            Price in major units, for example "19.99". Omit for a flexible (pay
            what you want) price, which is ONE_TIME only.
        minAmount:
          description: Optional minimum for a flexible price (ONE_TIME only)
          type: number
        maxAmount:
          description: Optional maximum for a flexible price (ONE_TIME only)
          type: number
        pricingName:
          type: string
          description: Name of the price
        billingInterval:
          $ref: '#/components/schemas/product.BillingInterval'
        billingIntervalCount:
          type: integer
          description: Number of intervals between charges (SUBSCRIPTION). Defaults to 1.
        status:
          type: string
          enum:
            - PUBLISHED
            - DRAFT
            - ARCHIVED
          default: PUBLISHED
    response.ApiResponse-product_CreatedProductResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/product.CreatedProductResponse'
        error:
          $ref: '#/components/schemas/response.ErrorDetail'
        message:
          type: string
        success:
          type: boolean
    response.ApiResponse-any:
      type: object
      properties:
        data: {}
        error:
          $ref: '#/components/schemas/response.ErrorDetail'
        message:
          type: string
        success:
          type: boolean
    product.PricingType:
      type: string
      enum:
        - SUBSCRIPTION
        - ONE_TIME
      x-enum-varnames:
        - PricingTypeSubscription
        - PricingTypeOneTime
    product.BillingInterval:
      type: string
      enum:
        - DAY
        - MONTH
        - YEAR
      x-enum-varnames:
        - BillingIntervalDay
        - BillingIntervalMonth
        - BillingIntervalYear
    product.CreatedProductResponse:
      type: object
      properties:
        createdAt:
          type: string
        description:
          type: string
        id:
          description: 'Deprecated: use productId.'
          type: string
          deprecated: true
        name:
          type: string
        orgId:
          type: string
        paymentLinks:
          type: array
          items:
            $ref: '#/components/schemas/product.PaymentLinkResponse'
        productId:
          type: string
        status:
          type: string
        updatedAt:
          type: string
        pricing:
          $ref: '#/components/schemas/product.CreatedPricing'
    response.ErrorDetail:
      type: object
      properties:
        code:
          type: string
        message:
          type: string
    product.PaymentLinkResponse:
      type: object
      properties:
        amount:
          type: number
          nullable: true
        createdAt:
          type: string
        currency:
          type: string
        flexibleAmount:
          type: boolean
        isActive:
          type: boolean
        name:
          type: string
        paymentLinkUrl:
          type: string
        pricingId:
          type: string
        pricingType:
          type: string
        provider:
          type: string
        title:
          type: string
        description:
          type: string
        minAmount:
          type: number
          nullable: true
        maxAmount:
          type: number
          nullable: true
        successUrl:
          type: string
          description: >-
            Where the customer is sent after paying. Empty when the Anyway
            receipt is used.
    product.CreatedPricing:
      type: object
      properties:
        pricingId:
          type: string
        currency:
          type: string
        pricing:
          type: number
          description: Price in major units. Absent for a flexible price.
        minAmount:
          type: number
        maxAmount:
          type: number
        pricingType:
          $ref: '#/components/schemas/product.PricingType'
        billingInterval:
          $ref: '#/components/schemas/product.BillingInterval'
        billingIntervalCount:
          type: integer
        pricingName:
          type: string
          description: Price name, omitted when empty.
  securitySchemes:
    APIKeyAuth:
      description: 'Merchant API key (format: ak_BASE64)'
      type: apiKey
      name: X-API-Key
      in: header

````

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