> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.algorhythm.app/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.algorhythm.app/_mcp/server.

# List farm profiles

GET https://api.algorhythm.app/v1/farm-profiles

Returns all farm-managed profiles for your team, newest first. In-flight profiles are included — their phone fields (`phone_id`, `platforms`, `accounts`) will be `null` or empty until provisioning completes.

**Rate limit:** 100 requests per minute per team.

Reference: https://docs.algorhythm.app/api-reference/farm-profiles/list-farm-profiles-v-1-farm-profiles-get

## Authentication

- `X-API-Key` header (required) — API Key authentication via header

## Request

### Query parameters

- `cursor` (string, optional, nullable) — Opaque pagination cursor from a previous response's `next_cursor`.
- `limit` (integer, optional, default: 20) — Maximum number of profiles to return (max 100).

## Response

### 200

Successful Response

- `profiles` (list of FarmProfile, required)
- `has_more` (boolean, required) — Whether more results exist beyond this page.
- `next_cursor` (string, optional, nullable) — Opaque cursor for the next page. Pass back as the `cursor` query parameter. `null` when no more pages.

## Errors

### 422 Unprocessable Entity Error

Validation Error

- `detail` (list of ValidationError, optional)

### 429 Too Many Requests Error

Rate limit exceeded.

- `any`

## Types

### FarmProfile

- `profile_id` (string, required) — Unique profile identifier.
- `profile_name` (string, required) — Internal display name for the profile. Set via `account_name` at creation; defaults to `username`.
- `tiktok_username` (string, required) — The TikTok handle linked to this profile. Mutable — may change if the handle is renamed on TikTok.
- `created_at` (datetime, optional, nullable) — Profile creation time as an ISO-8601 timestamp (UTC). `null` until provisioning records it.
- `phone_id` (string, optional, nullable) — Cloud-phone identifier hosting this profile.
- `status` (enum, optional, default: configuring) — Lifecycle status of the profile. - `configuring` — phone is being provisioned and the social account is being set up. - `retrying` — initial setup hit a snag; we're auto-recovering on the backend. No action needed. - `cold` — accounts are logged in but lack the history needed to start posting; no warmup runs have happened yet. - `warming` — a warmup task is actively running on the phone (~15–30 minutes). Returns to `warm` when it finishes. - `warm` — resting state during the warmup phase (a ~3-day schedule of warmup tasks), between runs. Not postable and not terminal — oscillates with `warming` until enough runs complete. - `ready` — at least 3 successful warmup tasks have completed over a span of at least 3 days; the profile is now postable. Maintenance warmups may still cycle it back through `warming` and return it to `ready`. - `following`: a follow task is actively running on the phone. Transient; returns to its prior resting state (`cold`/`warm`/`ready`) when it finishes. - `posting`: a post is actively uploading/publishing on the phone. Transient; returns to its prior resting state when it finishes. - `failed` — recovery exhausted; this profile won't be salvaged. Terminal. Create a new profile to try again. - `deactivated` — profile is no longer active. Terminal. - `banned` — the platform banned the account. Terminal. The profile stays in your records but is removed from your monthly billing quantity, with prorated credits applied for the unused portion of the month. Transitions: `configuring` → `cold` → `warming` ↔ `warm` → `ready`. Once `ready`, maintenance runs flip it through `warming` and back to `ready`. `following` and `posting` are transient busy states any active profile can briefly enter and then leave. `configuring` may pass through `retrying` and back, or terminate at `failed`. Any state can transition to `deactivated` or `banned`.
  - Allowed values: `configuring`, `retrying`, `cold`, `warming`, `warm`, `ready`, `failed`, `deactivated`, `following`, `posting`, `banned`
- `warmup_count` (integer, optional, nullable) — Number of successful warmup runs completed so far. `null` until the phone is provisioned. Compare against `warmups_required` to gauge progress toward `ready`.
- `warmups_required` (integer, optional, default: 3) — Successful warmup runs required, spanning at least 3 days, before the profile becomes `ready`.
- `last_warmup_at` (datetime, optional, nullable) — ISO-8601 timestamp (UTC) of the most recent warmup run. `null` before the first run.
- `platforms` (list of string, optional, nullable) — Two-element array: `[social_platform, auth_method]`, e.g. `['tiktok', 'sms']` (default), `['tiktok', 'google']`, or `['tiktok', 'outlook']`.
- `bio` (string, optional, nullable) — Account bio/about text set on the profile. `null` until the phone is provisioned, or if none was provided at creation.
- `profile_picture_url` (string, optional, nullable) — HTTPS URL of the image set as the account's profile picture. `null` until the phone is provisioned, or if none was provided at creation.
- `accounts` (list of FarmAccount, optional) — Platform accounts on this phone (TikTok, plus its linked email for email-backed accounts). Empty array until the phone is provisioned.

### ValidationError

- `loc` (list of ValidationErrorLocItems, required)
- `msg` (string, required)
- `type` (string, required)
- `input` (any, optional)
- `ctx` (ValidationErrorCtx, optional)

### FarmAccount

- `platform` (string, required) — `tiktok`, or, for email-backed accounts, the linked `google` or `outlook`.
- `username` (string, optional, nullable) — Account login identifier: the TikTok handle, or the email/phone used to sign in. Falls back to `email` or `phone_number` when no handle is set yet.
- `email` (string, optional, nullable) — Email address associated with the account. For email-backed TikTok accounts this is the linked Google/Outlook address; `null` for phone-only accounts.
- `phone_number` (string, optional, nullable) — Phone number used to sign in, for phone-authenticated accounts. `null` for email-backed accounts.
- `password` (string, optional, nullable) — Account password. `null` for Gmail (OAuth) accounts, and until set for phone (SMS) accounts. Future posting endpoints will work for both auth methods.
- `recovery_email` (string, optional, nullable) — Recovery email address on file for the account. To change: email support; we'll set up a new recovery email on our side, then open a ticket to hop on a quick call where you input the verification code and we swap it over to you.

### ValidationErrorLocItems

- string
- integer

### ValidationErrorCtx

## Examples

**Response**

```json
{
  "profiles": [
    {
      "profile_id": "f8a1c2d4-3b7e-4f9a-9c2d-1e5b7a8f9c3d",
      "profile_name": "Green Valley Farm",
      "tiktok_username": "greenvalleyfarm",
      "created_at": "2023-06-01T08:00:00Z",
      "phone_id": "618031736399331394",
      "status": "ready",
      "warmup_count": 5,
      "warmups_required": 3,
      "last_warmup_at": "2023-06-08T14:12:00Z",
      "platforms": [
        "tiktok",
        "sms"
      ],
      "accounts": [
        {
          "platform": "tiktok",
          "username": "greenvalleyfarm",
          "phone_number": "5555550142",
          "password": "hunter2-example",
          "recovery_email": null
        }
      ]
    }
  ],
  "has_more": false,
  "next_cursor": "eyJwYWdlIjoxLCJzaXplIjoyMH0="
}
```

**SDK Code**

```python
import requests

url = "https://api.algorhythm.app/v1/farm-profiles"

headers = {"X-API-Key": "<apiKey>"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.algorhythm.app/v1/farm-profiles';
const options = {method: 'GET', headers: {'X-API-Key': '<apiKey>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.algorhythm.app/v1/farm-profiles"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("X-API-Key", "<apiKey>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.algorhythm.app/v1/farm-profiles")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<apiKey>'

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.algorhythm.app/v1/farm-profiles")
  .header("X-API-Key", "<apiKey>")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.algorhythm.app/v1/farm-profiles', [
  'headers' => [
    'X-API-Key' => '<apiKey>',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.algorhythm.app/v1/farm-profiles");
var request = new RestRequest(Method.GET);
request.AddHeader("X-API-Key", "<apiKey>");
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = ["X-API-Key": "<apiKey>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.algorhythm.app/v1/farm-profiles")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```