# Embed API

Core on premise platform allowing integration with Embed TOOLKIT for an integrator to provide a range of Embed common functionality. Stateless RESTful API hosted on-premise.

**Base URI:** `https://{hostname}:{18008}/embed-api/{version}/`

---

## Overview

The Embed API is a stateless RESTful API hosted on-premise that enables internal and external systems to perform actions within the Embed Card System (ECS), such as checking card balances, processing sales, managing games, and more.

### Key Characteristics

| Feature | Details |
|---------|---------|
| Protocol | HTTPS only (plain HTTP not supported) |
| Architecture | Stateless RESTful (on-premise) |
| Authentication | OAuth 2 Client Credentials Grant |
| Data Format | `application/json; charset=utf-8` |
| CORS | Completely open for browser JavaScript consumption |
| Versioning | URI-based: `/embed-api/{major}.{minor}/` |

### Base URI

The Base URI is the connection point to the Embed API, provided in absolute format:

```
https://{hostname|IP address}:{18008}/embed-api/{major}.{minor}/
```

Development and Production Base URIs will be provided by your Embed representative separately.

### HTTP Methods

- **GET** — Retrieve data from the API
- **POST** — Submit or change data

Using the wrong HTTP method will return an error.

### HTTP Status Codes

| Code | Description |
|------|-------------|
| 200 | Request was successful |
| 400 | Request could not be understood or is missing required information |
| 401 | Missing valid authentication details |
| 403 | Authenticated but no permission to access the resource |
| 404 | Resource cannot be found |
| 500 | Internal server error |
| 501 | Resource has not been implemented |

### Multi-Terminal Reporting

If your application connects from multiple terminals (e.g., multiple kiosks), each terminal must send a unique **API-Application-Thumbprint** header so that Embed reports can differentiate actions per terminal.

```
POST https://{base-uri}/embed-api/some/resource HTTP/1.0
API-Application-Thumbprint: d84955fc-90f2-4170-ade6-e9b21409b5c6
API-Device-Description: John's iPhone
```

- **API-Application-Thumbprint** — Minimum: randomly generated GUID, max 200 characters
- **API-Device-Description** — Optional human-friendly terminal name, max 200 characters

### Special Parameters

| Parameter | Description |
|-----------|-------------|
| `suppress_response_codes` | When `true`, all responses return HTTP 200 (useful for Flash/JS apps that intercept non-200 responses) |
| `callback` | JSONP callback function name — wraps JSON response in the specified function |

> Ensure you convert values to UTF-8 and URL-encode them when making requests.

---

## Getting Started

To use the Embed API, the service must first be deployed on your Embed server and you will need API access added to your Embed license. Once this has been done, your Embed representative will provide you with a **Key** and **Secret** (see the Authentication section).

### Supporting Cards / Media

Embed systems support both swipe cards and RFID tap cards (and other RFID media). Embed uses a **19-digit card numbering system** made up of `9 digits (location + validation) + 10-digit card barcode`.

| Media / Format | Details |
|----------------|---------|
| 10-digit barcode | Printed on the rear of the physical card. Used in the PRIZES application and accepted by most API calls. |
| 19-digit card number | Full card number available on the magnetic stripe (swipe) or returned encrypted from an RFID reader tap. |
| 64-byte RFID string | Read from an RFID tap, then base64-encoded. Send the encoded string directly to the API — it expects the encrypted format. |

> Most API endpoints accept your choice of the 10-digit barcode, the full 19-digit card number, or the 64-byte RFID encrypted base64 string.

### Common API Use Cases

#### Use Case 1: Check a Guest's Card Balance

Allows a staff member to assist a guest when they have a question related to balances. The response provides a breakdown of each balance including a currency version and a converted "points" version for play balances, eticket balance, card status, and play privilege details.

```
GET [base URI]/card/[19 digits or 10 digit barcode]
GET [base URI]/card/mifareultralight/[64 byte string]
```

#### Use Case 2: Check a Guest's Recent Transactions

Allows staff to assist where there are disputes about balances or where a guest reports crediting a game that did not work. Can be filtered to return only game transactions, only non-game transactions, or all transactions (default).

```
GET [base URI]/card_history/[19 digits or 10 digit barcode]
GET [base URI]/card_history/mifareultralight/[64 byte string]
```

Example response entry:

```json
{
  "date_time":   "2012-08-23 13:55:22",
  "type":        "PLAY",
  "description": "GHOST Squad LEFT",
  "amount":      "3.00",
  "bonus":       "1.00",
  "tickets":     0,
  "points":      "0.00",
  "status": {
    "id":          0,
    "description": "Normal"
  }
}
```

#### Use Case 3: Making Sales of Embed Card Products

The most common use case for integration. Use the `mobile templates` endpoint to retrieve available products for sale — these are configured in the GURU application by the operator. If not using mobile templates, configure products in your software by copying the Embed product ID from GURU.

It is common in operations to start a sale that does not get completed. Many integrators begin each new sales flow with a **cancel** call to clear any existing in-progress products on the current terminal before starting fresh.

**Typical sales flow:**

```
1. Sale → Cancel
2. Sale → Add Item   (repeat for multiple items)
3. Sale → Tender
```

**Step 2 — Add an item:**

Send the `product_id, product_type, and card_id`. The response includes product value, new card costs, and the total including taxes.

```
POST [base URI]/sale/add_item

{
  "product_id":   "123",
  "product_type": 2,
  "card_id":      "0000095808299126033"
}
```

**Step 3 — Tender the sale:**

Send the `cashier_id, tender_amount, and tender_type`. The tender amount **must** match the sale total. If staff identity and payment method are not required for Embed reporting, generic values may be used.

```
POST [base URI]/current_sale/tender

{
  "cashier_id":    "76",
  "tender_amount": "50.00",
  "tender_type":   "cash"
}
```

---

## Authentication

The Embed API uses **OAuth 2 Client Credentials Grant** for authentication. Since the API is stateless, every request must include a Bearer Token in the `Authorization` header. The token is obtained by exchanging your Consumer Key and Consumer Secret.

> Your Consumer Key and Consumer Secret will be provided by an Embed representative separately from this documentation.

### Getting a Bearer Token

Exchange your credentials for a Bearer Token using the token endpoint:

```
POST https://{base-uri}/embed-api/auth/request_token HTTP/1.1
Authorization: Basic {base64(consumer_key:consumer_secret)}
Content-Type: application/x-www-form-urlencoded; charset=utf-8

grant_type=client_credentials&scope=cards_read%20cards_write
```

#### Parameters

| Parameter | Required | Description |
|-----------|----------|-------------|
| `grant_type` | Yes | Must be `client_credentials` |
| `scope` | No | Space-delimited list of scopes (e.g., `cards_read cards_write`) |

#### Successful Response

```
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{
  "access_token": "EDGjsCnBnYR5O0Z7k53G6f9BiksJl6I4Eao...",
  "token_type": "bearer",
  "expires_in": 3600,
  "scope": "cards_read cards_write"
}
```

> Bearer Tokens expire after **1 hour** (3600 seconds). Once expired, you must request a new token.

### Using the Bearer Token

Include the token in every API request via the `Authorization` header:

```
GET https://{base-uri}/embed-api/1.0/lists/general_settings HTTP/1.1
Accept: application/json
API-Application-Thumbprint: d84955fc-90f2-4170-ade6-e9b21409b5c6
Authorization: Bearer EDGjsCnBnYR5O0Z7k53G6f9BiksJl6I4Eao...
```

### Error Responses

| Scenario | HTTP Code | Error |
|----------|-----------|-------|
| No credentials provided | 400 | `invalid_request` |
| Bearer Token not provided | 400 | `invalid_request — "Missing access token."` |
| Missing application thumbprint | 400 | `invalid_token — "Application thumbprint was not supplied"` |
| Token tampered / corrupt | 401 | `invalid_token — "Decoding failed due to data corruption"` |
| Token expired | 401 | `invalid_token — "The message expired at..."` |
| Token revoked | 401 | `invalid_token — "Token has been revoked"` |
| Application not authorised | 401 | `invalid_token — "Application not authorised"` |
| Application not found | 401 | `invalid_token — "Application not found"` |
| Bad license | 401 | `invalid_token — "License verification failed"` |
| Invalid license/app not enabled | 401 | `invalid_token — "Invalid license or application not enabled"` |
| Insufficient scope | 403 | `insufficient_scope — "Needs {scope} scope"` |

### OAuth 2 Resource Scopes

Each API resource is associated with a pre-defined scope. Request only the scopes you need to limit risk if a token is compromised.

| Scope | Access |
|-------|--------|
| `system_read` | System time, general settings, card types, card prefixes, card statuses |
| `cards_read` | Card queries, card history, plays, timed statuses, verify CVC |
| `cards_write` | Card adjustments, reversals, holds, reissues, recycles, virtual swipes, add/remove play |
| `guests_read` | Guest search |
| `guests_write` | Update guest details |
| `games_read` | Pause groups, game categories, swipers, game stations |
| `games_write` | Swiper control, pause group control |

> Only request the scopes you need during token exchange. This limits exposure if the Bearer Token is ever compromised.
