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

# Create Link

> Creates a new link in the current workspace. The API enforces plan limits and feature availability for the authenticated organization.

Create a new link inside the workspace tied to your API token. The endpoint shares logic with the dashboard, so all plan limits, QR quotas, and custom domain validations apply here too.

<Tip>
  `domain_id` must point to a domain that is active for the organization and visible to the authenticated workspace. Use [`POST /v1/get`](./get-resources) with `resource: "domain"` to retrieve the allowed IDs.
</Tip>

### Request body

| Field | Type | Required | Description |
| - | - | - | - |
| `url` | string (URI) | ✅ | Destination URL. Missing schemes are automatically prefixed with `https://`. |
| `domain_id` | integer | ✅ | Domain that will host the link. The API validates ownership and plan eligibility. |
| `workspace_id` | integer | | Overrides the default workspace inferred from the token. Useful when a key has access to multiple workspaces. |
| `title` | string | | Optional human-friendly title for reporting. |
| `custom_slug` | string | | Branded slug appended to the domain instead of an auto-generated code. Plan limits and reserved-word checks apply. |
| `folder_id` | integer | | Assigns the link to an existing folder. |
| `param` | object | | Additional query parameters appended to the destination URL (for example UTM tags). Empty values are stripped automatically. |
| `generate_qr` | boolean | | Generates and returns a base64-encoded QR code alongside the link. |
| `enable_tracking` | boolean | | Links the URL to a tracking pixel. Requires `pixel_id`. |
| `pixel_id` | integer | | Pixel identifier retrieved via the resources endpoint. |
| `redirect_type` | integer (301 or 302) | | Controls whether redirects are permanent or temporary. Defaults to `301`. |
| `link_cloak` | boolean | | Cloaks the destination URL. |
| `hide_referer` | boolean | | Removes the referrer header so destination sites do not see the original source. |
| `with_password` | boolean | | Protects the link behind a password. Pair with `url_password`. |
| `url_password` | string | | Password required to resolve the link when `with_password` is true. |
| `r`, `g`, `b` | integer (0-255) | | RGB color channels used when a QR code is generated. |
| `uploaded_logo_type` | enum(`none`, `custom`, `uploaded`) | | Controls the logo embedded inside generated QR codes. `custom` reuses the organization logo, `uploaded` expects `uploaded_logo_data`. |
| `uploaded_logo_data` | base64 string | | Base64-encoded image used for the QR logo when `uploaded_logo_type` is `uploaded`. |
| `social_share_title` | string | | Overrides the OpenGraph title used when the link is shared. |
| `social_share_description` | string | | Overrides the OpenGraph description. |
| `social_share_image_data` | base64 string | | Custom social preview image (PNG/JPEG/SVG). |
| `tag_ids` | integer\[] | | IDs of the tags to attach to the new link. Tags must belong to the same workspace and organization; unknown IDs are ignored. A JSON-encoded string such as `"[12,18]"` is also accepted. |
| `notes` | string | | Add a custom note to the new link. 300 characters max. |

> Need to attach a stored social preview image that already lives on ShortPen? Set `social_share_image_data` to the base64 payload provided by previous uploads or send the legacy `social_share_image_session` value.

### Response highlights

* `data.link` — fully qualified link combining the selected domain and slug.
* `data.short_url` — same value as `link`. **Deprecated** — will be removed in a future version; migrate to `data.link`.
* `data.qr` — base64-encoded PNG when `generate_qr` evaluates to true; otherwise `null`.
* `data.created` — `true` for newly created links.

If a monthly quota (links, QR codes, custom slugs, etc.) has been reached, the API responds with HTTP 429 and a descriptive `message` so you can trigger a plan upgrade workflow or notify an operator.

<Note>
  Need to update an existing link instead? Use the [Edit Link](./edit-link) endpoint with `PUT` or `PATCH /v1/links`.
</Note>


## OpenAPI

````yaml POST /v1/generate
openapi: 3.1.0
info:
  title: ShortPen API
  version: 1.0.0
  description: >-
    Create branded links, fetch organization resources, and pull analytics
    programmatically with the ShortPen REST API.
servers:
  - url: https://{environment}.shortpen.com
    description: ShortPen API host
    variables:
      environment:
        default: api
        enum:
          - api
          - staging-api
security: []
tags:
  - name: Core
    description: Utility endpoints for checking service health.
  - name: Authentication
    description: Endpoints that return identity, limits, and feature availability.
  - name: Links
    description: Create, edit, and list links and their auxiliary assets like QR codes.
  - name: Resources
    description: >-
      Lookup supporting entities such as domains, workspaces, folders, and
      pixels.
  - name: Analytics
    description: Retrieve click analytics and raw tracking events.
paths:
  /v1/generate:
    post:
      tags:
        - Links
      summary: Create a link
      description: >-
        Creates a new link in the current workspace. The API enforces plan
        limits and feature availability for the authenticated organization.
      operationId: createLink
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateLinkRequest'
            examples:
              basic:
                summary: Basic link
                value:
                  url: https://example.com/launch
                  domain_id: 1
                  workspace_id: 24
                  title: Launch landing page
              withCustomizations:
                summary: Custom slug, QR, and tracking
                value:
                  url: https://example.com/summer-campaign
                  domain_id: 3
                  workspace_id: 24
                  custom_slug: summer-2025
                  generate_qr: true
                  enable_tracking: true
                  pixel_id: 12
                  param:
                    utm_source: newsletter
                    utm_medium: email
                    utm_campaign: summer-launch
      responses:
        '200':
          description: Link created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LinkResponse'
        '400':
          description: Validation error or invalid domain
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Missing or invalid token
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Monthly link or feature limit reached
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - bearerAuth: []
components:
  schemas:
    CreateLinkRequest:
      allOf:
        - $ref: '#/components/schemas/LinkFieldsMixin'
      required:
        - url
        - domain_id
    LinkResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        status_code:
          type: integer
          example: 200
        message:
          type: string
          example: ''
        data:
          $ref: '#/components/schemas/LinkData'
      required:
        - success
        - status_code
        - data
    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          example: false
        status_code:
          type: integer
          example: 401
        message:
          type: string
          example: There was an error while processing your request.
        data:
          description: Optional payload returned for additional context.
          nullable: true
      required:
        - success
        - status_code
        - message
    LinkFieldsMixin:
      type: object
      description: Common fields shared between link creation and editing.
      properties:
        url:
          type: string
          format: uri
          description: Destination URL the link redirects to.
          example: https://example.com/launch
        domain_id:
          type: integer
          description: ID of the domain that hosts the link.
        workspace_id:
          type: integer
          description: >-
            Workspace ID. Defaults to the first workspace associated with the
            organization when omitted.
        title:
          type: string
          description: Optional human-friendly title for the link.
        custom_slug:
          type: string
          description: >-
            Custom slug appended to the domain instead of an auto-generated
            code.
        folder_id:
          type: integer
          description: Folder to assign the link to.
        param:
          type: object
          description: Query parameters appended to the destination URL.
          additionalProperties:
            type: string
        generate_qr:
          type: boolean
          description: Whether to create a QR code for the link.
          default: false
        enable_tracking:
          type: boolean
          description: >-
            Set to true to associate the link with the specified pixel for event
            tracking.
          default: false
        pixel_id:
          type: integer
          description: Pixel ID used when tracking is enabled.
        redirect_type:
          type: integer
          enum:
            - 301
            - 302
          description: HTTP redirect status applied when visitors follow the link.
          default: 301
        link_cloak:
          type: boolean
          description: If true, cloaks the destination URL.
        hide_referer:
          type: boolean
          description: If true, removes the referrer header for visitors.
        with_password:
          type: boolean
          description: Protects the link behind a password.
        url_password:
          type: string
          description: Password required when `with_password` is true.
        r:
          type: integer
          minimum: 0
          maximum: 255
          description: Red channel used when generating QR codes.
          example: 45
        g:
          type: integer
          minimum: 0
          maximum: 255
          description: Green channel used when generating QR codes.
          example: 151
        b:
          type: integer
          minimum: 0
          maximum: 255
          description: Blue channel used when generating QR codes.
          example: 123
        uploaded_logo_type:
          type: string
          description: Controls which logo is embedded inside generated QR codes.
          enum:
            - none
            - custom
            - uploaded
          default: none
        uploaded_logo_data:
          type: string
          format: byte
          description: Base64-encoded file used when `uploaded_logo_type` is `uploaded`.
        social_share_title:
          type: string
          description: Overrides the title shown in social previews.
        social_share_description:
          type: string
          description: Overrides the description shown in social previews.
        social_share_image_data:
          type: string
          format: byte
          description: Base64-encoded image used for the social preview.
        tag_ids:
          type: array
          items:
            type: integer
          description: >-
            IDs of the tags to associate with the link. On creation the listed
            tags are attached. On edit, sending this field replaces the link's
            tags with the supplied set — an empty array clears every tag, while
            omitting the field entirely leaves existing tags untouched. Tags
            must belong to the same workspace and organization; unknown IDs are
            ignored. A JSON-encoded string of IDs (e.g. "[12,18]") is also
            accepted for backwards compatibility.
          example:
            - 12
            - 18
        notes:
          type: string
          description: Overrides the private notes shown in ShortPen Links/QRs list.
    LinkData:
      type: object
      properties:
        link:
          type: string
          format: uri
          description: Fully qualified link combining the selected domain and slug.
          example: https://go.shortpen.com/summer-2025
        short_url:
          type: string
          format: uri
          description: >-
            Deprecated — use `link` instead. Will be removed in a future
            version.
          example: https://go.shortpen.com/summer-2025
          deprecated: true
        qr:
          type: string
          nullable: true
          description: Base64-encoded PNG image for the generated QR code.
        created:
          type: boolean
          description: >-
            `true` when a new link was created, `false` when an existing link
            was updated.
      required:
        - link
        - short_url
        - created
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: Personal Access Token

````

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