# CRM · Customers

Part of AppEngine API Documentation. Full index: https://appengine.appmint.io/documentation.md
## GET /crm/customer-data/{customerId}

**Get complete customer data**

`operationId: CRMController_getCustomerData`

Returns a customer together with **every linked record** — addresses, phone numbers, and the other sub-records attached to them — in one response.

The identifier is flexible: a customer `sk`, an email address or a username all resolve, so a support tool can look someone up by whatever it has.

#### Signature

```http
GET /crm/customer-data/{customerId} (customerId: string) -> The customer and every linked record
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `User`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | CUSTOMER_NOT_FOUND | Customer not found | The identifier does not resolve to a customer. | Try the email address or `sk` — all three forms are accepted. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /crm/customer-data/{customerId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `customerId` | path | string | yes | Customer `sk`, email address, or username. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The customer and every linked record |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Customer not found — The identifier does not resolve to a customer. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /crm/customer-data/{customerId}

**Add linked data to a customer**

`operationId: CRMController_addCustomerData`

Attaches a sub-record to a customer — an address, a phone number, or any other linked datatype. `datatype` names what kind of record it is and `data` carries its fields.

As with the read, the customer can be identified by `sk`, email or username.

#### Signature

```http
POST /crm/customer-data/{customerId} (customerId: string, body) -> The created linked record
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `User`.

#### Notes

- `datatype` is not validated against a list — an unrecognised value creates a record nothing else reads.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | CUSTOMER_NOT_FOUND | Customer not found | The identifier does not resolve. | Check the identifier. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /crm/customer-data/{customerId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `customerId` | path | string | yes | Customer `sk`, email address, or username. |

### Request body

The linked record to add.

```json
{
  "datatype": "address",
  "data": {
    "line1": "12 Ada Way",
    "city": "London",
    "postcode": "E1 6AN",
    "country": "GB"
  }
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The created linked record |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Customer not found — The identifier does not resolve. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

