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

# API Introduction

> Connect to the ParsaLink API to read and write CRM data, trigger automations, and integrate with your own systems.

<div
  style={{ 
display: "inline-flex",
alignItems: "center",
gap: "8px",
background: "linear-gradient(90deg, #143D4E 0%, #1C758A 100%)",
color: "#FFFFFF",
fontSize: "12px",
fontWeight: "700",
marginBottom: "10px",
padding: "8px 14px",
letterSpacing: "0.08em",
textTransform: "uppercase",
borderRadius: "999px",
boxShadow: "0 8px 24px rgba(20, 61, 78, 0.18)"
}}
>
  Introduction
</div>

## Base URL

<div
  className="
bg-[linear-gradient(135deg,rgba(255,255,255,1)_0%,rgba(48,200,202,0.08)_100%)]
dark:bg-black
dark:border-white/10
dark:text-cyan-300
dark:shadow-none
"
  style={{
border: "1px solid rgba(48, 200, 202, 0.22)",
borderRadius: "16px",
padding: "16px 18px",
marginBottom: "20px",
color: "#2C768D",
boxShadow: "0 10px 26px rgba(28, 117, 138, 0.08)"
}}
>
  All API requests are made to:
</div>

```
https://api.parsalink.io/api
```

<div
  className="
bg-[linear-gradient(135deg,rgba(255,255,255,1)_0%,rgba(255,111,97,0.06)_100%)]
dark:bg-black
dark:border-white/10
dark:text-white
dark:shadow-none
"
  style={{
border: "1px solid rgba(255, 111, 97, 0.18)",
borderRadius: "16px",
padding: "16px 18px",
marginBottom: "20px",
color: "#212121",
boxShadow: "0 10px 26px rgba(20, 61, 78, 0.07)"
}}
>
  All endpoints use HTTPS. HTTP requests are not supported.
</div>

***

<div
  style={{ 
display: "inline-flex",
alignItems: "center",
gap: "8px",
background: "rgba(48, 200, 202, 0.12)",
color: "#1C758A",
fontSize: "12px",
fontWeight: "700",
marginBottom: "10px",
padding: "8px 14px",
letterSpacing: "0.08em",
textTransform: "uppercase",
borderRadius: "999px",
border: "1px solid rgba(48, 200, 202, 0.28)"
}}
>
  Authentication
</div>

## Authentication

<div
  className="
bg-[linear-gradient(135deg,rgba(255,255,255,1)_0%,rgba(48,200,202,0.08)_100%)]
dark:bg-black
dark:border-white/10
dark:text-cyan-300
dark:shadow-none
"
  style={{
border: "1px solid rgba(48, 200, 202, 0.22)",
borderRadius: "16px",
padding: "16px 18px",
marginBottom: "20px",
color: "#2C768D",
boxShadow: "0 10px 26px rgba(28, 117, 138, 0.08)"
}}
>
  The ParsaLink API uses Bearer token authentication. Include your access token in the `Authorization` header of every request:
</div>

```http theme={null}
Authorization: Bearer <your_access_token>
```

### Obtaining a Token

<div
  className="
bg-[linear-gradient(135deg,rgba(255,255,255,1)_0%,rgba(48,200,202,0.08)_100%)]
dark:bg-black
dark:border-white/10
dark:text-cyan-300
dark:shadow-none
"
  style={{
border: "1px solid rgba(48, 200, 202, 0.22)",
borderRadius: "16px",
padding: "16px 18px",
marginBottom: "20px",
color: "#2C768D",
boxShadow: "0 10px 26px rgba(28, 117, 138, 0.08)"
}}
>
  Authenticate by calling the login endpoint with your email and password:
</div>

```http theme={null}
POST https://api.parsalink.io/api/auth/login/
Content-Type: application/json

{
  "email": "you@example.com",
  "password": "your_password"
}
```

**Response:**

```json theme={null}
{
  "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "user": {
    "id": "usr_01HX...",
    "email": "you@example.com",
    "firstName": "Jane",
    "lastName": "Smith"
  }
}
```

<div
  className="
bg-[linear-gradient(135deg,rgba(255,255,255,1)_0%,rgba(48,200,202,0.08)_100%)]
dark:bg-black
dark:border-white/10
dark:text-cyan-300
dark:shadow-none
"
  style={{
border: "1px solid rgba(48, 200, 202, 0.22)",
borderRadius: "16px",
padding: "16px 18px",
marginBottom: "20px",
color: "#2C768D",
boxShadow: "0 10px 26px rgba(28, 117, 138, 0.08)"
}}
>
  The `access` token is valid for **1 hour**. Use the `refresh` token to get a new access token without re-entering credentials.
</div>

See [Authentication](/api-reference/authentication) for full details on token refresh and API key authentication.

***

<div
  style={{ 
display: "inline-flex",
alignItems: "center",
gap: "8px",
background: "rgba(255, 111, 97, 0.12)",
color: "#FF6F61",
fontSize: "12px",
fontWeight: "700",
marginBottom: "10px",
padding: "8px 14px",
letterSpacing: "0.08em",
textTransform: "uppercase",
borderRadius: "999px",
border: "1px solid rgba(255, 111, 97, 0.24)"
}}
>
  Responses
</div>

## Response Format

<div
  className="
bg-[linear-gradient(135deg,rgba(255,255,255,1)_0%,rgba(48,200,202,0.08)_100%)]
dark:bg-black
dark:border-white/10
dark:text-cyan-300
dark:shadow-none
"
  style={{
border: "1px solid rgba(48, 200, 202, 0.22)",
borderRadius: "16px",
padding: "16px 18px",
marginBottom: "20px",
color: "#2C768D",
boxShadow: "0 10px 26px rgba(28, 117, 138, 0.08)"
}}
>
  All responses are JSON. Field names use **camelCase** throughout the API.
</div>

### Success Response

```json theme={null}
{
  "id": "cnt_01HX...",
  "firstName": "John",
  "lastName": "Smith",
  "email": "john@acme.com",
  "stage": "engaged",
  "createdAt": "2025-03-15T10:30:00Z",
  "updatedAt": "2025-03-20T14:22:00Z"
}
```

### Paginated List Response

```json theme={null}
{
  "count": 142,
  "next": "https://api.parsalink.io/api/contacts/?page=2",
  "previous": null,
  "results": [...]
}
```

<div
  className="
bg-[linear-gradient(135deg,rgba(255,255,255,1)_0%,rgba(48,200,202,0.08)_100%)]
dark:bg-black
dark:border-white/10
dark:text-cyan-300
dark:shadow-none
"
  style={{
border: "1px solid rgba(48, 200, 202, 0.22)",
borderRadius: "16px",
padding: "16px 18px",
marginBottom: "20px",
color: "#2C768D",
boxShadow: "0 10px 26px rgba(28, 117, 138, 0.08)"
}}
>
  Use the `next` URL directly to fetch the next page. You can also pass `?page=N` or `?limit=N&offset=N` query parameters.
</div>

***

<div
  style={{ 
display: "inline-flex",
alignItems: "center",
gap: "8px",
background: "linear-gradient(90deg, #143D4E 0%, #1C758A 100%)",
color: "#FFFFFF",
fontSize: "12px",
fontWeight: "700",
marginBottom: "10px",
padding: "8px 14px",
letterSpacing: "0.08em",
textTransform: "uppercase",
borderRadius: "999px",
boxShadow: "0 8px 24px rgba(20, 61, 78, 0.18)"
}}
>
  Errors
</div>

## Error Handling

<div
  className="
bg-[linear-gradient(135deg,rgba(255,255,255,1)_0%,rgba(48,200,202,0.08)_100%)]
dark:bg-black
dark:border-white/10
dark:text-cyan-300
dark:shadow-none
"
  style={{
border: "1px solid rgba(48, 200, 202, 0.22)",
borderRadius: "16px",
padding: "16px 18px",
marginBottom: "20px",
color: "#2C768D",
boxShadow: "0 10px 26px rgba(28, 117, 138, 0.08)"
}}
>
  Errors return standard HTTP status codes with a JSON body explaining the error.
</div>

| Status Code | Meaning                                                            |
| ----------- | ------------------------------------------------------------------ |
| `400`       | Bad Request — invalid or missing parameters                        |
| `401`       | Unauthorized — missing or invalid token                            |
| `403`       | Forbidden — authenticated but not permitted to perform this action |
| `404`       | Not Found — resource doesn't exist or isn't accessible to you      |
| `422`       | Unprocessable Entity — validation error                            |
| `429`       | Too Many Requests — rate limit exceeded                            |
| `500`       | Internal Server Error — something went wrong on our end            |

**Error response body:**

```json theme={null}
{
  "detail": "Authentication credentials were not provided."
}
```

For validation errors:

```json theme={null}
{
  "email": ["This field is required."],
  "stage": ["Value 'invalid_stage' is not a valid choice."]
}
```

***

<div
  style={{ 
display: "inline-flex",
alignItems: "center",
gap: "8px",
background: "rgba(48, 200, 202, 0.12)",
color: "#1C758A",
fontSize: "12px",
fontWeight: "700",
marginBottom: "10px",
padding: "8px 14px",
letterSpacing: "0.08em",
textTransform: "uppercase",
borderRadius: "999px",
border: "1px solid rgba(48, 200, 202, 0.28)"
}}
>
  Rate Limits
</div>

## Rate Limiting

<div
  className="
bg-[linear-gradient(135deg,rgba(255,255,255,1)_0%,rgba(48,200,202,0.08)_100%)]
dark:bg-black
dark:border-white/10
dark:text-cyan-300
dark:shadow-none
"
  style={{
border: "1px solid rgba(48, 200, 202, 0.22)",
borderRadius: "16px",
padding: "16px 18px",
marginBottom: "20px",
color: "#2C768D",
boxShadow: "0 10px 26px rgba(28, 117, 138, 0.08)"
}}
>
  Each plan has a defined request rate limit.
</div>

| Plan       | Rate Limit          |
| ---------- | ------------------- |
| Starter    | 100 requests/minute |
| Growth     | 300 requests/minute |
| Business   | 600 requests/minute |
| Enterprise | Custom              |

Rate limit headers are returned with every response:

```http theme={null}
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 247
X-RateLimit-Reset: 1711500060
```

<div
  className="
bg-[linear-gradient(135deg,rgba(255,255,255,1)_0%,rgba(255,111,97,0.06)_100%)]
dark:bg-black
dark:border-white/10
dark:text-white
dark:shadow-none
"
  style={{
border: "1px solid rgba(255, 111, 97, 0.18)",
borderRadius: "16px",
padding: "16px 18px",
marginBottom: "20px",
color: "#212121 ,rgba(255, 255, 255)",
boxShadow: "0 10px 26px rgba(20, 61, 78, 0.07)"
}}
>
  When you exceed the limit, a `429` response is returned. The `X-RateLimit-Reset` value is a Unix timestamp indicating when the rate limit window resets.
</div>

***

<div
  style={{ 
display: "inline-flex",
alignItems: "center",
gap: "8px",
background: "rgba(255, 111, 97, 0.12)",
color: "#FF6F61",
fontSize: "12px",
fontWeight: "700",
marginBottom: "10px",
padding: "8px 14px",
letterSpacing: "0.08em",
textTransform: "uppercase",
borderRadius: "999px",
border: "1px solid rgba(255, 111, 97, 0.24)"
}}
>
  Versioning
</div>

## Versioning

<div
  style={{

border: "1px solid rgba(28, 117, 138, 0.18)",
borderRadius: "16px",
padding: "16px 18px",
marginBottom: "20px",
color: "#212121 ,rgba(255, 255, 255)",
boxShadow: "0 10px 26px rgba(20, 61, 78, 0.07)"
}}
  className="bg-white dark:bg-black dark:border-white/10 dark:text-white dark:shadow-none"
>
  The current API version is **v1**, which is the default when no version is specified. Breaking changes will be introduced with a new version prefix (e.g., `/api/v2/`). The current version will be supported for at least 12 months after a new version is released.
</div>
