# Quickstart

Load a contact and record an event in under five minutes. You will need a project, a datasource token and curl.

This walkthrough ends with one contact in your datasource and one event on their timeline. Budget five minutes.

## Before you start

#### 1. Have a project

Sign in to the [dashboard](https://dashboard.instasent.com) and pick the project that will receive the data. If this is your first time, **create a throw-away project** — it makes cleanup trivial once you have finished exploring.

#### 2. Create a datasource

Inside the project, open **Datasources** → **New datasource** → **API**. Copy the `project`, `datasource` and the generated token — you will not see the token again.

#### 3. Export them as env vars

```bash
export INSTASENT_PROJECT="proj_xxx"
export INSTASENT_DATASOURCE="ds_xxx"
export INSTASENT_TOKEN="eyJhbGciOi..."
export BASE="https://api.instasent.com/v1/project/$INSTASENT_PROJECT/datasource/$INSTASENT_DATASOURCE"
```

## 1. Verify the token

`GET /stream` returns metadata and is the cheapest way to confirm your credentials work.

```bash
curl "$BASE/stream" \
  -H "Authorization: Bearer $INSTASENT_TOKEN"
```

You should get a `200` with an object describing the organization, project, datasource and recent usage. A `401` means the token is wrong; a `404` means the project or datasource id is wrong.

## 2. Create a contact

`POST /stream/contacts` takes an **array** even when you only have one record. The reserved `_`-prefixed fields are Instasent's known attributes; everything else becomes a custom attribute on the contact.

```bash
curl -X POST "$BASE/stream/contacts" \
  -H "Authorization: Bearer $INSTASENT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "_user_id": "USER-123",
      "_first_name": "Ada",
      "_last_name": "Lovelace",
      "_email": "ada@example.com",
      "_phone_mobile": "+34600000000",
      "plan": "pro",
      "signup_source": "landing-a"
    }
  ]'
```

A `202 Accepted` with a per-item outcome means the contact is in flight to the audience; it will be queryable within seconds. Partial failures come back in the same body — see [Errors](/ingest-api/errors).

> **Tip**: Resending the same `_user_id` updates the contact. Attributes you omit are kept; attributes you send as `null` are cleared.

## 3. Record an event

Events must carry a stable `_event_id` so retries are idempotent. Pick one from your source system (order id, message id, click id…) and reuse it if you ever resend.

```bash
curl -X POST "$BASE/stream/events" \
  -H "Authorization: Bearer $INSTASENT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "_user_id": "USER-123",
      "_event_id": "ORDER-987",
      "_event_type": "purchase",
      "_event_parameters": {
        "currency": "EUR",
        "amount": 49.90,
        "product_sku": "SKU-42"
      }
    }
  ]'
```

`202 Accepted` again. The event lands on the contact's timeline and becomes queryable for segmentation.

> **Warning**: Omitting `_event_date` (as above) defaults it to "now" and lets the event trigger automations. If you pass `_event_date` yourself, it must be within **±1 hour** of reception time — historical or future-dated events are stored and queryable but will not fire automations. See [Automations and the event time window](/ingest-api/guide#automations-and-the-event-time-window).

## 4. (Optional) embed the contact in the event

If your source system produces the event and the contact at the same time, you can skip the separate contacts call:

```json
{
  "_user_id": "USER-456",
  "_event_id": "ORDER-988",
  "_event_type": "purchase",
  "_user_data": {
    "_email": "grace@example.com",
    "_first_name": "Grace"
  },
  "_event_parameters": {
    "currency": "EUR",
    "amount": 12.50
  }
}
```

The contact is upserted before the event is processed. If the upsert fails, the event is skipped.

## 5. Delete the contact (cleanup)

When you are ready to tear down your test run:

```bash
curl -X DELETE "$BASE/stream/contacts/USER-123" \
  -H "Authorization: Bearer $INSTASENT_TOKEN"
```

The contact is permanently removed from the audience.

## What to read next

- [Guide](/ingest-api/guide) - Mental model, merge rules and event handling.
- [Errors](/ingest-api/errors) - Status codes and partial-success shape.
- [API Reference](/ingest-api/reference) - Every endpoint, every parameter.
