# Ads

## GET /api/adcenter/v1/ads/

Returns every banner ad currently being served, in the intended render order — first in the list goes first.

| | |
|---|---|
| **Method** | `GET` |
| **URL** | `https://app.vzla.io/api/adcenter/v1/ads/` |
| **Authentication** | `Authorization: Bearer vzlaio_...` |
| **Parameters** | None |

### Request

```bash
curl --request GET \
  --url 'https://app.vzla.io/api/adcenter/v1/ads/' \
  --header 'Authorization: Bearer vzlaio_YOUR_TOKEN_HERE'
```

### Response

#### `data`

An array of ad objects. Empty when no ads are being served.

| Field | Type | Description |
|---|---|---|
| `ad_id` | string (UUID) | Stable public identifier for this ad. Use it to deduplicate and to attribute clicks |
| `title` | string | The banner headline. Always present |
| `link` | string (URL) | Destination to open when the banner is tapped. Always present |
| `description` | string or null | Optional supporting line. Render the ad without it when `null` |
| `expires_at` | string (ISO 8601 datetime) or null | When the ad stops being served. `null` means it does not expire |

#### `meta`

| Field | Type | Description |
|---|---|---|
| `count` | integer | Number of ads in `data` |

### Example response

```json
{
  "data": [
    {
      "ad_id": "5edce7fa-0109-49a7-8aff-0e5eb27e9560",
      "title": "⚽ ¿Cuánto sabes realmente de fútbol?",
      "link": "https://futbble.com/descargar",
      "description": null,
      "expires_at": "2026-09-21T12:00:20-04:00"
    },
    {
      "ad_id": "daa03fb6-9647-4ce6-ba53-f1700177fe92",
      "title": "DressDocs",
      "link": "https://futbble.com/#descargar",
      "description": "No dejes que tus documentos salgan mostrando picon.",
      "expires_at": "2026-09-22T12:20:14-04:00"
    }
  ],
  "meta": {
    "count": 2
  }
}
```

### HTTP status codes

| Code | Meaning |
|---|---|
| `200 OK` | Success. |
| `401 Unauthorized` | Missing or invalid token. |
| `403 Forbidden` | Token was issued for a different vzla.io API. |
| `405 Method Not Allowed` | Only GET is supported. |
| `429 Too Many Requests` | Monthly quota exhausted, or hourly rate limit hit. |
| `500 Internal Server Error` | Server error. Retry after a short delay. |

#### 401 — no Authorization header

```json
{
  "error": {
    "code": "auth_missing",
    "message": "Authentication credentials were not provided"
  }
}
```

#### 401 — invalid token

```json
{
  "error": {
    "code": "auth_token_unknown",
    "message": "Invalid token format"
  }
}
```

#### 403 — token belongs to another API

```json
{
  "error": {
    "code": "product_forbidden",
    "message": "This token is not valid for this API"
  }
}
```

#### 429

```json
{
  "error": {
    "code": "quota_exceeded",
    "message": "Monthly quota exceeded. Limit: 1000 requests/month"
  }
}
```
**Note:** This endpoint is cached for **5 minutes**. An ad that is disabled or passes its `expires_at` can take that long to disappear from the response.
**Tip:** Respect `expires_at` on your side too. If you cache ads for longer than 5 minutes, drop any ad whose `expires_at` has passed before rendering it.