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

# Open a hosted checkout from a launch link

> A launch link carries the checkout in its query string, so you can put it in an email, a button, or an iframe `src`. Every time the link is opened it creates a new checkout and redirects to it, so one link can be reused. Anyone holding the link can start a checkout with it.

It takes the same fields as `POST /api/v1/payer/intake` except `metadata` and the items' `required` and `metadata`. Number the items from 1: `item1_id`, `item1_description`, `item1_amount`, `item1_quantity`, `item1_category`, then `item2_…`. Bracket names such as `items[0][id]` also work, and `amount_cents` is accepted for `amount`. For a single item you can send `description` and `amount`, with optional `item_id` (default `ITEM-001`) and `quantity`.



## OpenAPI

````yaml /openapi.json get /api/v1/payer/intake/link
openapi: 3.1.0
info:
  title: Partner Payments API
  version: 1.0.0
  description: >
    Use the Partner Payments API to create, refund, void, and retrieve payments
    from your backend.


    ## Payments and portals


    A payment is one charge, identified by `id`. Its line items describe what
    the payer paid for. The payer is the person making the payment, and the
    agency receives the payment.


    A portal is an agency's payment configuration in GroGov. It determines the
    payment gateway and service fee configuration used for a payment. GroGov
    provides the `portalId` values your API account can access. Requests for an
    inaccessible or unknown portal return `403 PORTAL_ACCESS_DENIED`. Contact
    GroGov support to request access.


    ## Environments


    Use the sandbox at `https://apistagepc.grogov.us` to test without moving
    real money. GroGov provides your sandbox API key, portal IDs, and test
    cards. Production processes live payments and requires separate access.


    ## Authentication


    All payment endpoints require one of these credentials:


    - API key: `Authorization: ApiKey pc_<your-key>`. Request your key from
    GroGov support.

    - Access token: exchange your API key at `POST /api/partner/v1/auth/token`,
    then send `Authorization: Bearer <token>`. The access token is a JWT valid
    for one hour. When it expires, exchange your API key again. There is no
    refresh token.


    Rotating an API key invalidates the previous key. Access tokens already
    issued remain valid until they expire. Deactivating your API account blocks
    both credentials on the next request.


    A card token represents card details and is separate from an access token.
    Contact GroGov support for the supported card-token integration for your
    portal. This API does not create card tokens.


    ## Amounts


    All monetary amounts are integer cents in `USD`. Monetary field names end in
    `Cents`, including `amountCents` and `serviceFeeCents`. `100` cents is $1.00
    USD. Sending a field named `amount` returns `400 VALIDATION_ERROR`.


    The principal is the payment amount excluding the service fee. GroGov adds
    the service fee to `amountCents`. Use `GET /api/partner/v1/fees/quote` to
    calculate the fee before charging.


    ## Settlement


    A batch is a group of transactions the payment processor submits for
    settlement. Settlement transfers funds for those transactions. A settled
    payment requires a refund instead of a void.


    ## Idempotency


    For `POST /payments`, `POST /payments/{id}/refund`, and `POST
    /payments/{id}/void`, use an `Idempotency-Key` header. The key can be any
    unique string up to 255 characters. The header is optional but recommended
    to prevent duplicate operations when retrying. Keys are scoped to your API
    account and kept for 24 hours.


    - Same key and body: the original response is returned with
    `Idempotent-Replayed: true`. No additional charge, refund, or void occurs.

    - Same key with a different body: `409 IDEMPOTENCY_MISMATCH`.

    - Same key while the first request is still processing: `409
    IDEMPOTENCY_IN_PROGRESS` with `Retry-After`.

    - After a `5xx` on create, the key stays reserved and a retry returns `409
    IDEMPOTENCY_RECONCILIATION_REQUIRED`. Check the payment list and resolve the
    original outcome before attempting a new charge. After a `5xx` on refund or
    void, the key is released and you can retry with the same key.


    ## Errors


    Payment errors include a machine-readable `details.code`: `{ "success":
    false, "message": "…", "details": { "code": "…" } }`. Authentication
    failures with HTTP status `401` or `403` can omit `details` and include only
    `message`.


    Case-specific restrictions use the payment-level `referenceId`. This is
    separate from each line item's `referenceId`. The applicable restrictions
    depend on the agency's payment configuration.


    | Code | HTTP | Meaning |

    |---|---|---|

    | `VALIDATION_ERROR` | 400 | The request is malformed or a field is invalid.
    See `message` for details |

    | `PAYMENT_DECLINED` | 402 | The card was declined |

    | `PAYMENT_BLOCKED` | 403 | Payments are blocked for the case identified by
    the payment-level `referenceId`. Do not retry |

    | `PAYMENT_HELD` | 409 | The case identified by the payment-level
    `referenceId` has a temporary payment hold. Try again later |

    | `DECLINE_BLOCKED` | 409 | This card was declined recently and is
    temporarily blocked. Use another card or try again later |

    | `VELOCITY_LIMIT` | 429 | Too many recent attempts for this case or card.
    Wait before retrying |

    | `PAYMENT_NOT_ALLOWED` | 422 | The payment does not meet the portal's
    payment rules or applicable case restrictions |

    | `PORTAL_ACCESS_DENIED` | 403 | The portal does not exist or your API
    account may not use it |

    | `PAYMENT_NOT_FOUND` | 404 | The payment does not exist or belongs to
    another API account |

    | `IDEMPOTENCY_MISMATCH` | 409 | The `Idempotency-Key` was already used with
    a different request |

    | `IDEMPOTENCY_IN_PROGRESS` | 409 | A request with this `Idempotency-Key` is
    still being processed. Retry after `Retry-After` |

    | `IDEMPOTENCY_RECONCILIATION_REQUIRED` | 409 | An earlier request with this
    key ended in an unknown state. Contact GroGov before retrying |

    | `INVALID_STATE` | 422 | The payment cannot be refunded or voided in its
    current state, or the refund exceeds the remaining amount |

    | `VOID_FAILED` | 422 | The payment gateway rejected the void. Check
    `details.suggestedAction` for the next operation |

    | `INTERNAL_ERROR` | 500 | An unexpected server error |

    | `CAPTURE_NOT_SUPPORTED` | 501 | Authorize-then-capture is not supported.
    Payments charge immediately |

    | `VAULT_NOT_SUPPORTED` | 501 | Storing cards and charging stored vault
    cards are not supported |

    | `PAYMENT_GATEWAY_ERROR` | 502 | The payment gateway returned an error. The
    payment did not succeed |

    | `PARTIAL_REFUND_PENDING` | 502 | The principal was refunded but the
    service fee refund failed. Retry the refund |

    | `GATEWAY_NOT_CONFIGURED` | 503 | The portal has no payment gateway
    configured |

    | `IDEMPOTENCY_UNAVAILABLE` | 503 | A request with an `Idempotency-Key`
    cannot be processed safely right now. Nothing was charged or refunded.
    Contact GroGov support |

    | `PAYMENT_TIMEOUT` | 504 | The payment gateway response was missing or
    unreadable. The outcome is unknown. Check the payment before retrying |


    ## Unsupported operations


    - Authorizing payments for later capture. `capture: "auth"` and `POST
    /payments/{id}/capture` return `501 CAPTURE_NOT_SUPPORTED`.

    - Storing cards or charging stored cards. `POST /vault` and
    `paymentMethod.type: "vault"` return `501 VAULT_NOT_SUPPORTED`.

    - Individual line-item refunds. Use the payment's `id`. A line-item ID
    returns `404 PAYMENT_NOT_FOUND`.

    - Filtering `GET /payments` by `referenceId`.
  contact:
    name: GroGov Partner Support
    email: support@grogov.us
servers:
  - url: https://apistagepc.grogov.us
    description: Sandbox
  - url: https://apiprodpc.grogov.us
    description: Production. Live payments require production access.
security:
  - ApiKeyAuth: []
  - BearerAuth: []
tags:
  - name: Auth
    description: >-
      Exchange an API key for a one-hour access token to authenticate subsequent
      requests.
  - name: Vault
    description: >-
      Storing cards and charging stored cards are not supported. Requests return
      501 `VAULT_NOT_SUPPORTED`.
  - name: Payments
    description: Create and manage payments containing one or more line items.
  - name: Hosted checkout
    description: >-
      Send the payer's browser to a GroGov-hosted checkout page instead of
      collecting card details yourself. You never handle card data, and these
      endpoints need no API key: the portal's hosted-checkout settings authorize
      the request.


      Start a checkout by posting a form or JSON to `POST /api/v1/payer/intake`,
      or by sending the payer to a launch link, `GET /api/v1/payer/intake/link`.
      Both answer with a `303` redirect. On success the payer lands on the
      checkout page with your line items filled in. On failure they go to your
      `cancel_url` with an error code, or to a GroGov error page.


      The result comes back on the payer's browser: when they press Done on the
      receipt, they go to your `return_url`. When they leave the checkout, they
      go to your `cancel_url`. Both carry a `sig` you can verify with the
      portal's signing secret. See `HostedCheckoutPaidResult`,
      `HostedCheckoutCancelledResult`, and `HostedCheckoutFailedResult`.


      Ask the agency or GroGov support to turn on hosted checkout for the
      portal, to add your return and cancel addresses to its allowlist, and for
      the signing secret. Every address must use `https`.
paths:
  /api/v1/payer/intake/link:
    get:
      tags:
        - Hosted checkout
      summary: Open a hosted checkout from a launch link
      description: >-
        A launch link carries the checkout in its query string, so you can put
        it in an email, a button, or an iframe `src`. Every time the link is
        opened it creates a new checkout and redirects to it, so one link can be
        reused. Anyone holding the link can start a checkout with it.


        It takes the same fields as `POST /api/v1/payer/intake` except
        `metadata` and the items' `required` and `metadata`. Number the items
        from 1: `item1_id`, `item1_description`, `item1_amount`,
        `item1_quantity`, `item1_category`, then `item2_…`. Bracket names such
        as `items[0][id]` also work, and `amount_cents` is accepted for
        `amount`. For a single item you can send `description` and `amount`,
        with optional `item_id` (default `ITEM-001`) and `quantity`.
      parameters:
        - in: query
          name: portal_id
          required: true
          schema:
            type: string
            format: uuid
        - in: query
          name: reference_id
          required: true
          schema:
            type: string
            maxLength: 64
        - in: query
          name: label
          schema:
            type: string
            maxLength: 80
        - in: query
          name: payer_name
          schema:
            type: string
            maxLength: 200
        - in: query
          name: payer_email
          schema:
            type: string
            format: email
        - in: query
          name: payer_phone
          schema:
            type: string
            maxLength: 50
        - in: query
          name: return_url
          schema:
            type: string
            format: uri
        - in: query
          name: cancel_url
          schema:
            type: string
            format: uri
        - in: query
          name: expires_at
          schema:
            type: string
            format: date-time
        - in: query
          name: item1_id
          schema:
            type: string
            maxLength: 64
          description: >-
            First item. Repeat the `itemN_` fields for each further item.
            `item1_id`, `item1_description` and `item1_amount` are required
            unless you send a single item with `description` and `amount`.
        - in: query
          name: item1_description
          schema:
            type: string
            maxLength: 200
        - in: query
          name: item1_amount
          schema:
            type: integer
            minimum: 0
          description: Price of one unit, in cents
        - in: query
          name: item1_quantity
          schema:
            type: integer
            minimum: 1
            default: 1
        - in: query
          name: item1_category
          schema:
            type: string
            maxLength: 32
        - in: query
          name: description
          schema:
            type: string
            maxLength: 200
          description: >-
            Single-item form: the item's description. Ignored when any `itemN_`
            or `items[…]` field is present.
        - in: query
          name: amount
          schema:
            type: integer
            minimum: 0
          description: >-
            Single-item form: price of one unit, in cents. `amount_cents` is
            accepted too.
        - in: query
          name: item_id
          schema:
            type: string
            maxLength: 64
            default: ITEM-001
          description: 'Single-item form: the item''s id.'
        - in: query
          name: quantity
          schema:
            type: integer
            minimum: 1
            default: 1
          description: 'Single-item form: the quantity.'
        - in: query
          name: embed
          schema:
            type: string
            enum:
              - iframe
          description: >-
            Send `iframe` when the link is the `src` of an iframe, so the
            checkout renders for embedding.
      responses:
        '303':
          description: Always a redirect, as for `POST /api/v1/payer/intake`.
          headers:
            Location:
              schema:
                type: string
                format: uri
              description: The checkout page or the failure address
      security: []
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: Authorization
      description: >-
        Send your API key as `Authorization: ApiKey pc_<your-key>`. The API also
        accepts the key without the `ApiKey ` prefix. API keys authenticate
        requests to `/api/partner/v1/*`. Contact GroGov support to rotate your
        key or deactivate your API account. Rotation invalidates the previous
        key. Account deactivation blocks both API keys and access tokens.
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        Exchange your API key at `POST /api/partner/v1/auth/token` for a
        one-hour access token, then send `Authorization: Bearer <token>`. An
        access token cannot obtain another access token. When a token expires or
        is rejected, exchange your API key for a new one. Tokens authenticate
        requests only to `/api/partner/v1/*`.

````

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