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

# Magic Link

> Create shareable URLs that let growers authenticate with John Deere, Climate FieldView, CNHi, CNHI FieldOps, and other providers or upload machine files.

Use the Magic Link endpoints to create hosted authentication or file-upload flows that you can send directly to end users. This page covers the provider, single-provider authentication, and file-upload link variants, along with the settings object they share.

For conceptual background, see [Magic Link](/components/magic-link).

## Overview

Magic Links are shareable URLs that let your users connect provider accounts or upload files without embedding widgets in your application. There are three types:

* **Provider** — multi-provider authentication (connect one or more providers).
* **Authentication** — single-provider authentication (connect exactly one provider).
* **File Upload** — manual file upload through a hosted interface.

**Base URL:** `https://api.withleaf.io/services/widgets/api`

<Note>
  All Magic Link types share the same `expiresIn` parameter: lifetime in seconds, minimum `900`, maximum approximately 1 year.
</Note>

<Note>
  The GET endpoints return usage-tracking fields such as `usageCount` and `maxUsage`. Magic Links are not inherently single-use.
</Note>

***

## Settings object

Every Magic Link type accepts an optional `settings` object to customize the hosted page:

| Field               | Type    | Description                                 |
| ------------------- | ------- | ------------------------------------------- |
| `backgroundColor`   | string  | Hex color for the page background.          |
| `headerImage`       | string  | URL of an image displayed in the header.    |
| `companyLogo`       | string  | URL of your company logo.                   |
| `companyName`       | string  | Your company name displayed on the page.    |
| `showLeafUserName`  | boolean | Whether to display the Leaf user's name.    |
| `disconnectEnabled` | boolean | Whether the user can disconnect a provider. |

***

## Provider Magic Link

Lets the end user authenticate with multiple providers in a single session.

### Endpoints

| Endpoint                     | Method   | Path                                      |
| ---------------------------- | -------- | ----------------------------------------- |
| Get all                      | `GET`    | `/magic-link/provider`                    |
| Get one                      | `GET`    | `/magic-link/provider/{magicLinkId}`      |
| Create (with Leaf user)      | `POST`   | `/magic-link/users/{leafUserId}/provider` |
| Create (with auto Leaf user) | `POST`   | `/magic-link/provider`                    |
| Delete                       | `DELETE` | `/magic-link/provider/{magicLinkId}`      |

***

### Create a Provider Magic Link (with Leaf user)

`POST /magic-link/users/{leafUserId}/provider`

Creates a Magic Link for an existing Leaf user.

#### Path parameters

| Parameter    | Type   | Required | Description                |
| ------------ | ------ | -------- | -------------------------- |
| `leafUserId` | string | Yes      | The UUID of the Leaf user. |

#### Request body

| Field              | Type      | Required | Description                                                          |
| ------------------ | --------- | -------- | -------------------------------------------------------------------- |
| `expiresIn`        | integer   | No       | Lifetime in seconds. Min `900`, max \~1 year.                        |
| `allowedProviders` | string\[] | No       | Provider keys to display (e.g. `"JohnDeere"`, `"ClimateFieldView"`). |
| `settings`         | object    | No       | Customization options. See [Settings object](#settings-object).      |

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST \
    "https://api.withleaf.io/services/widgets/api/magic-link/users/{leafUserId}/provider" \
    -H "Authorization: Bearer {token}" \
    -H "Content-Type: application/json" \
    -d '{
      "expiresIn": 604800,
      "allowedProviders": ["JohnDeere", "ClimateFieldView"],
      "settings": {
        "backgroundColor": "#ffffff",
        "companyName": "Acme Ag",
        "disconnectEnabled": true
      }
    }'
  ```

  ```python Python theme={null}
  import requests

  url = f"https://api.withleaf.io/services/widgets/api/magic-link/users/{leaf_user_id}/provider"
  headers = {
      "Authorization": f"Bearer {token}",
      "Content-Type": "application/json",
  }
  body = {
      "expiresIn": 604800,
      "allowedProviders": ["JohnDeere", "ClimateFieldView"],
      "settings": {
          "backgroundColor": "#ffffff",
          "companyName": "Acme Ag",
          "disconnectEnabled": True,
      },
  }

  response = requests.post(url, headers=headers, json=body)
  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    `https://api.withleaf.io/services/widgets/api/magic-link/users/${leafUserId}/provider`,
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        expiresIn: 604800,
        allowedProviders: ["JohnDeere", "ClimateFieldView"],
        settings: {
          backgroundColor: "#ffffff",
          companyName: "Acme Ag",
          disconnectEnabled: true,
        },
      }),
    }
  );
  const magicLink = await response.json();
  ```
</CodeGroup>

#### Response

```json theme={null}
{
  "id": "magicLinkId",
  "leafUserId": "UUID",
  "link": "https://magic-link.withleaf.io/{magicLinkId}",
  "expiresAt": "2024-10-26T14:23:56.584Z"
}
```

***

### Create a Provider Magic Link (with auto Leaf user)

`POST /magic-link/provider`

Creates a Magic Link for flows where Leaf creates a Leaf user based on the provided `externalId`.

#### Request body

| Field              | Type      | Required | Description                                                              |
| ------------------ | --------- | -------- | ------------------------------------------------------------------------ |
| `externalId`       | string    | Yes      | Your identifier for the user. Required for automatic Leaf user creation. |
| `name`             | string    | No       | Display name for the auto-created Leaf user.                             |
| `email`            | string    | No       | Email for the auto-created Leaf user.                                    |
| `expiresIn`        | integer   | No       | Lifetime in seconds. Min `900`, max \~1 year.                            |
| `allowedProviders` | string\[] | No       | Provider keys to display.                                                |
| `settings`         | object    | No       | Customization options. See [Settings object](#settings-object).          |

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST \
    "https://api.withleaf.io/services/widgets/api/magic-link/provider" \
    -H "Authorization: Bearer {token}" \
    -H "Content-Type: application/json" \
    -d '{
      "externalId": "farmer-123",
      "name": "Jane Doe",
      "expiresIn": 604800,
      "allowedProviders": ["JohnDeere"]
    }'
  ```

  ```python Python theme={null}
  import requests

  url = "https://api.withleaf.io/services/widgets/api/magic-link/provider"
  headers = {
      "Authorization": f"Bearer {token}",
      "Content-Type": "application/json",
  }
  body = {
      "externalId": "farmer-123",
      "name": "Jane Doe",
      "expiresIn": 604800,
      "allowedProviders": ["JohnDeere"],
  }

  response = requests.post(url, headers=headers, json=body)
  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    "https://api.withleaf.io/services/widgets/api/magic-link/provider",
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        externalId: "farmer-123",
        name: "Jane Doe",
        expiresIn: 604800,
        allowedProviders: ["JohnDeere"],
      }),
    }
  );
  const magicLink = await response.json();
  ```
</CodeGroup>

***

### Get all Provider Magic Links

`GET /magic-link/provider`

Returns all Provider Magic Links for your API owner.

#### Query parameters

| Parameter       | Type   | Required | Description                                                                                   |
| --------------- | ------ | -------- | --------------------------------------------------------------------------------------------- |
| `nextPageToken` | string | No       | Pagination token returned by a previous list response. Use `0` or omit it for the first page. |

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET \
    "https://api.withleaf.io/services/widgets/api/magic-link/provider" \
    -H "Authorization: Bearer {token}"
  ```

  ```python Python theme={null}
  import requests

  url = "https://api.withleaf.io/services/widgets/api/magic-link/provider"
  headers = {"Authorization": f"Bearer {token}"}

  response = requests.get(url, headers=headers)
  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    "https://api.withleaf.io/services/widgets/api/magic-link/provider",
    { headers: { Authorization: `Bearer ${token}` } }
  );
  const links = await response.json();
  ```
</CodeGroup>

#### Response

```json theme={null}
{
  "items": [
    {
      "id": "magicLinkId",
      "link": "https://magic-link.withleaf.io/{magicLinkId}",
      "createdAt": "2024-10-19T14:23:56.584Z",
      "expiresAt": "2024-10-26T14:23:56.584Z",
      "lastAccessedAt": "2024-10-19T14:23:56.584Z",
      "leafUserId": "UUID",
      "maxUsage": 3,
      "usageCount": 0,
      "widget": "PROVIDER",
      "allowedProviders": ["JohnDeere", "ClimateFieldView"],
      "settings": {
        "companyName": "Acme Ag",
        "companyLogo": "https://example.com/logo.svg",
        "disconnectEnabled": true
      }
    }
  ],
  "nextPageToken": "opaque-pagination-token"
}
```

***

### Get a Provider Magic Link

`GET /magic-link/provider/{magicLinkId}`

Returns a single Provider Magic Link by ID.

#### Path parameters

| Parameter     | Type   | Required | Description               |
| ------------- | ------ | -------- | ------------------------- |
| `magicLinkId` | string | Yes      | The ID of the Magic Link. |

#### Response

```json theme={null}
{
  "id": "magicLinkId",
  "link": "https://magic-link.withleaf.io/{magicLinkId}",
  "createdAt": "2024-10-19T14:23:56.584Z",
  "expiresAt": "2024-10-26T14:23:56.584Z",
  "lastAccessedAt": "2024-10-19T14:23:56.584Z",
  "leafUserId": "UUID",
  "maxUsage": 3,
  "usageCount": 0,
  "widget": "PROVIDER",
  "allowedProviders": ["JohnDeere", "ClimateFieldView"],
  "settings": {
    "companyName": "Acme Ag",
    "companyLogo": "https://example.com/logo.svg",
    "disconnectEnabled": true
  }
}
```

***

### Delete a Provider Magic Link

`DELETE /magic-link/provider/{magicLinkId}`

Permanently deletes a Provider Magic Link. The URL immediately stops working.

#### Path parameters

| Parameter     | Type   | Required | Description               |
| ------------- | ------ | -------- | ------------------------- |
| `magicLinkId` | string | Yes      | The ID of the Magic Link. |

***

## Authentication Magic Link

Lets the end user authenticate with a single, specified provider.

### Endpoints

| Endpoint                     | Method   | Path                                            |
| ---------------------------- | -------- | ----------------------------------------------- |
| Get all                      | `GET`    | `/magic-link/authentication`                    |
| Get one                      | `GET`    | `/magic-link/authentication/{magicLinkId}`      |
| Create (with Leaf user)      | `POST`   | `/magic-link/users/{leafUserId}/authentication` |
| Create (with auto Leaf user) | `POST`   | `/magic-link/authentication`                    |
| Delete                       | `DELETE` | `/magic-link/authentication/{magicLinkId}`      |

***

### Create an Authentication Magic Link (with Leaf user)

`POST /magic-link/users/{leafUserId}/authentication`

Creates a Magic Link scoped to a single provider for an existing Leaf user.

#### Path parameters

| Parameter    | Type   | Required | Description                |
| ------------ | ------ | -------- | -------------------------- |
| `leafUserId` | string | Yes      | The UUID of the Leaf user. |

#### Request body

| Field       | Type    | Required | Description                                                     |
| ----------- | ------- | -------- | --------------------------------------------------------------- |
| `expiresIn` | integer | No       | Lifetime in seconds. Min `900`, max \~1 year.                   |
| `provider`  | string  | Yes      | The provider key (e.g. `"JohnDeere"`, `"ClimateFieldView"`).    |
| `settings`  | object  | No       | Customization options. See [Settings object](#settings-object). |

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST \
    "https://api.withleaf.io/services/widgets/api/magic-link/users/{leafUserId}/authentication" \
    -H "Authorization: Bearer {token}" \
    -H "Content-Type: application/json" \
    -d '{
      "expiresIn": 604800,
      "provider": "JohnDeere",
      "settings": {
        "companyName": "Acme Ag"
      }
    }'
  ```

  ```python Python theme={null}
  import requests

  url = f"https://api.withleaf.io/services/widgets/api/magic-link/users/{leaf_user_id}/authentication"
  headers = {
      "Authorization": f"Bearer {token}",
      "Content-Type": "application/json",
  }
  body = {
      "expiresIn": 604800,
      "provider": "JohnDeere",
      "settings": {"companyName": "Acme Ag"},
  }

  response = requests.post(url, headers=headers, json=body)
  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    `https://api.withleaf.io/services/widgets/api/magic-link/users/${leafUserId}/authentication`,
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        expiresIn: 604800,
        provider: "JohnDeere",
        settings: { companyName: "Acme Ag" },
      }),
    }
  );
  const magicLink = await response.json();
  ```
</CodeGroup>

#### Response

```json theme={null}
{
  "id": "magicLinkId",
  "leafUserId": "UUID",
  "link": "https://magic-link.withleaf.io/{magicLinkId}",
  "expiresAt": "2024-10-26T14:23:56.584Z"
}
```

***

### Create an Authentication Magic Link (with auto Leaf user)

`POST /magic-link/authentication`

Creates a Magic Link for flows where Leaf creates a Leaf user based on the provided `externalId`.

#### Request body

| Field        | Type    | Required | Description                                                     |
| ------------ | ------- | -------- | --------------------------------------------------------------- |
| `externalId` | string  | Yes      | Your identifier for the user.                                   |
| `name`       | string  | No       | Display name for the auto-created Leaf user.                    |
| `email`      | string  | No       | Email for the auto-created Leaf user.                           |
| `expiresIn`  | integer | No       | Lifetime in seconds. Min `900`, max \~1 year.                   |
| `provider`   | string  | Yes      | The provider key.                                               |
| `settings`   | object  | No       | Customization options. See [Settings object](#settings-object). |

<Tip>
  Use the auto-create variant when you do not want to create the Leaf user separately before sending the link.
</Tip>

***

### Get, Delete

The Get all, Get one, and Delete endpoints for Authentication Magic Links follow the same pattern as the [Provider Magic Link](#provider-magic-link) endpoints, but the resource includes a single `provider` field instead of `allowedProviders`.

Authentication list endpoints also use the same paginated envelope with `items` and `nextPageToken`.

#### Authentication list/get response shape

```json theme={null}
{
  "id": "magicLinkId",
  "link": "https://magic-link.withleaf.io/{magicLinkId}",
  "createdAt": "2024-10-19T14:23:56.584Z",
  "expiresAt": "2024-10-26T14:23:56.584Z",
  "lastAccessedAt": "2024-10-19T14:23:56.584Z",
  "leafUserId": "UUID",
  "maxUsage": 3,
  "usageCount": 0,
  "widget": "AUTHENTICATION",
  "provider": "JohnDeere",
  "settings": {
    "companyName": "Acme Ag",
    "companyLogo": "https://example.com/logo.svg"
  }
}
```

***

## File Upload Magic Link

Lets the end user upload machine files through a hosted interface.

### Endpoints

| Endpoint                     | Method   | Path                                         |
| ---------------------------- | -------- | -------------------------------------------- |
| Get all                      | `GET`    | `/magic-link/file-upload`                    |
| Get one                      | `GET`    | `/magic-link/file-upload/{magicLinkId}`      |
| Create (with Leaf user)      | `POST`   | `/magic-link/users/{leafUserId}/file-upload` |
| Create (with auto Leaf user) | `POST`   | `/magic-link/file-upload`                    |
| Delete                       | `DELETE` | `/magic-link/file-upload/{magicLinkId}`      |

***

### Create a File Upload Magic Link (with Leaf user)

`POST /magic-link/users/{leafUserId}/file-upload`

Creates a Magic Link for uploading machine files, tied to an existing Leaf user.

#### Path parameters

| Parameter    | Type   | Required | Description                |
| ------------ | ------ | -------- | -------------------------- |
| `leafUserId` | string | Yes      | The UUID of the Leaf user. |

#### Request body

| Field       | Type    | Required | Description                                                     |
| ----------- | ------- | -------- | --------------------------------------------------------------- |
| `expiresIn` | integer | No       | Lifetime in seconds. Min `900`, max \~1 year.                   |
| `settings`  | object  | No       | Customization options. See [Settings object](#settings-object). |

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST \
    "https://api.withleaf.io/services/widgets/api/magic-link/users/{leafUserId}/file-upload" \
    -H "Authorization: Bearer {token}" \
    -H "Content-Type: application/json" \
    -d '{
      "expiresIn": 604800,
      "settings": {
        "companyName": "Acme Ag",
        "companyLogo": "https://example.com/logo.png"
      }
    }'
  ```

  ```python Python theme={null}
  import requests

  url = f"https://api.withleaf.io/services/widgets/api/magic-link/users/{leaf_user_id}/file-upload"
  headers = {
      "Authorization": f"Bearer {token}",
      "Content-Type": "application/json",
  }
  body = {
      "expiresIn": 604800,
      "settings": {
          "companyName": "Acme Ag",
          "companyLogo": "https://example.com/logo.png",
      },
  }

  response = requests.post(url, headers=headers, json=body)
  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    `https://api.withleaf.io/services/widgets/api/magic-link/users/${leafUserId}/file-upload`,
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        expiresIn: 604800,
        settings: {
          companyName: "Acme Ag",
          companyLogo: "https://example.com/logo.png",
        },
      }),
    }
  );
  const magicLink = await response.json();
  ```
</CodeGroup>

#### Response

```json theme={null}
{
  "id": "magicLinkId",
  "leafUserId": "UUID",
  "link": "https://magic-link.withleaf.io/{magicLinkId}",
  "expiresAt": "2024-10-26T14:23:56.584Z"
}
```

***

### Create a File Upload Magic Link (with auto Leaf user)

`POST /magic-link/file-upload`

Creates a Magic Link for flows where Leaf creates a Leaf user based on the provided `externalId`.

#### Request body

| Field        | Type    | Required | Description                                                     |
| ------------ | ------- | -------- | --------------------------------------------------------------- |
| `externalId` | string  | Yes      | Your identifier for the user.                                   |
| `name`       | string  | No       | Display name for the auto-created Leaf user.                    |
| `email`      | string  | No       | Email for the auto-created Leaf user.                           |
| `expiresIn`  | integer | No       | Lifetime in seconds. Min `900`, max \~1 year.                   |
| `settings`   | object  | No       | Customization options. See [Settings object](#settings-object). |

***

### Get, Delete

The Get all, Get one, and Delete endpoints for File Upload Magic Links follow the same paginated pattern as the [Provider Magic Link](#provider-magic-link) endpoints.

File Upload list endpoints also use the same paginated envelope with `items` and `nextPageToken`.

#### File Upload list/get response shape

```json theme={null}
{
  "id": "magicLinkId",
  "link": "https://magic-link.withleaf.io/{magicLinkId}",
  "createdAt": "2024-10-19T14:23:56.584Z",
  "expiresAt": "2024-10-26T14:23:56.584Z",
  "lastAccessedAt": "2024-10-19T14:23:56.584Z",
  "leafUserId": "UUID",
  "maxUsage": 3,
  "usageCount": 0,
  "widget": "FILE_UPLOAD",
  "settings": {
    "companyName": "Acme Ag",
    "companyLogo": "https://example.com/logo.svg"
  }
}
```
