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

# Register Wallet

> Connect wallets and create memberships in Turtle

<Note>
  All requests require an API key via the `X-API-Key` header.
  See [Authentication](/sdk/authentication/api-keys) for details.
</Note>

## Overview

The Membership API allows users to connect their wallets (EVM, Solana, or TON) and become members of Turtle. This API follows a secure three-step flow to ensure wallet ownership verification.

## Authentication Flow

<Steps>
  <Step title="Check Membership Status">
    Verify if a wallet address is already associated with a Turtle account
  </Step>

  <Step title="Request Signature Agreement">
    Generate a message that must be signed by the wallet to prove ownership
  </Step>

  <Step title="Create Membership">
    Submit the signed message to create a new user account and associate the wallet
  </Step>
</Steps>

## Endpoints

### Check Membership Status

<CodeGroup>
  ```bash curl theme={null}
  curl -X GET "https://earn.turtle.xyz/v1/membership?address=0xaD595ba34B6BEdCdFDecCe0C0cDe6A2Dc7Ad658D&walletEcosystem=evm" \
    -H "X-API-Key: pk_live_xxxxx"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    'https://earn.turtle.xyz/v1/membership?address=0xaD595ba34B6BEdCdFDecCe0C0cDe6A2Dc7Ad658D&walletEcosystem=evm',
    { headers: { 'X-API-Key': 'pk_live_xxxxx' } }
  );
  const data = await response.json();
  ```
</CodeGroup>

**Query Parameters**

<ParamField query="address" type="string" required>
  The wallet address to check
</ParamField>

<ParamField query="walletEcosystem" type="string" default="evm">
  The blockchain ecosystem. Supported values: `evm`, `solana`, `ton`
</ParamField>

**Response**

```json theme={null}
{
  "isMember": false
}
```

### Request Signature Agreement

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://earn.turtle.xyz/v1/membership/agreement \
    -H "X-API-Key: pk_live_xxxxx" \
    -H "Content-Type: application/json" \
    -d '{
      "address": "0xaD595ba34B6BEdCdFDecCe0C0cDe6A2Dc7Ad658D",
      "walletEcosystem": "evm",
      "url": "https://turtle.xyz",
      "chainId": "1"
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://earn.turtle.xyz/v1/membership/agreement', {
    method: 'POST',
    headers: { 'X-API-Key': 'pk_live_xxxxx', 'Content-Type': 'application/json' },
    body: JSON.stringify({
      address: '0xaD595ba34B6BEdCdFDecCe0C0cDe6A2Dc7Ad658D',
      walletEcosystem: 'evm',
      url: 'https://turtle.xyz',
      chainId: '1'
    })
  });
  const data = await response.json();
  ```
</CodeGroup>

**Request Body**

<ParamField body="address" type="string" required>
  The wallet address requesting membership
</ParamField>

<ParamField body="walletEcosystem" type="string" required>
  The blockchain ecosystem. Supported values: `evm`, `solana`, `ton`
</ParamField>

<ParamField body="url" type="string" required>
  The URL of the application (used in the signature message)
</ParamField>

<ParamField body="chainId" type="string" default="1">
  The chain ID for EVM wallets. Not required for Solana or TON
</ParamField>

**Response**

```json theme={null}
{
  "nonce": "550e8400-e29b-41d4-a716-446655440000",
  "message": "turtle.xyz wants you to sign in with your Ethereum account:\n0xaD595ba34B6BEdCdFDecCe0C0cDe6A2Dc7Ad658D\n\nSign Up to Turtle\n\nURI: https://turtle.xyz\nVersion: 1\nChain ID: 1\nNonce: 550e8400-e29b-41d4-a716-446655440000\nIssued At: 2024-01-15T10:00:00Z"
}
```

### Create Membership

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://earn.turtle.xyz/v1/membership \
    -H "X-API-Key: pk_live_xxxxx" \
    -H "Content-Type: application/json" \
    -d '{
      "address": "0xaD595ba34B6BEdCdFDecCe0C0cDe6A2Dc7Ad658D",
      "walletEcosystem": "evm",
      "signature": "0x1234567890abcdef...",
      "nonce": "550e8400-e29b-41d4-a716-446655440000",
      "distributorId": "your-distributor-id"
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://earn.turtle.xyz/v1/membership', {
    method: 'POST',
    headers: { 'X-API-Key': 'pk_live_xxxxx', 'Content-Type': 'application/json' },
    body: JSON.stringify({
      address: '0xaD595ba34B6BEdCdFDecCe0C0cDe6A2Dc7Ad658D',
      walletEcosystem: 'evm',
      signature: '0x1234567890abcdef...',
      nonce: '550e8400-e29b-41d4-a716-446655440000',
      distributorId: 'your-distributor-id' // optional
    })
  });
  const data = await response.json();
  ```
</CodeGroup>

**Request Body**

<ParamField body="address" type="string" required>
  The wallet address creating the membership
</ParamField>

<ParamField body="walletEcosystem" type="string" required>
  The blockchain ecosystem. Supported values: `evm`, `solana`, `ton`
</ParamField>

<ParamField body="signature" type="string" required>
  The signature of the message returned by the agreement endpoint
</ParamField>

<ParamField body="nonce" type="string" required>
  The nonce returned by the agreement endpoint
</ParamField>

<ParamField body="distributorId" type="string">
  The distributor ID to associate the membership with. When provided, the user will be tracked as having signed up through the distributor's integration.
</ParamField>

**Response**

```json theme={null}
{
  "isMember": true,
  "error": ""
}
```

## Complete Flow Example

Here's a complete example of the membership creation flow:

```bash_cURL theme={null}
# Step 1: Check if wallet is already a member
curl -X GET "https://earn.turtle.xyz/v1/membership?address=0xaD595ba34B6BEdCdFDecCe0C0cDe6A2Dc7Ad658D&walletEcosystem=evm" \
  -H "X-API-Key: pk_live_xxxxx"
# Response: {"isMember": false}

# Step 2: Request signature agreement
curl -X POST https://earn.turtle.xyz/v1/membership/agreement \
  -H "X-API-Key: pk_live_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "address": "0xaD595ba34B6BEdCdFDecCe0C0cDe6A2Dc7Ad658D",
    "walletEcosystem": "evm",
    "url": "https://turtle.xyz",
    "chainId": "1"
  }'
# Response: {"nonce": "550e8400...", "message": "turtle.xyz wants you to sign..."}

# Step 3: Sign the message with your wallet (using web3 library or wallet app)
# This step happens client-side

# Step 4: Submit the signature to create membership
curl -X POST https://earn.turtle.xyz/v1/membership \
  -H "X-API-Key: pk_live_xxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "address": "0xaD595ba34B6BEdCdFDecCe0C0cDe6A2Dc7Ad658D",
    "walletEcosystem": "evm",
    "signature": "0x1234567890abcdef...",
    "nonce": "550e8400-e29b-41d4-a716-446655440000"
  }'
# Response: {"isMember": true, "error": ""}

# Step 5: Verify membership was created
curl -X GET "https://earn.turtle.xyz/v1/membership?address=0xaD595ba34B6BEdCdFDecCe0C0cDe6A2Dc7Ad658D&walletEcosystem=evm" \
  -H "X-API-Key: pk_live_xxxxx"
# Response: {"isMember": true}
```

## Error Handling

### Common Errors

<AccordionGroup>
  <Accordion title="Invalid Wallet Ecosystem">
    **Status Code:** 400 Bad Request

    **Response:**

    ```json theme={null}
    {
      "error": {
        "status": "INVALID_ARGUMENT",
        "error": "invalid wallet ecosystem"
      }
    }
    ```

    **Solution:** Use one of the supported ecosystems: `evm`, `solana`, or `ton`
  </Accordion>

  <Accordion title="Invalid Wallet Address">
    **Status Code:** 400 Bad Request

    **Response:**

    ```json theme={null}
    {
      "error": {
        "status": "INVALID_ARGUMENT",
        "error": "invalid wallet address"
      }
    }
    ```

    **Solution:** Ensure the wallet address is valid for the specified ecosystem
  </Accordion>

  <Accordion title="Wallet Already Exists">
    **Status Code:** 409 Conflict

    **Response:**

    ```json theme={null}
    {
      "error": {
        "status": "ALREADY_EXISTS",
        "error": "wallet already exists"
      }
    }
    ```

    **Solution:** This wallet is already associated with an account. Is not necessary to create a new membership.
  </Accordion>

  <Accordion title="Invalid or Expired Nonce">
    **Status Code:** 400 Bad Request

    **Response:**

    ```json theme={null}
    {
      "error": {
        "status": "INVALID_ARGUMENT",
        "error": "invalid nonce or expired"
      }
    }
    ```

    **Solution:** Request a new agreement and sign it promptly. Nonces expire after a short period
  </Accordion>
</AccordionGroup>

## Security Considerations

<Warning>
  Never share your private keys or seed phrases. The API only requires signatures, not private keys.
</Warning>

* Nonces are single-use and expire after a short period
* Messages follow the [EIP-4361](https://eips.ethereum.org/EIPS/eip-4361) standard for EVM wallets
* All signatures are verified server-side before creating accounts
