---
title: "Create a discount code (site admin)"
method: POST
path: "/discount-codes"
tags: ["Discount codes"]
---

# Create a discount code (site admin)

`POST /discount-codes`

## Request

- Base URL: `https://app.pencil.ink/api/v1`
- URL: `https://app.pencil.ink/api/v1/discount-codes`
- Auth: HTTP bearer

Requires a write key with explicit discount-management permission and a current site-admin creator. Single-use; terms editable until redemption starts. Omit recipient IDs for shareable signup redemption. Does not enable global redemption or call Stripe. On uncertain completion, GET the same code before retrying.

## Request body

- object
  - `code` string, required: Unique code, 6–64 letters, digits, dashes or underscores; normalized to uppercase.
  - `label` string, required
  - `percentOff` integer, required
  - `duration` 'once' | 'repeating' | 'forever', required
  - `months` integer: Required for repeating duration.
  - `planKey` 'pro' | 'team', required: USD monthly base subscription only; excludes AI usage.
  - `targetOrgId` string: Optional recipient organization. Recipient-targeted codes are single-use.
  - `targetUserId` string: Optional recipient user; mutually exclusive with targetOrgId.
  - `maxRedemptions` integer, nullable: Maximum distinct organization redemptions. Null means unlimited. Defaults to 1 and must be 1 for recipient-targeted codes.
  - `redeemFrom` number: Optional redemption start, Unix milliseconds.
  - `redeemBy` number: Optional future redemption deadline, Unix milliseconds.

## Response `201`

The resource.

- object
  - `data` DiscountCode
    - `code` string: Unique code, 6–64 letters, digits, dashes or underscores; normalized to uppercase.
    - `label` string
    - `percentOff` integer
    - `duration` 'once' | 'repeating' | 'forever'
    - `months` integer: Required for repeating duration.
    - `planKey` 'pro' | 'team': USD monthly base subscription only; excludes AI usage.
    - `targetOrgId` string: Optional recipient organization. Recipient-targeted codes are single-use.
    - `targetUserId` string: Optional recipient user; mutually exclusive with targetOrgId.
    - `maxRedemptions` integer, nullable: Maximum distinct organization redemptions. Null means unlimited. Defaults to 1 and must be 1 for recipient-targeted codes.
    - `redeemFrom` number: Optional redemption start, Unix milliseconds.
    - `redeemBy` number: Optional future redemption deadline, Unix milliseconds.
    - `_id` string
    - `_creationTime` number
    - `active` boolean
    - `createdBy` string
    - `createdAt` number

## Other responses

- `400`: Malformed request or invalid field (`validation_error`).
- `401`: Missing or invalid API key (`unauthorized`).
- `403`: The key is read-only and may not write (`forbidden`).
- `404`: Resource not found in this org (`not_found`).
- `409`: Code already exists.
- `429`: Rate limit exceeded (`rate_limited`).

---

[API](https://skmtc.dev/pencil/apis/pencil-public-api.md) · [All operations](https://skmtc.dev/pencil/apis/pencil-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/pencil/apis/pencil-public-api/revisions/2b842698b76d?raw)
