# Create a purchase history entry

URL: https://docs.sparklayer.io/developers/api/purchasing/create-a-purchase-history-entry
Operation: `POST /api/v1/purchases/{lookupBy}/{identifier}/history` (operationId `createPurchaseHistory`)
OpenAPI spec: https://docs.sparklayer.io/openapi/purchasing.yaml

Adds an event to the history of the purchase that matches `lookupBy` and `identifier`. Set `event_type` to `message` or `note` (with `created_by` and `body`), or to `email` (with `sent_by` and `body`). Returns `404` if no purchase matches.

`POST /api/v1/purchases/{lookupBy}/{identifier}/history`

**Base URLs:** `https://app.sparklayer.io` (Live), `https://test.app.sparklayer.io` (Test)

**Authentication:** send `Authorization: Bearer <access_token>` and `Site-Id: <site id>` with every request. Get the token from [Get an access token](https://docs.sparklayer.io/developers/api/core/get-an-access-token.md); see [Authentication](https://docs.sparklayer.io/developers/authentication.md).

### Example request

```bash
curl -X POST "https://app.sparklayer.io/api/v1/purchases/platform/123456789/history" \
  -H "Authorization: Bearer $SPARKLAYER_TOKEN" \
  -H "Site-Id: $SPARKLAYER_SITE_ID" \
  -H "Content-Type: application/json" \
  -d '{
  "event_type": "message",
  "created_by": "4217ba4f-7618-4e3b-b1af-9055639b18d1",
  "body": "<body>"
}'
```

Set `SPARKLAYER_TOKEN` to an access token and `SPARKLAYER_SITE_ID` to your Site ID. For the test environment, use `https://test.app.sparklayer.io`.

### Path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `lookupBy` | "sparklayer" \| "platform" \| "internal" \| "visible" | Yes | Which of the purchase's `purchase_identifiers` `identifier` is: `sparklayer`, `platform`, `internal` or `visible`. Example: `platform` |
| `identifier` | string | Yes | The purchase identifier, of the kind set by `lookupBy`. With `lookupBy=sparklayer` it must be a UUID. Length: min 1. Example: `123456789` |

### Header parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `Site-Id` | string | Yes | Your SparkLayer Site ID, from Settings > API in the SparkLayer Dashboard. Length: min 1. Example: `jones-climbing` |

### Request body (`application/json`) (required)

One of these:

**MessageEventBase**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `event_type` | "message" \| "note" | Yes | |
| `created_by` | string \| null | Yes | The ID of the actor (customer, sales agent..) that created the message. |
| `body` | string | Yes | Length: max 2047. |

**EmailEventBase**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `event_type` | "email" | Yes | |
| `sent_by` | string \| null | Yes | An identity for the sender of the email creating the notification |
| `body` | string | Yes | Length: max 2047. |

```json
{
  "event_type": "message",
  "created_by": "4217ba4f-7618-4e3b-b1af-9055639b18d1",
  "body": "<body>"
}
```

### Responses

#### 200: The purchase's history events.

An array. Each item is one of these (or a combination):

**MessageEvent**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `[].created_at` | string (date-time) | Yes | date and time of the event |
| `[].event_type` | "message" \| "note" | Yes | |
| `[].created_by` | string \| null | Yes | The ID of the actor (customer, sales agent..) that created the message. |
| `[].body` | string | Yes | Length: max 2047. |

**EmailEvent**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `[].created_at` | string (date-time) | Yes | date and time of the event |
| `[].event_type` | "email" | Yes | |
| `[].sent_by` | string \| null | Yes | An identity for the sender of the email creating the notification |
| `[].body` | string | Yes | Length: max 2047. |

**UpdateEvent**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `[].created_at` | string (date-time) | Yes | date and time of the event |
| `[].event_type` | "update" | | |
| `[].purchase_type` | "quote" | | |
| `[].fields` | (AssigneeChangeEvent \| ExpiryChangeEvent \| StatusChangeEvent)[] | | |
| `[].fields[].created_at` | string (date-time) | | date and time of the event |
| `[].fields[].field` | "assignee" | | |
| `[].fields[].old_value` | string \| null | | previous assignee |
| `[].fields[].new_value` | string \| null | | new assignee |
| `[].fields[].created_by` | string \| null | | The ID of the actor (customer, sales agent..) that made the edit. |
| `[].fields[].purchase_type` | "quote" | | |

```json
[
  {
    "created_at": "2020-01-01T00:00:00+02:00",
    "event_type": "message",
    "created_by": "4217ba4f-7618-4e3b-b1af-9055639b18d1",
    "body": "<body>"
  }
]
```

#### 404: Not found.

`application/problem+json`: the standard error body (below).

#### 500: An unexpected error.

`application/problem+json`: the standard error body (below).

### Error body

Error responses with a body use this RFC 7807 problem details object. See [Errors](https://docs.sparklayer.io/developers/errors.md) for every status code and which errors to retry.

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `detail` | string | | Human-readable summary of the error |
| `status` | integer | | HTTP Status code returned from API |
| `title` | string | | Machine-readable error code |
| `type` | string | | |
| `errors` | object[] | | |
| `errors[].code` | string | | A machine-readable error message |
| `errors[].property` | string | | The offending property |
| `errors[].message` | string | | A human-readable summary of the error |

```json
{
  "detail": "Data Validation Failed",
  "status": 400,
  "title": "invalid-api-request-contents",
  "type": "https://hub.sparklayer.io/tech-docs",
  "errors": [
    {
      "code": "unique-constraint-violation",
      "property": "purchase_identifiers.sparklayer",
      "message": "Each stock level must have a unique stock location and sku combination"
    }
  ]
}
```
