> For the complete documentation index, see [llms.txt](https://docs.xp-protocol.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.xp-protocol.io/products/xp-protocol/design-patterns/referral-design-pattern.md).

# Referral Design Pattern

## Intro

**Referrals**

One way to use XP Protocol is as an on-chain **Referral System**. This design encourages your users to refer new users to your platform/protocol.

A referral is said to be "attributed" to the person who brought the new user in.&#x20;

The key to setting this up correctly while ensuring it does not get gamed is to tap into the unique identifier of a **updateScore()** transaction.

{% hint style="info" %}
updateId: Is a unique identifier that must be sent with each updateScore() transaction. This transaction is Deduped on-chain to prevent attacks.
{% endhint %}

```javascript
let myHeaders = new Headers();
let message = Date.now().toString();
let signatureObject = await web3.eth.accounts.sign(message, <PRIVATE_KEY>); //Private key of a wallet that is either an Updater or an Owner of the current project.
let signature = signatureObject.signature;

//Headers
myHeaders.append("X-API-KEY","<key>");
myHeaders.append("Content-Type", "application/json");
 
 let attributedAddress = "0xa6869c3001de171c26418e9e2eedca1c0d763ee2";
 let newUserAddress = "0x0baBda04f62C549A09EF3313Fe187f29c099FF3C";
 let updateId = "referral:"+attributedAddress+":"+newUserAddress;
 updateId = '0x' + sha256(updateId).toString(); // 0x to signify its a bytes32
  //Send to API
    const body = JSON.stringify({
        "updateId": updateId,
        "projectId": "0xadb591795f9e9047f9117163b83c2ebcd5edc4503644d59a98cf911aef0367f8",
        "actionName": "referral",
        "scoreType": "social",
        "targetWallet": attributedAddress,
        "signature": signature,
        "message": message
    })
    const requestOptions = {
        method: 'POST',
        headers: myHeaders,
        body: body,
        redirect: 'follow'
    };
    
    let response = await fetch('https://api.xp-protocol.io/update-score, requestOptions).then(async (response) => ({ status: response.status, value: await response.text() }));

```

Notice this particular line below:

```javascript
 let updateId = "referral:"+attributedAddress+":"+newUserAddress
```

This line sets the **updateId** to a concatenation of the two user addresses involved in this score update.&#x20;

The simplicity in this line is that as a developer you do not need to worry about checking to see if a user has already gotten a reward for referring that particular user. This means there is no state management or querying that needs to happen before you fire off a score update.

The deduping will happen on-chain, each score update is **Idempotent**.

Idempotence is a key differentiator with XP Protocol which allows developers to bypass complexity in storying and tracking referrals.

That's it!


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.xp-protocol.io/products/xp-protocol/design-patterns/referral-design-pattern.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
