# HAL Response Format

The Cineamo API uses **HAL (Hypertext Application Language)** for all responses.

## What is HAL?

HAL provides a consistent way to hyperlink between resources. It makes APIs self-documenting and discoverable.

**Key Principles**:
- Resources have their own URLs (`_links.self`)
- Related data is embedded (`_embedded`)
- Navigation is built-in (next, prev, first, last pages)
- Hypermedia-driven discoverability

**Official Spec**: [HAL Specification](https://stateless.group/hal_specification.html)

---

## 🎯 Why HAL?

**Benefits**:
1. Self-documenting - Links show what's possible
2. Consistency - Same structure everywhere
3. Built-in pagination
4. Each resource has a canonical URL
5. Easy API evolution without breaking clients

### Comparison

**Traditional JSON**:
```json
{
  "data": [...],
  "total": 100,
  "page": 1
}
```

**HAL**:
```json
{
  "_embedded": { "cinemas": [...] },
  "_total_items": 100,
  "_page": 1,
  "_links": {
    "self": { "href": "/cinemas?page=1" },
    "next": { "href": "/cinemas?page=2" }
  }
}
```

---

## 🏗️ HAL Structure

Every HAL response has these elements:

### 1. Resource Properties

Direct properties (not prefixed with `_`):

```json
{
  "id": 123,
  "name": "Cineplex Berlin",
  "city": "Berlin"
}
```

### 2. `_links` - Hypermedia Links

Links to related resources and navigation:

```json
{
  "_links": {
    "self": { "href": "/cinemas/123" },
    "next": { "href": "/cinemas?page=2" }
  }
}
```

### 3. `_embedded` - Related Resources

Embedded collections or related data:

```json
{
  "_embedded": {
    "cinemas": [
      { "id": 1, "name": "Cinema 1" },
      { "id": 2, "name": "Cinema 2" }
    ]
  }
}
```

### 4. Pagination Metadata

Cineamo extends HAL with pagination fields:

```json
{
  "_total_items": 487,
  "_page": 1,
  "_page_count": 5
}
```

---

## 📦 Collection Response Example

```json
{
  "_total_items": 487,
  "_page": 1,
  "_page_count": 5,
  "_links": {
    "self": { "href": "/cinemas?per_page=100&page=1" },
    "next": { "href": "/cinemas?per_page=100&page=2" },
    "last": { "href": "/cinemas?per_page=100&page=5" }
  },
  "_embedded": {
    "cinemas": [
      {
        "id": 123,
        "name": "Cineplex Berlin",
        "city": "Berlin",
        "_links": {
          "self": { "href": "/cinemas/123" }
        }
      }
    ]
  }
}
```

**Key Points**:
- Collection name matches resource type: `cinemas`, `showings`
- Each item has its own `_links.self`
- Pagination links at root level
- Metadata at root: `_total_items`, `_page`, `_page_count`

---

## 🎬 Single Resource Example

```json
{
  "id": 123,
  "name": "Cineplex Berlin",
  "city": "Berlin",
  "_links": {
    "self": { "href": "/cinemas/123" }
  }
}
```

### With Embedded Resources

When using `embed[]` parameters:

```json
{
  "id": 98765,
  "name": "Inception",
  "startDatetime": "2025-11-08T19:30:00Z",
  "_links": {
    "self": { "href": "/showings/98765" }
  },
  "_embedded": {
    "cinema": {
      "id": 123,
      "name": "Cineplex Berlin",
      "_links": {
        "self": { "href": "/cinemas/123" }
        }
      }
    },
    "content": {
      "id": 456,
      "title": "Inception",
      "_links": {
        "self": { "href": "/contents/456" }
      }
    }
  }
}
```

---

## 🧭 Accessing HAL Data

### Accessing Collections

```javascript
const response = await fetch('https://api.cineamo.com/cinemas');
const data = await response.json();

// Access collection
const cinemas = data._embedded.cinemas;

// Access pagination
const totalItems = data._total_items;
const currentPage = data._page;
const totalPages = data._page_count;

// Check for next page
const hasNextPage = !!data._links.next;
```

### Following Links

```javascript
// Get next page link
const nextPageUrl = data._links.next?.href;

if (nextPageUrl) {
  const nextResponse = await fetch(`https://api.cineamo.com${nextPageUrl}`);
}
```

### Accessing Embedded Resources

```javascript
const showings = data._embedded.showings;

showings.forEach(showing => {
  const movieTitle = showing._embedded?.content?.title;
  const cinemaName = showing._embedded?.cinema?.name;
});
```

---

## ⚠️ Common Pitfalls

### ❌ Accessing Data Directly

```javascript
// Wrong
const cinemas = data.cinemas; // undefined

// Correct
const cinemas = data._embedded.cinemas;
```

### ❌ Assuming Flat Pagination

```javascript
// Wrong
const total = data.total; // undefined

// Correct
const total = data._total_items;
```

### ❌ Ignoring Links

```javascript
// Wrong - hardcoding
const nextUrl = `/cinemas?page=${currentPage + 1}`;

// Correct - follow HAL links
const nextUrl = data._links.next?.href;
```

---

## 🚀 Available Links

Common link relations in Cineamo API:

| Link | Description |
|------|-------------|
| `self` | Current resource URL |
| `next` | Next page in pagination |
| `prev` | Previous page in pagination |
| `first` | First page in pagination |
| `last` | Last page in pagination |

---

## 📚 See Also

- [PHP Array Parameters](/php-arrays) - Understanding array syntax in URLs
- [Authentication](/authentication) - How to authenticate API requests
- [Fetching Showtimes](/showtimes) - Practical HAL usage examples
- [API Reference](/api) - Complete endpoint documentation

**Further Reading**:
- [HAL Specification](https://stateless.group/hal_specification.html)
