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

# Authenticated Routes

> Learn how to interact with our API using user credentials.

# Authenticated Routes

## Introduction

API Keys alone do not provide complete security, we use them as a way to identify the calling client, but not for authentication and authorization. Here is an article to read more about why:

[API Keys ≠ Security: Why API Keys Are Not Enough | Nordic APIs |](https://nordicapis.com/why-api-keys-are-not-enough/)

To provide additional security we use the API Key together with the JWT authentication scheme (for third-party non-browser clients). Some routes might be protected to only authorized users. To read more about JWT in the following article:

[Refresh Tokens: When to Use Them and How They Interact with JWTs](https://auth0.com/blog/refresh-tokens-what-are-they-and-when-to-use-them/)

## How does it work?

Use the provided `email` and `password` credentials to obtain an Access token.

This token will authenticate the request and grant you authorization to call the Vitau API's protected resources, therefore, it should be included within the header of each request.

Access tokens must be short lived, decoding the token will show the `access_lifetime` field in seconds. For example, an expiry value of 3600 expires in one hour. To handle token expiration you might want to:

* Set a timer to update the access token before it expires.
* Keep track of obtained time + `access_lifetime`.

Re-use the access token until it expires, then get a new token.

See more of decoding-encoding jwt: [JWT IO](https://jwt.io/)

## Obtaining token

```bash theme={null}
Request:
curl --request POST \\
  --url API_URL/api/token/ \\
  --header 'Accept: application/json' \\
	--header 'Content-Type: application/json' \\
  --header 'X-API-Key: Client API Key'
	--data '{"email":STRING, "password": STRING}'

Response:
Status Code: 200 OK
{
  "access" TOKEN
}

```

### Responses

| Status           | Meaning                                                                        |
| ---------------- | ------------------------------------------------------------------------------ |
| 200 OK           | Authentication completed successfully and you'll receive a valid access token. |
| 401 Unauthorized | The given email/password pair is not correct.                                  |

## Prove authentication

The access token must be present in the Authorization header.

```bash theme={null}
Request:
curl --request GET \\
  --url API_URL/api/some-route/ \\
  --header 'Accept: application/json' \\
  --header 'X-API-Key: Client API Key' \\
  --header 'Authorization: Bearer {ACCESS_TOKEN}'

```

An expired token will return `401 Unauthorized`

## Orders

An order is a customer's request to purchase products from Vitau. The Order object consists primarily of:

* Patient's personal information
* Delivery address. (This might also be picked up at Vitau Store).
* Details is an array with the quantity of each product to be purchased
* Payment method
* Relevant dates such as creation, expected delivery, etc.
* Invoicing details. (Optional)
* Order status
* Payment status

### CREATE

This service creates an ORDER object, along with the USER, SHIPPING, and INVOICING information if they're included within the payload.

The products and quantities of the Order are specified inside an array of `DETAIL` objects. Each detail has `{"product": ID, "quantity":INT}`.

The `payment_method` ID must be the one given along with the Client's API KEY.

Request objects:

* USER
  * "email": STRING & UNIQUE
  * "phone": UNIQUE, Format: +(COUNTRY-CODE)(PHONE) e.g. +528188888888
  * "first\_name": STRING
  * "last\_name": STRING
* INVOICING
  * "full\_name": STRING
  * "email": STRING
  * "rfc": STRING
  * "street": STRING
  * "exterior\_number": STRING
  * "neighborhood": STRING
  * "city": STRING
  * "state": STRING
  * "country": STRING
  * "zipcode": STRING
* SHIPPING
  * "street": STRING
  * "exterior\_number": STRING
  * "interior\_number": STRING
  * "neighborhood": STRING
  * "city": STRING
  * "state": STRING
  * "country": STRING
  * "zipcode": STRING
  * "phone": STRING
* PRESCRIPTION
  * "document": BASE64 STRING
  * "document\_name": STRING OPTIONAL
  * "issue\_date": DATE (Y-m-d)
  * "expiring\_date": DATE (Y-m-d) OPTIONAL

Purchase order status ENUM values:

* patient\_order\_status
  * "in\_process" : The order has been created successfully.
  * "shipped": The order has been dispatched and is on its way.
  * "delivered": The order has been delivered to the client.
  * "cancelled": The order has been cancelled.
* payment\_status
  * "unpaid": The order has not been paid.
  * "credit": The order is placed under credit and will be paid within a specified timeframe.
  * "paid": The order has been paid.
  * "rejected": The payment processor rejected the transaction.
  * "in\_process": The payment processor is processing the transaction.

```bash theme={null}
Request:
curl --request POST \\
  --url API_URL/api/orders/resources/ \\
  --header 'Accept: application/json' \\
  --header 'X-API-Key: {Client API Key}' \\
	--header 'Authorization: Bearer {ACCESS_TOKEN}'
	--data \\
		{
		"user":  USER, REQUIRED,
		"invoicing": INVOICING, OPTIONAL, // Sending invoicing info. will generate and send the invoice
		"order": {
			"details":[{"product":INT,"quantity":INT} ...], REQUIRED
			"shipping": SHIPPING, OPTIONAL
			"shipping_method": INT, OPTIONAL // Selected shipping method from the valid methods for this zip code.
			"store": 1, OPTIONAL, // To be picked up at Vitau's store.
			"payment_method": INT, REQUIRED,
			"coupon": STRING, OPTIONAL // Coupon code,
			"prescriptions":[ PRESCRIPTION ], OPTIONAL // Array of PRESCRIPTION objects
			"comments": TEXT, OPTIONAL,
			}
		}

Response:
Status Code: 201 Created
{
"subtotal": DOUBLE,
"shipping_price": DOUBLE,
"shipping_discount": DOUBLE,
"coupon": {
	"code": STRING,
	"value": DOUBLE // Between 0 and 1 is a percentage, else has a fixed value.
},
"discount":DOUBLE,
"iva":DOUBLE,
"total": DOUBLE,
"selected_shipping_method": INT,
"expected_delivery_date": UTC DATETIME,
"max_delivery_date": UTC DATETIME,
"details":
	[{
    "product": INT,
    "quantity": INT,
    "subtotal": DOUBLE,
    "discount": DOUBLE,
    "iva":DOUBLE,
    "total": DOUBLE
	}...],
"shipping": SHIPPING,
"store": STORE,
"patient_order_status": "in_process",
"payment_status": ENUM,
...
}

```

### Error messages

| Status                      | Meaning                                                                                                                                                                                     |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400 Bad Request             | This response may be the result if any value from the payload is missing or incorrect, and the service will respond with the corresponding message explaining the error.                    |
| 201 Created. Invoice error  | When generating an invoice fails the order will be created along with the other resources, however the order will not have a value in the cfdi attribute, and the email will not be sent.   |
| 201 Created. Coupon invalid | As with calculate, the order will be created along with the other resources, however, it will not have a value in the coupon attribute, and the corresponding discount will not be applied. |

### GET

* Searchable lookup fields
  * Patient's full name
* Filterable fields
  * patient=INT
  * order\_status\_\_in=ENUMs separated by commas
  * exclude\_order\_status\_\_in=ENUMs separated by commas
  * payment\_status\_\_in=ENUMs separated by commas
  * expected\_delivery\_date\_before DATE
  * expected\_delivery\_date\_after DATE
  * max\_delivery\_date\_before DATE
  * max\_delivery\_date\_after DATE
* Ordering fields
  * created\_at This is the default by descending order
  * expected\_delivery\_date

```bash theme={null}
Request:
curl --request GET \\
  --url API_URL/api/orders/ \\
  --header 'Accept: application/json' \\
  --header 'X-API-Key: {Client API Key}' \\
	--header 'Authorization: Bearer {ACCESS_TOKEN}'

Response:
Status Code: 200 OK
{
"count": INT,
"next": "API_URL/api/orders/?page=2",
"previous": null,
"results": [
      {
        "id": INT,
        "created_at": DATETIME,
        "order_status": ENUM,
        "patient_order_status": ENUM,
        "patient": STRING,
        "payment_status": ENUM,
        "products_count": INT,
        "details": [{"default_image": URL,"quantity": INT}],
        "shipping": {"street": STRING,"exterior_number": STRING,"city": STRING},
        "payment_method": STRING,
        "total": DOUBLE,
        "origin": STRING,
        "expected_delivery_date": DATETIME,
        "max_delivery_date": DATETIME,
      },
	...,
	]
}

```

### Details

You might want to fetch a specific order and view more details.

The API will respond with 404 if the order is not found or you don't have permission to view it.

```bash theme={null}
Request:
curl --request GET \\
  --url API_URL/api/orders/{orderID} \\
  --header 'Accept: application/json' \\
  --header 'X-API-Key: {Client API Key}' \\
	--header 'Authorization: Bearer {ACCESS_TOKEN}'

Response:
Status Code: 200 OK
{
"count": INT,
"next": "API_URL/api/orders/?page=2",
"previous": null,
"results": [
      {
        "id": INT,
		    "details": [{
						"id": INT,
						"product": PRODUCT,
            "price": DOUBLE,
            "subtotal": DOUBLE,
            "total": DOUBLE,
            "discount": DOUBLE,
            "iva": DOUBLE,
            "quantity": INT
        }],
		    "patient": {
					"id": INT,
					"user": USER,
	        "default_shipping": INT,
	        "default_invoicing": INT,
	        "preferred_payment": INT
		    },
		    "shipping": SHIPPING,
		    "store": INT,
		    "payment": INT,
		    "payment_references": [REFERENCE],
		    "payment_method": PAYMENT_METHOD,
		    "coupon": COUPON,
		    "generated_by": USER,
		    "updated_by": USER,
		    "invoicing": INT,
		    "payment_date": DATETIME,
		    "shipping_date": DATETIME,
		    "expected_delivery_date": DATETIME,
		    "max_delivery_date": DATETIME,
		    "receiving_date": DATETIME,
		    "patient_order_status": ENUM,
		    "prescriptions": [PRESCRIPTION],
		    "shipping_method": SHIPPING_METHOD,
		    "created_at": DATETIME,
		    "updated_at": DATETIME,
		    "insurance_refund_status": ENUM,
		    "order_status": ENUM,
		    "payment_status": ENUM,
		    "rejection_reason": STRING,
		    "origin": STRING,
		    "subtotal": DOUBLE,
		    "iva": DOUBLE,
		    "shipping_price": DOUBLE,
		    "shipping_discount": DOUBLE,
		    "shipping_cost": DOUBLE,
		    "discount": DOUBLE,
		    "total": DOUBLE,
		    "cfdi": STRING,
		    "reminder": REMINDER
      },
	...,
	]
}

```

### UPDATE

After the order is created you may only change the products if the status is `quoted` or `approved`. The URL includes the ID of the order to be modified. As you may only edit certain attributes we recommend using `PATCH`.

```bash theme={null}
Request:
curl --request PATCH \\
  --url API_URL/api/orders/{orderID}/ \\
  --header 'Accept: application/json' \\
  --header 'X-API-Key: {Client API Key}' \\
	--header 'Authorization: Bearer {ACCESS_TOKEN}'
	--data \\
		{
		// This array will override the existing order details and recalculate totals
		"details":[{"product":INT,"quantity":INT} ...]
		}

Response:
Status Code: 200 OK
{
"subtotal": DOUBLE,
"shipping_price": DOUBLE,
"shipping_discount": DOUBLE,
"coupon": {
	"code": STRING,
	"value": DOUBLE // Between 0 and 1 is a percentage, else has a fixed value.
},
"discount":DOUBLE,
"iva":DOUBLE,
"total": DOUBLE,
"selected_shipping_method": INT,
"expected_delivery_date": UTC DATETIME,
"max_delivery_date": UTC DATETIME,
"details":
	[{
    "product": INT,
    "quantity": INT,
    "subtotal": DOUBLE,
    "discount": DOUBLE,
    "iva":DOUBLE,
    "total": DOUBLE
	}...],
"shipping": SHIPPING,
"store": STORE,
"patient_order_status": "in_process",
"payment_status": ENUM,
...
}

```

Besides updating the order details you can also cancel the order when we have not started building or dispatching it. Simply, send the order status with value `cancelled` . This operation cannot be undone.

```bash theme={null}
Request:
curl --request PATCH \\
  --url API_URL/api/orders/{orderID}/ \\
  --header 'Accept: application/json' \\
  --header 'X-API-Key: {Client API Key}' \\
	--header 'Authorization: Bearer {ACCESS_TOKEN}'
	--data \\
		{
			"order_status": "cancelled"
		}

Response:
Status Code: 200 OK

```

### Request Invoice

After creating an order you may request to generate an invoice simply by sending the ID of the corresponding invoicing information, however, there are some limitations:

* After creating the order you have up to 3 days
* Orders of past months cannot request invoice
* INVOICING
  * "full\_name": STRING
  * "email": STRING
  * "rfc": STRING
  * "street": STRING
  * "exterior\_number": STRING
  * "neighborhood": STRING
  * "city": STRING
  * "state": STRING
  * "country": STRING
  * "zipcode": STRING
  * "cfdi\_use": STRING
  * "fiscal\_regime": STRING

Example request:

```bash theme={null}
Request:
curl --request PUT \\
  --url API_URL/api/orders/{orderID}/request-invoice/ \\
  --header 'Accept: application/json' \\
  --header 'X-API-Key: {Client API Key}' \\
	--header 'Authorization: Bearer {ACCESS_TOKEN}'
	--data \\
		{
			"invoicing": INVOICING
		}

Response:
Status Code: 200 OK

```
