PPanel Edge

coupons

由 openapi.json 自动生成的 9 个端点及其请求、响应和权限元数据。

此参考由已发布 API 契约生成。字段、请求头和权限要求如下。

下载完整 OpenAPI 文档 · SHA-256: ccaa20cec11fad96e369b88073ce3608a5b071ce55d6dc03fa31df7b0f08c525

标识符和数据结构与公开契约一致,说明直接给出调用规则。共享模型见 数据模型.

GET /api/v1/admin/growth/coupons

GET /api/v1/admin/growth/coupons

List coupons (public codes and issued coupons)

{
  "parameters": [
    {
      "description": "Distribution; repeat the parameter for several values",
      "in": "query",
      "name": "distribution",
      "required": false,
      "schema": {
        "anyOf": [
          {
            "enum": [
              "public",
              "issued"
            ],
            "type": "string"
          },
          {
            "items": {
              "enum": [
                "public",
                "issued"
              ],
              "type": "string"
            },
            "type": "array"
          }
        ],
        "description": "Distribution; repeat the parameter for several values"
      }
    },
    {
      "description": "Status; repeat the parameter for several values",
      "in": "query",
      "name": "status",
      "required": false,
      "schema": {
        "anyOf": [
          {
            "enum": [
              "active",
              "disabled"
            ],
            "type": "string"
          },
          {
            "items": {
              "enum": [
                "active",
                "disabled"
              ],
              "type": "string"
            },
            "type": "array"
          }
        ],
        "description": "Status; repeat the parameter for several values"
      }
    },
    {
      "description": "Name (contains) or code text (prefix)",
      "in": "query",
      "name": "q",
      "required": false,
      "schema": {
        "description": "Name (contains) or code text (prefix)",
        "maxLength": 64,
        "minLength": 1,
        "type": "string"
      }
    },
    {
      "description": "Default created_at (desc); name (asc)",
      "in": "query",
      "name": "sort",
      "required": false,
      "schema": {
        "description": "Default created_at (desc); name (asc)",
        "enum": [
          "created_at",
          "name"
        ],
        "type": "string"
      }
    },
    {
      "description": "Return `total` (first page only)",
      "in": "query",
      "name": "include_total",
      "required": false,
      "schema": {
        "description": "Return `total` (first page only)",
        "enum": [
          "true",
          "false"
        ],
        "type": "string"
      }
    },
    {
      "description": "Default 20, at most 100",
      "in": "query",
      "name": "page_size",
      "required": false,
      "schema": {
        "description": "Default 20, at most 100",
        "maximum": 100,
        "minimum": 1,
        "type": "integer"
      }
    },
    {
      "description": "`next_cursor` of the previous page",
      "in": "query",
      "name": "cursor",
      "required": false,
      "schema": {
        "description": "`next_cursor` of the previous page",
        "maxLength": 512,
        "minLength": 1,
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/CouponPage"
          }
        }
      },
      "description": "A page of coupons"
    },
    "422": {
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      },
      "description": "Invalid filter or cursor"
    }
  },
  "summary": "List coupons (public codes and issued coupons)",
  "tags": [
    "coupons"
  ],
  "x-body": "none",
  "x-body-limit": 0,
  "x-permission": [
    "growth.coupon.manage",
    "growth.coupon.issue"
  ],
  "effectiveSecurity": []
}

POST /api/v1/admin/growth/coupons

POST /api/v1/admin/growth/coupons

Create a coupon

{
  "parameters": [
    {
      "description": "Idempotency-Key: 16–128 visible ASCII characters",
      "in": "header",
      "name": "idempotency-key",
      "required": true,
      "schema": {
        "description": "Idempotency-Key: 16–128 visible ASCII characters",
        "pattern": "^[\\x21-\\x7e]{16,128}$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/CouponCreate"
        }
      }
    },
    "required": true
  },
  "responses": {
    "201": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Coupon"
          }
        }
      },
      "description": "The coupon, with ETag",
      "headers": {
        "ETag": {
          "description": "Current resource version for If-Match.",
          "schema": {
            "type": "string"
          }
        }
      }
    },
    "409": {
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      },
      "description": "growth.code_taken or an Idempotency-Key conflict"
    },
    "422": {
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      },
      "description": "Validation failed (incl. growth.currency_mismatch, growth.plan_unknown field errors)"
    }
  },
  "summary": "Create a coupon",
  "tags": [
    "coupons"
  ],
  "x-audit": "growth.coupon.create",
  "x-body": "json",
  "x-body-limit": 524288,
  "x-concurrency": {
    "etag": true
  },
  "x-idempotency": "required",
  "x-permission": "growth.coupon.manage",
  "effectiveSecurity": []
}

DELETE /api/v1/admin/growth/coupons/{id}

DELETE /api/v1/admin/growth/coupons/{id}

Delete a coupon nothing was issued from or used (If-Match)

{
  "parameters": [
    {
      "in": "path",
      "name": "id",
      "required": true,
      "schema": {
        "format": "uuid",
        "type": "string"
      }
    },
    {
      "description": "Resource ETag; missing 428, malformed 412, stale 409.",
      "in": "header",
      "name": "If-Match",
      "required": true,
      "schema": {
        "type": "string"
      }
    }
  ],
  "responses": {
    "204": {
      "description": "Deleted"
    },
    "404": {
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      },
      "description": "No such coupon"
    },
    "409": {
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      },
      "description": "common.version_conflict or growth.coupon_in_use (disable it instead)"
    },
    "412": {
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      },
      "description": "Malformed If-Match"
    },
    "428": {
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      },
      "description": "If-Match missing"
    }
  },
  "summary": "Delete a coupon nothing was issued from or used (If-Match)",
  "tags": [
    "coupons"
  ],
  "x-audit": "growth.coupon.delete",
  "x-body": "none",
  "x-body-limit": 0,
  "x-concurrency": {
    "ifMatch": true
  },
  "x-idempotency": "optional",
  "x-permission": "growth.coupon.manage",
  "effectiveSecurity": []
}

GET /api/v1/admin/growth/coupons/{id}

GET /api/v1/admin/growth/coupons/{id}

One coupon with its usage

{
  "parameters": [
    {
      "in": "path",
      "name": "id",
      "required": true,
      "schema": {
        "format": "uuid",
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/CouponDetail"
          }
        }
      },
      "description": "The coupon, with ETag",
      "headers": {
        "ETag": {
          "description": "Current resource version for If-Match.",
          "schema": {
            "type": "string"
          }
        }
      }
    },
    "404": {
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      },
      "description": "No such coupon"
    }
  },
  "summary": "One coupon with its usage",
  "tags": [
    "coupons"
  ],
  "x-body": "none",
  "x-body-limit": 0,
  "x-concurrency": {
    "etag": true
  },
  "x-permission": [
    "growth.coupon.manage",
    "growth.coupon.issue"
  ],
  "effectiveSecurity": []
}

PATCH /api/v1/admin/growth/coupons/{id}

PATCH /api/v1/admin/growth/coupons/{id}

Update a coupon (If-Match); status disabled disables it. Coupons already issued keep their terms

{
  "parameters": [
    {
      "in": "path",
      "name": "id",
      "required": true,
      "schema": {
        "format": "uuid",
        "type": "string"
      }
    },
    {
      "description": "Resource ETag; missing 428, malformed 412, stale 409.",
      "in": "header",
      "name": "If-Match",
      "required": true,
      "schema": {
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/CouponPatch"
        }
      }
    },
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Coupon"
          }
        }
      },
      "description": "The coupon, with ETag",
      "headers": {
        "ETag": {
          "description": "Current resource version for If-Match.",
          "schema": {
            "type": "string"
          }
        }
      }
    },
    "404": {
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      },
      "description": "No such coupon"
    },
    "409": {
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      },
      "description": "common.version_conflict (with current) or growth.code_taken"
    },
    "412": {
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      },
      "description": "Malformed If-Match"
    },
    "422": {
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      },
      "description": "Validation failed"
    },
    "428": {
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      },
      "description": "If-Match missing"
    }
  },
  "summary": "Update a coupon (If-Match); status `disabled` disables it. Coupons already issued keep their terms",
  "tags": [
    "coupons"
  ],
  "x-audit": "growth.coupon.update",
  "x-body": "json",
  "x-body-limit": 524288,
  "x-concurrency": {
    "etag": true,
    "ifMatch": true
  },
  "x-idempotency": "optional",
  "x-permission": "growth.coupon.manage",
  "effectiveSecurity": []
}

POST /api/v1/admin/growth/coupons/{id}/issue

POST /api/v1/admin/growth/coupons/{id}/issue

Issue the coupon to users (≤ 100; larger audiences use a bulk operation)

{
  "parameters": [
    {
      "in": "path",
      "name": "id",
      "required": true,
      "schema": {
        "format": "uuid",
        "type": "string"
      }
    },
    {
      "description": "Idempotency-Key: 16–128 visible ASCII characters",
      "in": "header",
      "name": "idempotency-key",
      "required": true,
      "schema": {
        "description": "Idempotency-Key: 16–128 visible ASCII characters",
        "pattern": "^[\\x21-\\x7e]{16,128}$",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/CouponIssue"
        }
      }
    },
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/CouponIssueResult"
          }
        }
      },
      "description": "One result per user (growth.code_invalid, code_expired, code_exhausted, code_user_limit, common.not_found)"
    },
    "404": {
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      },
      "description": "No such coupon"
    },
    "409": {
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      },
      "description": "Idempotency-Key conflict"
    },
    "422": {
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      },
      "description": "Validation failed"
    }
  },
  "summary": "Issue the coupon to users (≤ 100; larger audiences use a bulk operation)",
  "tags": [
    "coupons"
  ],
  "x-audit": "growth.coupon.issue",
  "x-body": "json",
  "x-body-limit": 65536,
  "x-idempotency": "required",
  "x-permission": "growth.coupon.issue",
  "effectiveSecurity": []
}

POST /api/v1/admin/user-coupons/{id}/revoke

POST /api/v1/admin/user-coupons/{id}/revoke

Revoke an unused coupon (reason required)

{
  "parameters": [
    {
      "in": "path",
      "name": "id",
      "required": true,
      "schema": {
        "format": "uuid",
        "type": "string"
      }
    }
  ],
  "requestBody": {
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/UserCouponRevoke"
        }
      }
    },
    "required": true
  },
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/UserCoupon"
          }
        }
      },
      "description": "The revoked coupon"
    },
    "404": {
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      },
      "description": "No such coupon"
    },
    "409": {
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      },
      "description": "growth.coupon_unavailable: held by an order, used, expired or already revoked (with current)"
    },
    "422": {
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      },
      "description": "Validation failed"
    }
  },
  "summary": "Revoke an unused coupon (reason required)",
  "tags": [
    "coupons"
  ],
  "x-audit": "growth.user_coupon.revoke",
  "x-body": "json",
  "x-body-limit": 65536,
  "x-idempotency": "optional",
  "x-permission": "growth.coupon.issue",
  "effectiveSecurity": []
}

GET /api/v1/admin/users/{id}/coupons

GET /api/v1/admin/users/{id}/coupons

A user's coupons and code uses, newest first

{
  "parameters": [
    {
      "in": "path",
      "name": "id",
      "required": true,
      "schema": {
        "format": "uuid",
        "type": "string"
      }
    },
    {
      "description": "Status; repeat the parameter for several values",
      "in": "query",
      "name": "status",
      "required": false,
      "schema": {
        "anyOf": [
          {
            "enum": [
              "available",
              "reserved",
              "consumed",
              "released",
              "reversed",
              "expired",
              "revoked"
            ],
            "type": "string"
          },
          {
            "items": {
              "enum": [
                "available",
                "reserved",
                "consumed",
                "released",
                "reversed",
                "expired",
                "revoked"
              ],
              "type": "string"
            },
            "type": "array"
          }
        ],
        "description": "Status; repeat the parameter for several values"
      }
    },
    {
      "description": "Return `total` (first page only)",
      "in": "query",
      "name": "include_total",
      "required": false,
      "schema": {
        "description": "Return `total` (first page only)",
        "enum": [
          "true",
          "false"
        ],
        "type": "string"
      }
    },
    {
      "description": "Default 20, at most 100",
      "in": "query",
      "name": "page_size",
      "required": false,
      "schema": {
        "description": "Default 20, at most 100",
        "maximum": 100,
        "minimum": 1,
        "type": "integer"
      }
    },
    {
      "description": "`next_cursor` of the previous page",
      "in": "query",
      "name": "cursor",
      "required": false,
      "schema": {
        "description": "`next_cursor` of the previous page",
        "maxLength": 512,
        "minLength": 1,
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/UserCouponPage"
          }
        }
      },
      "description": "A page of the user’s coupons"
    },
    "422": {
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      },
      "description": "Invalid filter or cursor"
    }
  },
  "summary": "A user's coupons and code uses, newest first",
  "tags": [
    "coupons"
  ],
  "x-body": "none",
  "x-body-limit": 0,
  "x-permission": "growth.coupon.issue",
  "effectiveSecurity": []
}

GET /api/v1/me/coupons

GET /api/v1/me/coupons

My coupons: available (default), used or expired

{
  "parameters": [
    {
      "description": "available (default), used or expired",
      "in": "query",
      "name": "status",
      "required": false,
      "schema": {
        "description": "available (default), used or expired",
        "enum": [
          "available",
          "used",
          "expired"
        ],
        "type": "string"
      }
    },
    {
      "description": "Preferred locale; else Accept-Language",
      "in": "query",
      "name": "locale",
      "required": false,
      "schema": {
        "description": "Preferred locale; else Accept-Language",
        "pattern": "^[a-z]{2,3}(-[A-Z][a-z]{3})?(-([A-Z]{2}|\\d{3}))?$",
        "type": "string"
      }
    },
    {
      "description": "Default 20, at most 100",
      "in": "query",
      "name": "page_size",
      "required": false,
      "schema": {
        "description": "Default 20, at most 100",
        "maximum": 100,
        "minimum": 1,
        "type": "integer"
      }
    },
    {
      "description": "`next_cursor` of the previous page",
      "in": "query",
      "name": "cursor",
      "required": false,
      "schema": {
        "description": "`next_cursor` of the previous page",
        "maxLength": 512,
        "minLength": 1,
        "type": "string"
      }
    }
  ],
  "responses": {
    "200": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/MyCouponPage"
          }
        }
      },
      "description": "A page of my coupons, with Content-Language"
    },
    "422": {
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      },
      "description": "Invalid cursor"
    }
  },
  "summary": "My coupons: available (default), used or expired",
  "tags": [
    "coupons"
  ],
  "x-body": "none",
  "x-body-limit": 0,
  "effectiveSecurity": []
}