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

# Transaction References: Identity and Idempotency Guide

> References uniquely identify every Paylink transaction. Learn how to generate, store, and use them to track payments and prevent duplicates.

Every transaction on Paylink — payments, virtual accounts, direct debits, refunds, and transfers — is identified by an **opaque string reference**. References are the primary key you use to look up transaction status, reconcile records, and correlate webhook events back to your own database. Treat them as durable identifiers and persist them as soon as you create a transaction.

## What Is a Reference?

A reference is a unique string that you supply when you initialise a transaction, or that Paylink generates for you when you do not provide one. References are:

* **Opaque** — Paylink treats them as arbitrary strings. You can encode any identifier format that is meaningful to your system.
* **Unique per operation** — Each payment, virtual account, direct debit, refund, or transfer must have a distinct reference. Reusing a reference across different transaction types or across transactions in the same category is not allowed.
* **Immutable** — Once a reference is associated with a transaction, it cannot be changed.

## How to Use References

<Steps>
  <Step title="Pass your reference at initialisation">
    Supply your reference in the request body when you call an initialisation endpoint such as `/payments/initialize`. If you omit it, the API generates one for you — but you should always provide your own so that you control the value and can tie it to your internal records.

    ```json theme={null}
    {
      "reference": "order_12345",
      "amount": 2500,
      "currency": "NGN"
    }
    ```
  </Step>

  <Step title="Persist the reference immediately">
    Store the reference in your database before you redirect the customer or trigger any downstream action. If a network failure interrupts the response, you can use the stored reference to query the transaction status rather than creating a duplicate.
  </Step>

  <Step title="Use the reference for status queries">
    Pass the reference as a path or query parameter to verification and lookup endpoints (for example, `/payments/verify/{reference}`) to retrieve the current status of any transaction.
  </Step>

  <Step title="Correlate incoming webhook events">
    Webhook payloads include a `reference` (and sometimes a `payment_reference`) field in the `data` object. Match this value against your stored references to identify which transaction the event relates to.
  </Step>
</Steps>

## Best Practices

* **Generate a unique reference for every transaction.** A UUID v4 or a combination of your internal order ID and a timestamp both work well.
* **Store the reference before calling the API.** Write it to your database first so you can recover from partial failures.
* **Never reuse a reference.** Even if an earlier transaction using that reference failed, submitting it again will be rejected.
* **Do not parse or construct meaning from references returned by the API.** Their format may change; rely only on the value itself.

## Reference Errors

When something goes wrong with a reference, the API returns a descriptive error. The table below lists every reference-related error, what causes it, and how to recover.

| HTTP Status | Error Message                       | Cause                                                                                       | How to Handle                                                                                                      |
| ----------- | ----------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `404`       | `Invalid transaction reference`     | The reference string is malformed or does not match any known transaction                   | Verify that you are sending the correct reference and that it belongs to the right environment (sandbox vs. live)  |
| `404`       | `Transaction record not found`      | The reference is well-formed but no transaction exists for it                               | Check that the transaction was successfully created; if you are in the wrong environment, switch and retry         |
| `409`       | `Reference already exists`          | You supplied a reference that is already associated with a different transaction            | Generate a new, unique reference and retry the request                                                             |
| `409`       | `Duplicate transaction reference`   | You submitted the same reference for a transaction that is already in progress or completed | Do not retry with the same reference; query the existing transaction using the reference to get its current status |
| `410`       | `Transaction reference has expired` | The transaction was created but was not completed within the allowed time window            | Create a new transaction with a new reference                                                                      |
