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

# Redirect a legacy (PartnerStack) link

> Backwards-compatible redirect for links created in a previous affiliate tool (e.g. PartnerStack) that were migrated into Introw. During a migration every old link is mapped to its newly generated Introw affiliate link. Point your old links at this endpoint with a redirect rule on your side; Introw resolves the mapping and `302`-redirects to the matching Introw link (`/r/{code}`), which then records the click, sets the first-party `_introw_aff` attribution cookie, and forwards the visitor to the campaign destination.

**No key required.** The lookup is keyed by the globally-unique original URL, so no API key or publishable key is needed.

**How the original URL is captured**, in priority order:
1. The `u` query parameter (recommended): your redirect rule forwards the original absolute URL, e.g. `https://api.introw.io/api/v1/affiliate/legacy-redirect?u=https%3A%2F%2Fgo.acme.com%2Fabc`.
2. The `X-Original-URL` or `X-Forwarded-Uri` request header (reverse-proxy / CNAME setups).
3. The `Referer` header (fallback).

The captured URL is normalized before lookup (scheme and host lowercased, default ports and a trailing slash stripped, query params sorted; path and query values stay case-sensitive), so the value you forward does not need to match byte-for-byte.



## OpenAPI

````yaml /openapi.json get /api/v1/affiliate/legacy-redirect
openapi: 3.1.0
info:
  title: Introw API
  version: '2026-05-20'
  description: >-
    Customer-facing API for Introw. Manage partners, delegate commission payout
    operations to your finance software, embed the partner portal in your
    product with pre-authenticated sessions, ingest affiliate conversions, and
    trigger on-demand CRM object syncs.
servers:
  - url: https://api.introw.io
  - url: https://api.staging.introw.io
security:
  - ApiKeyAuth: []
tags:
  - name: Partners
    description: >-
      Read and manage partners for the organisation associated with the
      authenticated API key.
  - name: Payouts
    description: >-
      Read and update commission payouts. Delegate approval, scheduling, and
      payment status to your ERP or accounts-payable stack.
  - name: Commission lines
    description: >-
      Create, read, update, decline, and detach commission line items. Lines can
      live in the pending pool or be attached to a payout.
  - name: Collaboration
    description: >-
      Post comments on partner portals, deals, tasks, form submissions, and
      payouts, with rich text, internal visibility, and thread replies. Comments
      trigger the same notifications, workflows, and CRM note sync as comments
      posted in the app.
  - name: Forms
    description: >-
      Submit Introw forms server-to-server. Register deals, share leads, or file
      any other form submission from your own systems; submissions run the exact
      same automation and acceptance pipeline as portal submissions. Read a
      form's field schema first to discover the field ids, value shapes, and
      allowed values to send.
  - name: Auth
    description: >-
      Create pre-authenticated partner portal sessions. Exchange a visitor email
      for a short-lived, single-use portal URL that you embed in an iframe
      inside your own product: one login, fully branded, no login screen for the
      partner.
  - name: Affiliate
    description: >-
      Ingest affiliate conversions from your backend or directly from the
      browser via affiliate.js. Every conversion is anchored to a signed,
      server-side click token (the first-party `_introw_aff` cookie),
      deduplicated, and mapped onto a campaign form submission, so attribution
      cannot be forged or double-counted.
  - name: CRM
    description: >-
      Trigger on-demand syncs of individual CRM objects. Introw already syncs
      every object automatically about every 15 minutes; use this only when a
      change must be reflected in Introw immediately, e.g. a workflow mutated
      the record and its result must persist in Introw right away.
paths:
  /api/v1/affiliate/legacy-redirect:
    get:
      tags:
        - Affiliate
      summary: Redirect a legacy (PartnerStack) link
      description: >-
        Backwards-compatible redirect for links created in a previous affiliate
        tool (e.g. PartnerStack) that were migrated into Introw. During a
        migration every old link is mapped to its newly generated Introw
        affiliate link. Point your old links at this endpoint with a redirect
        rule on your side; Introw resolves the mapping and `302`-redirects to
        the matching Introw link (`/r/{code}`), which then records the click,
        sets the first-party `_introw_aff` attribution cookie, and forwards the
        visitor to the campaign destination.


        **No key required.** The lookup is keyed by the globally-unique original
        URL, so no API key or publishable key is needed.


        **How the original URL is captured**, in priority order:

        1. The `u` query parameter (recommended): your redirect rule forwards
        the original absolute URL, e.g.
        `https://api.introw.io/api/v1/affiliate/legacy-redirect?u=https%3A%2F%2Fgo.acme.com%2Fabc`.

        2. The `X-Original-URL` or `X-Forwarded-Uri` request header
        (reverse-proxy / CNAME setups).

        3. The `Referer` header (fallback).


        The captured URL is normalized before lookup (scheme and host
        lowercased, default ports and a trailing slash stripped, query params
        sorted; path and query values stay case-sensitive), so the value you
        forward does not need to match byte-for-byte.
      operationId: redirectLegacyAffiliateLink
      parameters:
        - name: u
          in: query
          required: false
          description: >-
            The original (old) link to resolve, as an absolute URL. URL-encode
            the value. If omitted, Introw falls back to the `X-Original-URL` /
            `X-Forwarded-Uri` headers, then `Referer`.
          schema:
            type: string
            format: uri
          example: https://go.acme.com/abc
      responses:
        '302':
          description: >-
            A match was found. Redirects to the mapped Introw affiliate link
            (`/r/{code}`), which in turn records the click and forwards to the
            campaign destination.
          headers:
            Location:
              description: The Introw affiliate link the old link maps to.
              schema:
                type: string
                format: uri
        '402':
          description: >-
            Monthly API credit allowance reached. Credits reset at the start of
            the next calendar month.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiError'
          headers:
            x-ratelimit-limit-minute:
              description: Maximum number of requests allowed in the current minute.
              schema:
                type: string
            x-ratelimit-remaining-minute:
              description: Number of requests remaining in the current minute.
              schema:
                type: string
            x-introw-credits-limit-month:
              description: >-
                This month's API credit allowance. Absent when the request was
                not metered (for example an authentication failure) or when the
                allowance is unlimited.
              schema:
                type: string
            x-introw-credits-remaining-month:
              description: >-
                API credits left in the current calendar month, after this
                request. `0` on a `402`. Absent when the request was not metered
                or when the allowance is unlimited.
              schema:
                type: string
            retry-after:
              description: >-
                Seconds until the API credit allowance resets (the start of the
                next calendar month).
              schema:
                type: string
        '404':
          description: >-
            No original URL was provided, or it does not match any migrated
            link.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiError'
          headers:
            x-ratelimit-limit-minute:
              description: Maximum number of requests allowed in the current minute.
              schema:
                type: string
            x-ratelimit-remaining-minute:
              description: Number of requests remaining in the current minute.
              schema:
                type: string
            x-introw-credits-limit-month:
              description: >-
                This month's API credit allowance. Absent when the request was
                not metered (for example an authentication failure) or when the
                allowance is unlimited.
              schema:
                type: string
            x-introw-credits-remaining-month:
              description: >-
                API credits left in the current calendar month, after this
                request. `0` on a `402`. Absent when the request was not metered
                or when the allowance is unlimited.
              schema:
                type: string
        '429':
          description: Rate limit exceeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiError'
          headers:
            x-ratelimit-limit-minute:
              description: Maximum number of requests allowed in the current minute.
              schema:
                type: string
            x-ratelimit-remaining-minute:
              description: Number of requests remaining in the current minute.
              schema:
                type: string
            x-introw-credits-limit-month:
              description: >-
                This month's API credit allowance. Absent when the request was
                not metered (for example an authentication failure) or when the
                allowance is unlimited.
              schema:
                type: string
            x-introw-credits-remaining-month:
              description: >-
                API credits left in the current calendar month, after this
                request. `0` on a `402`. Absent when the request was not metered
                or when the allowance is unlimited.
              schema:
                type: string
        '500':
          description: Unexpected server error while resolving the mapping.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiError'
          headers:
            x-ratelimit-limit-minute:
              description: Maximum number of requests allowed in the current minute.
              schema:
                type: string
            x-ratelimit-remaining-minute:
              description: Number of requests remaining in the current minute.
              schema:
                type: string
            x-introw-credits-limit-month:
              description: >-
                This month's API credit allowance. Absent when the request was
                not metered (for example an authentication failure) or when the
                allowance is unlimited.
              schema:
                type: string
            x-introw-credits-remaining-month:
              description: >-
                API credits left in the current calendar month, after this
                request. `0` on a `402`. Absent when the request was not metered
                or when the allowance is unlimited.
              schema:
                type: string
      security: []
components:
  schemas:
    PublicApiError:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              description: Stable machine-readable error code.
            message:
              type: string
              description: Human-readable error message.
            details:
              description: Optional structured details for validation and debugging.
          required:
            - code
            - message
          additionalProperties: false
      required:
        - error
      additionalProperties: false
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: Introw API key shown once when the credential is created.

````