> ## 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.

# Create Point

> Create a point asset for the organization associated with the API key

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

## Overview

`POST /v1/streams/points` creates a point asset for the organization associated with the API key.

Points are used as reward assets for point-based streams. Creating a point lets your organization define a symbol, display name, precision, and optional logo for those rewards.

You only need this endpoint if you plan to create point-based streams. It is not required for streams that use `rewardToken`.

<Info>
  The API key must belong to an organization and that organization must have the `organization:incentivize:streams:create` permission.
</Info>

## Endpoint

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST "https://earn.turtle.xyz/v1/streams/points" \
    -H "X-API-Key: sk_live_xxxxx" \
    -H "Content-Type: application/json" \
    -d '{
      "symbol": "PTS",
      "name": "Partner Points",
      "decimals": 18,
      "logoUrl": "https://cdn.example.com/points/pts.png"
    }'
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch('https://earn.turtle.xyz/v1/streams/points', {
    method: 'POST',
    headers: {
      'X-API-Key': process.env.TURTLE_SECRET_KEY!,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      symbol: 'PTS',
      name: 'Partner Points',
      decimals: 18,
      logoUrl: 'https://cdn.example.com/points/pts.png',
    }),
  });

  const data = await response.json();
  ```
</CodeGroup>

## Request Body

<ParamField body="symbol" type="string" required>
  Point symbol.
</ParamField>

<ParamField body="name" type="string" required>
  Point name.
</ParamField>

<ParamField body="decimals" type="integer" default={18}>
  Decimal precision for the point asset. If omitted, it uses the default configured precision of `18`.
</ParamField>

<ParamField body="logoUrl" type="string">
  Optional logo URL for the point asset.
</ParamField>

## Response Example

```json theme={null}
{
  "point": {
    "id": "7ff13cf6-53d0-4f3e-bd1a-e8eab6db4cf1",
    "orgId": "9f51b66a-d13a-4b55-8515-ae6e4ef7cf25",
    "symbol": "PTS",
    "name": "Partner Points",
    "decimals": 18,
    "logoUrl": "https://cdn.example.com/points/pts.png",
    "createdAt": "2026-03-01T00:00:00Z",
    "updatedAt": "2026-03-01T00:00:00Z"
  }
}
```

```typescript theme={null}
point: Point
```

## Response Fields

<ResponseField name="point" type="Point">
  The newly created point asset.
</ResponseField>

### `Point`

<ResponseField name="id" type="uuid">
  Unique point identifier.
</ResponseField>

<ResponseField name="orgId" type="uuid">
  Organization that owns the point.
</ResponseField>

<ResponseField name="symbol" type="string">
  Normalized uppercase point symbol.
</ResponseField>

<ResponseField name="name" type="string">
  Point name.
</ResponseField>

<ResponseField name="decimals" type="integer">
  Decimal precision assigned to the point asset.
</ResponseField>

<ResponseField name="logoUrl" type="string | null">
  Optional logo URL associated with the point asset.
</ResponseField>

<ResponseField name="createdAt" type="datetime">
  Creation timestamp of the point.
</ResponseField>

<ResponseField name="updatedAt" type="datetime">
  Last update timestamp of the point.
</ResponseField>

## Important Notes

<AccordionGroup>
  <Accordion title="Symbol normalization is automatic">
    The backend trims whitespace and uppercases `symbol` before persisting the point.
  </Accordion>

  <Accordion title="Decimals default to 18">
    If `decimals` is omitted, Turtle uses the configured default point precision, currently `18`.
  </Accordion>

  <Accordion title="Creating points is optional for token-based programs">
    Organizations using ERC-20 rewards through `rewardToken` do not need to create points. Points are only used with `pointId` in point-based stream creation.
  </Accordion>
</AccordionGroup>

## Error Handling

<AccordionGroup>
  <Accordion title="Missing or invalid API key">
    **Status Code:** 401 Unauthorized

    ```json theme={null}
    {
      "error": "Invalid API key"
    }
    ```

    **Solution:** Pass a valid `X-API-Key` header belonging to an organization-scoped API key.
  </Accordion>

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

    ```json theme={null}
    {
      "error": {
        "status": "INVALID_ARGUMENT",
        "error": "symbol is required"
      }
    }
    ```

    **Common causes:**

    * `symbol` is missing or blank
    * `name` is missing or blank
  </Accordion>

  <Accordion title="Permission denied">
    **Status Code:** 403 Forbidden

    ```json theme={null}
    {
      "error": {
        "status": "PERMISSION_DENIED",
        "error": "permission denied"
      }
    }
    ```

    **Solution:** Use an API key associated with an organization that has the `organization:incentivize:streams:create` permission.
  </Accordion>

  <Accordion title="Unexpected internal error">
    **Status Code:** 500 Internal Server Error

    **Solution:** Retry the request and contact Turtle if the issue persists.
  </Accordion>
</AccordionGroup>
