# Affiliate Links & Codes

Affiliates share tracking links to refer users to your project. By default, links use the affiliate's wallet address as the identifier. Fuul also lets affiliates create custom codes for cleaner, branded URLs.

```
# Default link (wallet address)
https://yourwebsite.com?af=0x1f9090aae28b8a3dceadf281b0f12828e676c326

# With a custom code
https://yourwebsite.com?af=my-affiliate-code
```

## Generating tracking links

Use `generateTrackingLink` to build a referral URL for an affiliate:

```typescript
import { Fuul } from '@fuul/sdk';

const trackingLink = await Fuul.generateTrackingLink(
  'https://yourwebsite.com',  // Base URL where pageview events are implemented
  '0x1234...',                 // Affiliate's address
  'evm_address'                // Identifier type
);

// If the affiliate has registered a code, it is used as the `af` value.
// Otherwise the raw identifier is used: "https://yourwebsite.com?af=0x1234..."
```

You can also append optional tracking parameters:

```typescript
const trackingLink = await Fuul.generateTrackingLink(
  'https://yourwebsite.com',
  '0x1234...',
  'evm_address',
  {
    title: 'campaign-name',
    format: 'banner',
    place: 'homepage'
  }
);
```

## Creating affiliate codes

Affiliates can create codes from the Fuul Hosted Hub, or you can add this to your own site using the SDK.

```typescript
import { Fuul } from '@fuul/sdk';

await Fuul.createAffiliateCode({
  userIdentifier: '0x1234...',
  identifierType: 'evm_address',
  signature: '0xabc...',
  code: 'my-affiliate-code',
  accountChainId: 1, // Required for EIP-1271 signature verification (smart contract wallets on EVM)
  userRebateRate: 0.05, // optional, sets the rebate rate at creation time (0 to 0.2, max 2 decimals)
});
```

{% hint style="info" %}
The message to sign must follow this exact format:

*I confirm that I am creating the ${affiliateCode} code on Fuul*
{% endhint %}

### Code rules

* Alphanumeric characters and dashes (`-`) only
* Maximum 30 characters

### Error handling

| Error                   | Cause                                           |
| ----------------------- | ----------------------------------------------- |
| `ValidationError`       | Invalid characters in the code                  |
| `InvalidSignatureError` | Signature doesn't match the address and message |
| `AddressInUseError`     | Address already has a code registered           |
| `CodeInUseError`        | Code is already taken                           |

## Updating affiliate codes

```typescript
import { Fuul } from '@fuul/sdk';

await Fuul.updateAffiliateCode({
  userIdentifier: '0x1234...',
  identifierType: 'evm_address',
  signature: '0xabc...',
  code: 'my-new-code',
});
```

{% hint style="info" %}
The message to sign must follow this exact format:

*I confirm that I am updating my code to ${affiliateCode} on Fuul*
{% endhint %}

## Getting affiliate info

Returns the affiliate profile for a user: identity (`user_identifier`, `user_identifier_type`), `region`, `current_tier`, and `codes` — an array of all referral codes owned by this affiliate, ordered oldest-first. Each entry includes `code`, `created_at`, `uses`, `clicks`, `total_users`, `total_earnings`, and `rebate_rate`.

`current_tier` is a root-level field (`{ id, name, slug, rank } | null`) — it is not part of each `codes[]` entry. It is `null` when the project has no tier configuration or when no API key is provided.

```typescript
import { Fuul, UserIdentifierType } from '@fuul/sdk';

const affiliate = await Fuul.getAffiliateInfo('0x1234...', UserIdentifierType.EvmAddress);
// Returns the Affiliate object, or null if none exists
```

{% hint style="warning" %}
The `user_rebate_rate` and `rebate_rates[]` fields are no longer returned by the server. The SDK's `getAffiliateCode` method is also deprecated — use `getAffiliateInfo`.
{% endhint %}

{% hint style="info" %}
When authenticated with a Bearer API key, if the affiliate exists but has no codes linked to that project, the endpoint returns `200` with `codes: []` — not `404`. A `404` means the affiliate identifier does not exist at all.
{% endhint %}

For the multi-level referral tree (R1-R4), use the separate endpoint `GET /v1/affiliate-portal/referral-tree` (SDK: `Fuul.getReferralTree`).

## Checking code availability

```typescript
import { Fuul } from '@fuul/sdk';

// Check if a code has NOT been registered yet
const isFree = await Fuul.isAffiliateCodeFree('my-code');
// true = available, false = taken

// Check if a code exists AND still has remaining uses
const isAvailable = await Fuul.isAffiliateCodeAvailable('my-code');
```

## Updating rebate rates

Set a custom rebate rate for an affiliate — overrides the project default for that specific user:

```typescript
import { Fuul, UserIdentifierType } from '@fuul/sdk';

await Fuul.updateRebateRate({
  userIdentifier: '0x1234...',
  identifierType: UserIdentifierType.EvmAddress,
  signature: '0xabc...',
  code: 'my-affiliate-code',
  rebateRate: 0.05,  // 5% referral commission. Must be between 0 and 0.2 (0% to 20%) with at most 2 decimal places.
});
```

{% hint style="info" %}
The signature message must be: `I confirm that I am setting my rebate rate to 0.05 on Fuul`

For XRPL wallets, include `signaturePublicKey`. For smart contract wallets, include `accountChainId`.
{% endhint %}

## API reference

| Feature                 | API endpoint                                   | Reference                                                               |
| ----------------------- | ---------------------------------------------- | ----------------------------------------------------------------------- |
| Create affiliate code   | `POST /v1/affiliates`                          | [View](https://fuul.readme.io/reference/createaffiliatecode)            |
| Update affiliate code   | `POST /v1/affiliates/{userIdentifier}`         | [View](https://fuul.readme.io/reference/updateaffiliatecode)            |
| Get affiliate code      | `GET /v1/affiliates/{userIdentifier}`          | [View](https://fuul.readme.io/reference/getaffiliatecode)               |
| Check if code is free   | `GET /v1/affiliates/codes/{code}`              | [View](https://fuul.readme.io/reference/get_v1-affiliates-codes-code)   |
| Check code availability | `GET /v1/affiliates/codes/{code}/availability` | [View](https://fuul.readme.io/reference/checkaffiliatecodeavailability) |


---

# Agent Instructions: 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.fuul.xyz/developer-guide/creating-affiliate-links-or-codes.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.
