# Ordering your first test

For more details on the specific endpoints, follow the OpenAPI reference

Before we begin, let's clarify some key terminology you'll encounter with some analogies:

* `Product Types`: The broadest category of offering (e.g., iPhone, MacBook, iPad)
* `Products`: Individual products within each type (e.g., iPhone 17 Pro, iPhone 16 Pro Max)
* `Product Variants`: The specific configuration an end user receives (e.g., iPhone 17 White 256GB)

### 1. Explore Product Types

* Start off by exploring what product types are available, by calling the `GET api/v1/products` endpoint

{% hint style="info" %}
**🤖 Production Base URL:**&#x20;

```hurl
https://vantage.tryterra.co
```

**🏝️ Sandbox Base URL:**     &#x20;

```hurl
https://vantage-sandbox.tryterra.co
```

{% endhint %}

{% tabs %}
{% tab title="cURL" %}

```hurl
curl --location --request GET \
  'https://vantage-sandbox.tryterra.co/api/v1/products/' \
  --header 'Authorization: Basic <YOUR_CLIENT_ID:YOUR_CLIENT_SECRET_BASE64>'
  
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

url = "https://vantage-sandbox.tryterra.co/api/v1/products/"
headers = {
    'Authorization': 'Basic <YOUR_CLIENT_ID:YOUR_CLIENT_SECRET_BASE64>'
}
response = requests.get(url, headers=headers)
print(response.text)

```

{% endtab %}

{% tab title="GO" %}

```go
package main

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

func main() {
    url := "https://vantage-sandbox.tryterra.co/api/v1/products/"
    
    req, _ := http.NewRequest("GET", url, nil)
    req.Header.Add("Authorization", "Basic <YOUR_CLIENT_ID:YOUR_CLIENT_SECRET_BASE64>")
    
    res, _ := http.DefaultClient.Do(req)
    defer res.Body.Close()
    
    body, _ := io.ReadAll(res.Body)
    fmt.Println(string(body))
}

```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="200" %}

```ruby
[
  {
    "description": "Diagnostic blood panels and biomarker tests",
    "id": 1,
    "name": "Blood Test"
  }
]

```

{% endtab %}
{% endtabs %}

### 2. Explore Products within each product type

* Suppose we are looking to order a blood test. Let's see what Vantage API offers.
* **N.B: '**&#x31;' is the **product type** ID of a blood test as seen in the response above

{% tabs %}
{% tab title="cURL" %}

```hurl
curl --location --request GET \
  'https://vantage-sandbox.tryterra.co/api/v1/products/1' \
  --header 'Authorization: Basic <YOUR_CLIENT_ID:YOUR_CLIENT_SECRET_BASE64>'
  
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

product_type_id = 1
url = "https://vantage-sandbox.tryterra.co/api/v1/products/" + str(product_type_id)
headers = {
    'Authorization': 'Basic <YOUR_CLIENT_ID:YOUR_CLIENT_SECRET_BASE64>'
}
response = requests.get(url, headers=headers)
print(response.text)

```

{% endtab %}

{% tab title="GO" %}

```go
package main

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

func main() {
    productTypeID := 1
    url := fmt.Sprintf("https://vantage-sandbox.tryterra.co/api/v1/products/%d", productTypeID)
    
    req, _ := http.NewRequest("GET", url, nil)
    req.Header.Add("Authorization", "Basic <YOUR_CLIENT_ID:YOUR_CLIENT_SECRET_BASE64>")
    
    res, _ := http.DefaultClient.Do(req)
    defer res.Body.Close()
    
    body, _ := io.ReadAll(res.Body)
    fmt.Println(string(body))
}

```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="200" %}

```ruby
[
    {
        "id": 10002,
        "product_type_id": 1,
        "supplier_id": 2,
        "name": "Blood Test",
        "description": "At-home blood test kit with lab processing.",
        "base_price_cents": 4999,
        "currency": 840,
        "availability": 1
    }
]
```

{% endtab %}
{% endtabs %}

### 3. Explore Product Variants within each Product

* Now let's choose the exact blood test we would like to order
* **N.B** 10002 is the product id of a blood test product as seen in the response above

{% tabs %}
{% tab title="cURL" %}

```hurl
curl --location --request GET \
  'https://vantage-sandbox.tryterra.co/api/v1/products/10002/variants' \
  --header 'Authorization: Basic <YOUR_CLIENT_ID:YOUR_CLIENT_SECRET_BASE64>'
  
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

product_id = 10002
url = "https://vantage-sandbox.tryterra.co/api/v1/products/" + str(product_id) + "/variants"
headers = {
    'Authorization': 'Basic <YOUR_CLIENT_ID:YOUR_CLIENT_SECRET_BASE64>'
}
response = requests.get(url, headers=headers)
print(response.text)

```

{% endtab %}

{% tab title="GO" %}

```go
package main

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

func main() {
    productID := 10002
    url := fmt.Sprintf("https://vantage-sandbox.tryterra.co/api/v1/products/%d/variants", productID)
    
    req, _ := http.NewRequest("GET", url, nil)
    req.Header.Add("Authorization", "Basic <YOUR_CLIENT_ID:YOUR_CLIENT_SECRET_BASE64>")
    
    res, _ := http.DefaultClient.Do(req)
    defer res.Body.Close()
    
    body, _ := io.ReadAll(res.Body)
    fmt.Println(string(body))
}

```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="200" %}

```ruby
[
    {
        "id": 100041,
        "product_id": 10002,
        "product_type_id": 1,
        "product_external_sku": "TA_002",
        "supplier_id": 2,
        "variant_name": "Inflammation",
        "variant_defining_attrs": {
            "biomarkers": [
                "hs-CRP",
                "Vitamin D"
            ],
            "panel": "Inflammation",
            "turnaround_days": "3-5"
        },
        "descriptive_attrs_override": {
            "notes": "Inflammation marker testing"
        },
        "variant_availability": 1,
        "price_cents": 7900,
        "currency": 840,
        "available_collection_types": [
            "AT_HOME",
            "GO_TO_LAB"
        ]
    },
]

```

{% endtab %}
{% endtabs %}

### 4. Order a test kit

* Now let's order one 'Inflammation' test kit (`product_type_id` = 1, `product_id` = 10002, `product_variant_id` = 100041)
  * Note that all you need is the **variant ID** and quantity to make an order&#x20;
  * For now all orders will be in USD (840 in IS0 4217 format)
* Different suppliers have different constraints when ordering
* If you try to order a product variant that does not exist, you can expect the 404 response below

{% tabs %}
{% tab title="cURL" %}

```hurl
curl --location --request POST 'https://vantage-sandbox.tryterra.co/api/v1/orders' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic <YOUR_CLIENT_ID:YOUR_CLIENT_SECRET_BASE64>' \
--data-raw '{
    "client_order_reference_id": "TEST-ORDER-001",
    "recipient": {
        "first_name": "John",
        "last_name": "Smith",
        "email": "john.smith@example.com",
        "phone_number": 4155551234,
        "country_code": 1,
        "date_of_birth": "1995-10-10",
        "gender_at_birth": "m"
    },
    "shipping_address": {
        "address_line_1": "123 Market Street",
        "city": "San Francisco",
        "administrative_area": "CA",
        "country_code": "US",
        "postal_code": "94102"
    },
    "items": [
        {
            "variant_id": 100041,
            "quantity": 1
        }
    ]
}'

```

{% endtab %}

{% tab title="Python" %}

```python
import requests
import json

url = "https://vantage-sandbox.tryterra.co/api/v1/orders"

headers = {
    'Content-Type': 'application/json',
    'Authorization': 'Basic <YOUR_CLIENT_ID:YOUR_CLIENT_SECRET_BASE64>'
}

payload = {
    "client_order_reference_id": "TEST-ORDER-001",
    "recipient": {
        "first_name": "John",
        "last_name": "Smith",
        "email": "john.smith@example.com",
        "phone_number": 4155551234,
        "country_code": 1,
        "date_of_birth": "1995-10-10",
        "gender_at_birth": "m"
    },
    "shipping_address": {
        "address_line_1": "123 Market Street",
        "city": "San Francisco",
        "administrative_area": "CA",
        "country_code": "US",
        "postal_code": "94102"
    },
    "items": [
        {
            "variant_id": 100021,
            "quantity": 1
        }
    ]
}

response = requests.post(url, headers=headers, json=payload)

print(response.text)

```

{% endtab %}

{% tab title="GO" %}

```go
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
)

func main() {
    url := "https://vantage-sandbox.tryterra.co/api/v1/orders"
    
    payload := map[string]interface{}{
        "client_order_reference_id": "TEST-ORDER-001",
        "recipient": map[string]any{
            "first_name":                    "John",
            "last_name":                     "Smith",
            "email":                         "john.smith@example.com",
            "phone_number":                  4155551234,
            "country_code":                  1,
            "date_of_birth":                 "1995-10-10",
            "gender_at_birth":               "m",
        },
        "shipping_address": map[string]any{
            "address_line_1":       "123 Market Street",
            "city":                 "San Francisco",
            "administrative_area":  "CA",
            "country_code":         "US",
            "postal_code":          "94102",
        },
        "items": []map[string]interface{}{
            {
                "variant_id": 100021,
                "quantity":   1,
            },
        },
    }
    
    jsonData, _ := json.Marshal(payload)
    
    req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
    req.Header.Add("Content-Type", "application/json")
    req.Header.Add("Authorization", "Basic <YOUR_CLIENT_ID:YOUR_CLIENT_SECRET_BASE64>")
    
    res, _ := http.DefaultClient.Do(req)
    defer res.Body.Close()
    
    body, _ := io.ReadAll(res.Body)
    fmt.Println(string(body))
}

```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="200" %}

```javascript
{
  "order_id": 251285377984405504,
  "recipient_id": 251285377984405505,
  "order_items": [
    {
      "order_id": 251285377984405504,
      "order_item_id": 251285377984405507,
      "variant_id": 100021,
      "product_type_id": 1,
      "price_per_item_cents": 4999,
      "quantity": 1,
      "currency": 840,
      "results_status": "results.awaiting_sample"
    }
  ],
  "order_status": "order.payment_processing"
}

```

{% endtab %}

{% tab title="404" %}

```python
{
    "detail": "resource not found",
    "instance": "/api/v1/orders",
    "status": 404,
    "title": "Resource Not Found",
    "type": "https://docs.tryterra.co/errors/not-found-error"
}

```

{% endtab %}
{% endtabs %}

### 5. Receiving Webhooks - Verification of Receipt

* Below are the first two webhooks that you will receive if a order is placed successfully
* **N.B:** You will still receive these webhooks even when working with sandbox :)&#x20;

{% hint style="info" %}
Note that in products, `supplier_item_id` will not be provided as this information is only relevant to your end users
{% endhint %}

{% tabs %}
{% tab title="Payment complete" %}

```json
{
  "data": {
    "order_id": 249956252111773696,
    "status": "fulfillment.payment_complete"
  },
  "event_id": 249956266972192768,
  "event_type": "order.status_changed",
  "timestamp": 1763661418
}

```

{% endtab %}

{% tab title="Delivery Fulfiled" %}

```json
{
  "data": {
    "order_id": 249956252111773696,
    "status": "fulfillment.delivery_fulfilled",
    "supplier_item_id": "249956258550030336",
    "tracking_number": "KnD3d5PMZyq5ulNcWkrq"
  },
  "event_id": 249956485092777984,
  "event_type": "order.status_changed",
  "timestamp": 1763661470
}

```

{% endtab %}
{% endtabs %}

### 6. Relax and wait for your new kit :tada:

* If you are working in sandbox, move on to the next section to see how you would receive results!!
* If you are working in prod, still read the next section to see the results flow :handshake:


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.tryterra.co/vantage-api-docs/getting-started/ordering-your-first-test.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
