---
title: "How to Export Data from HaloITSM: API Limits, Methods & Portability"
slug: how-to-export-data-from-haloitsm-api-limits-methods-portability
date: 2026-09-18
author: Abdul Aleem
categories: [HaloITSM]
excerpt: "Learn how to export data from HaloITSM using UI exports, SQL reports, and the REST API. Covers API rate limits, pagination, authentication, and migration edge cases."
tldr: "HaloITSM offers three export paths — UI CSV exports, SQL-backed reports, and a REST API capped at 700 requests per 5 minutes — each with different trade-offs for volume, automation, and data completeness."
canonical: https://clonepartner.com/blog/how-to-export-data-from-haloitsm-api-limits-methods-portability
---

# How to Export Data from HaloITSM: API Limits, Methods & Portability


# How to Export Data from HaloITSM: API Limits, Methods & Portability

HaloITSM gives you three paths to get data out: **UI-based CSV/Excel exports** from list views and reports, **SQL-backed custom reports** using the built-in reporting engine, and the **REST API** for full programmatic extraction. Which one you pick depends on volume, frequency, and whether a human or a script is doing the work. This guide covers all three methods with the technical constraints that actually matter when you're planning a migration or building an integration.

## Three Ways to Export Data from HaloITSM

| Method | Best for | Format | Volume limit | Automation |
|---|---|---|---|---|
| UI CSV/Excel export | Ad-hoc pulls, small datasets | CSV, Excel | View-dependent | Manual only |
| Reporting engine (SQL) | Structured recurring exports | CSV, Excel, PDF, email | Query-dependent | Schedulable |
| REST API | Full extraction, migration, sync | JSON | 700 req/5 min per tenant | Fully scriptable |

## How to Export Data from the HaloITSM UI

The fastest way to pull a small dataset out of HaloITSM is the built-in list export. Navigate to any list view — tickets, assets, software, users — apply your filters, and click **Export → CSV** (or **Export → Excel**).

Here's the step-by-step for asset data as an example:

1. Log in to your HaloITSM portal
2. Navigate to **Configuration → Assets → Software**
3. Apply filters to scope the dataset (e.g., active devices, specific software categories)
4. Click **Export → CSV** or **Export → Excel**
5. Save the file locally

You can also create a reusable export structure by building a custom View or Report under **Reports → New Report**, which lets you define exactly which fields appear in the output and reuse that structure later.

> [!WARNING]
> UI exports are limited to the columns and rows visible in the current view. If you need to export tens of thousands of records or include relational data (e.g., ticket actions and attachments together), the UI export won't cut it. Use the API or a custom SQL report instead.

## HaloITSM Reporting Engine: SQL-Backed Exports

**HaloITSM's reporting suite** provides read-only access to the underlying Microsoft SQL Server database, which makes it one of the most flexible export tools in the platform. You can write custom SQL queries to pull exactly the data you need, export the results to CSV, and schedule reports to run automatically via email.

The reporting engine supports two approaches:

- **Query Builder** — a visual interface that generates SQL behind the scenes. You pick tables, columns, filters, and sort orders; HaloITSM writes the query. You can switch the data source to "Custom SQL Query" to view and edit the generated SQL directly.
- **Custom SQL Query** — write raw T-SQL against the database. Halo publishes database schema documentation covering the Faults table (all tickets/incidents/problems) and the Asset and Contract tables.

### Key SQL Tables and Status Codes

The `Faults` table is the central table for all ITIL request types — incidents, service requests, changes, and problems. Status values are stored as integers. Key status codes in the `Faults` table:

| Status Code | Meaning |
|---|---|
| 1 | New / Open |
| 2 | In Progress |
| 4 | On Hold / Awaiting Response |
| 9 | Closed |
| 11 | Resolved (not yet closed) |

A typical query for all open, non-deleted, non-merged tickets:

```sql
SELECT
  F.Faultid        AS [Ticket ID],
  F.Symptom        AS [Subject],
  F.dateoccured    AS [Date Created],
  F.Status         AS [Status Code],
  A.Aareadesc      AS [Customer],
  U.Uname          AS [Agent]
FROM Faults F
JOIN Area  A ON A.AAREA  = F.Areaint
JOIN Uname U ON U.Unum   = F.assignedtoint
WHERE F.Status          <> 9   -- exclude Closed
  AND F.fdeleted         = 0   -- exclude soft-deleted records
  AND F.fmergedintofaultid = 0 -- exclude tickets merged into another
```

`Status <> 9` excludes closed tickets. `fdeleted = 0` excludes soft-deleted records. `fmergedintofaultid = 0` excludes tickets that have been merged into a parent ticket.

Reports built this way can be exported to CSV, Excel, or PDF — or scheduled for email delivery on a recurring basis.

> [!TIP]
> HaloITSM ships with 500+ out-of-the-box reports. Before writing custom SQL, check whether an existing report already covers your use case — it often does, and you can clone and modify it.

## HaloITSM REST API: Full Programmatic Data Export

**The HaloITSM API** is a REST-based interface using JSON over HTTPS that exposes tickets, assets, users, knowledge articles, configuration data, and more for programmatic read and write access. It's the only export method that supports full automation, handles relational data, and scales to large datasets.

### API Versioning and Stability

HaloITSM does not use explicit version prefixes in the base API path (e.g., `/api/v1/`). The API path structure is `https://yourcompany.haloitsm.com/api/{Resource}`. HaloITSM documents breaking changes in their release notes by version number; verify endpoint behavior against your specific instance version, as field names and available endpoints have evolved across major releases (particularly between the 2.x and current 2023+ series).

### How Does HaloITSM API Authentication Work?

HaloITSM uses **OAuth 2.0 client credentials flow** for API authentication — no user login required. Tokens are requested against the `/auth/token` endpoint and have a default expiry of **1 hour (3600 seconds)**. HaloITSM does **not** issue refresh tokens under the client credentials flow; when a token expires, request a new one using the same client ID and secret.

Setup steps:

1. Go to **Configuration → Integrations → HaloITSM API**
2. Click **View Applications**, then **Add** to create a new application
3. Set the **Authentication Method** to "Client ID and Secret (Services)"
4. Click **Generate** to create your credentials
5. Copy the **Client ID** and **Client Secret**
6. Set the **Login Type** to Agent and select the agent account the API will act as
7. On the **Permissions** tab, grant the scopes the application needs (e.g., read:tickets, read:assets, read:users)

Your API base URL follows the pattern `https://yourcompany.haloitsm.com/api/`. Include the Bearer token in every API call as `Authorization: Bearer <token>`. Build token refresh logic into your extraction pipeline — a long-running export that crosses the 1-hour mark will start receiving 401 responses without it.

```bash
# Request an access token
curl -X POST https://yourcompany.haloitsm.com/auth/token \
  -d "grant_type=client_credentials" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "scope=all"

# Response includes: access_token, token_type, expires_in (seconds)

# Fetch the first page of tickets
curl -H "Authorization: Bearer <token>" \
  "https://yourcompany.haloitsm.com/api/Tickets?page_size=50&page_no=1"
```

### What Is the HaloITSM API Rate Limit?

The HaloITSM API rate limit is **700 requests per 300-second (5-minute) rolling window**, applied per tenant. That works out to roughly **2.3 requests per second** sustained.

When you exceed the limit, the API returns **HTTP 429 Too Many Requests**. The 429 response body follows this structure:

```json
{
  "status": 429,
  "message": "Rate limit exceeded. Please wait before making further requests."
}
```

The API does not currently include a `Retry-After` header in 429 responses. The rate limit operates as a **sliding window** (not a fixed bucket reset), which means you cannot rely on a predictable reset time. Use exponential backoff with jitter rather than a fixed sleep interval.

**Rate limit planning for bulk exports:**

- 50,000 tickets at 100 records/page = 500 API calls for ticket list data alone
- Each ticket with actions requires an additional `/api/Actions?ticket_id={id}` call — potentially 50,000 more calls
- Attachments require separate download calls per file
- Total API calls for a full 50,000-ticket export with actions and attachments can exceed 150,000 — approximately 18+ hours at the sustained rate limit

> [!WARNING]
> The 700-request limit is per application, per tenant. If other integrations (monitoring tools, PSA connectors, automation scripts) share the same tenant, their requests count against the same pool. Schedule bulk exports during low-activity windows, and build exponential backoff with jitter to handle 429 responses without compounding the problem.

### How Does HaloITSM API Pagination Work?

HaloITSM uses **page-based pagination** with `page_no` and `page_size` query parameters. The API returns a `record_count` field in list responses so you can calculate total pages upfront.

**Maximum page size:** The documented maximum `page_size` is **1000 records per request** on most list endpoints. Using the maximum page size minimizes total API calls and is strongly recommended for bulk extraction. (Some endpoints may enforce lower limits — verify against the specific resource's documentation.)

```python
import requests
import time
import random

def export_all_tickets(base_url, token, page_size=1000):
    """
    Export all tickets using page-based pagination.
    Max page_size is 1000. Uses exponential backoff with jitter on 429.
    Token expires in 3600s — refresh logic omitted for brevity.
    """
    tickets = []
    page = 1
    backoff = 1

    while True:
        resp = requests.get(
            f"{base_url}/api/Tickets",
            headers={"Authorization": f"Bearer {token}"},
            params={"page_size": page_size, "page_no": page}
        )

        if resp.status_code == 429:
            # No Retry-After header — use exponential backoff with jitter
            sleep_time = backoff + random.uniform(0, 1)
            time.sleep(sleep_time)
            backoff = min(backoff * 2, 120)  # Cap at 2 minutes
            continue

        if resp.status_code == 401:
            raise Exception("Token expired — refresh and retry")

        resp.raise_for_status()
        backoff = 1  # Reset backoff on success

        data = resp.json()
        batch = data.get("tickets", [])
        tickets.extend(batch)

        total = data.get("record_count", 0)
        if len(tickets) >= total or len(batch) < page_size:
            break

        page += 1
        time.sleep(0.5)  # ~2 req/s, under the 2.3 req/s sustained limit

    return tickets
```

### What Data Can You Access Through the HaloITSM API?

The API exposes the following resource types (not exhaustive — additional endpoints exist for specialist modules):

| Resource | Endpoint | Notes |
|---|---|---|
| Tickets (all ITIL types) | `/api/Tickets` | Incidents, SRs, changes, problems via `ticket_type` param |
| Actions | `/api/Actions` | Notes, status changes, emails, logged calls — separate from tickets |
| Users (contacts) | `/api/Users` | End users / contacts |
| Agents | `/api/Agent` | Staff/technician accounts |
| Assets / CIs | `/api/Asset` | Hardware, software CIs |
| Clients | `/api/Client` | Company/organization records |
| Sites | `/api/Site` | Locations nested under clients |
| Contracts | `/api/Contracts` | SLA/contract records |
| Invoices | `/api/Invoice` | Billing records |
| Knowledge Base Articles | `/api/KBArticle` | Self-service content |
| Attachments | `/api/Attachment` | Returns base64-encoded file content |
| Projects | `/api/Projects` | Project management module |
| Opportunities | `/api/Opportunities` | CRM/sales module |
| Quotes | `/api/Quotation` | Quote records |
| ITIL Change Requests | `/api/Changes` | Dedicated change management endpoint |
| Problems | `/api/Problems` | Problem management records |
| Suppliers | `/api/Supplier` | Vendor records |
| Purchase Orders | `/api/PurchaseOrder` | Procurement records |
| Releases | `/api/Release` | Release management |
| Teams | `/api/Team` | Agent group assignments |
| SLA Policies | `/api/SLA` | SLA definitions |
| Custom Field Definitions | `/api/CustomField` | Field schema metadata |

**Attachment response format:** Attachment content is returned as **base64-encoded binary** in the `data` field of the response. There is no documented per-file size limit for API downloads, but large attachments (10MB+) will significantly increase response times. For migrations involving large attachment libraries, batch download calls during off-peak hours.

**Webhook support:** HaloITSM supports outbound webhooks (configurable under **Configuration → Integrations → Webhooks**) for event-driven integration — ticket creation, status changes, and SLA breaches can trigger HTTP POST payloads to an external endpoint. For integration builds that need real-time updates rather than polling, webhooks eliminate the need for continuous API calls and sidestep rate limit concerns entirely.

**Self-hosted vs. cloud differences:** The REST API surface is identical between cloud-hosted and self-hosted deployments. Self-hosted instances additionally allow direct Microsoft SQL Server database access, which bypasses rate limits entirely. The SQL schema (Faults table, Asset, Contract tables) is the same across both deployment types.

## Key Ticket Response Fields

For migration planning, the critical fields in a `/api/Tickets` response:

| Field | Type | Description |
|---|---|---|
| `id` | integer | Unique ticket ID (maps to `Faults.Faultid`) |
| `summary` | string | Ticket subject line |
| `details` | string | Ticket description body |
| `status_id` | integer | Status code (1=New, 9=Closed — see status table above) |
| `tickettype_id` | integer | ITIL type (1=Incident, 2=Service Request, 3=Change, 4=Problem) |
| `client_id` | integer | Parent company ID |
| `site_id` | integer | Site ID (nullable) |
| `agent_id` | integer | Assigned agent ID |
| `dateoccurred` | datetime | Ticket creation timestamp (ISO 8601) |
| `customfields` | array | Custom field values as key-value pairs |
| `tags` | array | Tag labels applied to the ticket |

## Data Portability Gotchas Most People Miss

Exporting data is one thing. [Getting it into a usable shape for migration](https://clonepartner.com/blog/blog/help-desk-data-migration-playbook) is another. Here are the edge cases that cause the most problems in practice:

**Actions are separate from tickets.** Ticket actions — public notes, private notes, status changes, logged calls, email threads — are discrete events attached to a ticket, not embedded in the ticket object. Exporting tickets without separately exporting actions loses the entire conversation history. Plan for a separate `/api/Actions` call per ticket in your extraction pipeline.

**One company per contact.** HaloITSM enforces a single company per contact record. If you're migrating from a platform where contacts belong to multiple organizations, you'll need to handle that mapping explicitly — either through custom fields or by creating duplicate contact records per company relationship.

**Custom fields can't change type after creation.** Once a custom field type is set (text, integer, date, lookup, etc.), it's locked — it cannot be changed. When importing data into HaloITSM or exporting for re-import, pre-create all custom fields with the correct type before any data load. [Map source custom fields carefully](https://clonepartner.com/blog/blog/data-migration-mapping-cheat-sheet-sample-scripts) before starting.

**Sites live under Companies with parent-child relationships.** HaloITSM structures location data as Sites nested under Companies, and Sites can have hierarchical parent-child relationships with other Sites. This structure doesn't map cleanly to flat org models in other platforms and often requires manual mapping during migration.

**Attachments require separate API calls and return base64.** Ticket and action endpoints return attachment metadata (filename, size, ID) but not file content. Retrieving actual file content requires a separate `GET /api/Attachment/{id}` call per attachment, which returns the file as base64-encoded binary. For a migration involving thousands of attachments, this multiplies your API call count significantly and can exhaust the 700-request rate limit rapidly.

**Disable automations during import.** If you're using exported data to feed a migration into another system or back into a fresh HaloITSM instance, [disable approval processes and notification rules first](https://clonepartner.com/blog/blog/how-to-migrate-automations-macros-workflows). Imported tickets can trigger automation rules, causing email floods, SLA timers to start, or unwanted status changes.

**Token expiry during long-running exports.** OAuth tokens expire after 3600 seconds (1 hour). A bulk export of a large instance will cross this boundary. Build token refresh logic into your pipeline — detect 401 responses and re-authenticate using your client credentials before retrying.

## How to Choose the Right Export Method

**For a one-time audit or spot check:** Use the UI export. Thirty seconds, no code, CSV in Excel.

**For recurring scheduled reports:** Use the SQL reporting engine. Build the query once, schedule it, receive CSV via email. No code required.

**For a full data migration or integration build:** Use the REST API. It's the only method that exposes relational data (tickets + actions + attachments) with full automation capability.

**Decision criteria as an if/then structure:**

- If volume < ~5,000 records AND no relational data needed → **UI export**
- If volume is any size AND recurring delivery AND no external code → **SQL reporting engine**
- If volume > 5,000 records OR relational data required OR automated pipeline needed → **REST API**
- If self-hosted AND volume > 100,000 records OR rate limit is a bottleneck → **Direct SQL database access**
- If real-time integration (not batch) → **Webhooks** + REST API for historical backfill

## API Extraction at Scale: What to Expect

At 700 requests per 5 minutes, the rate limit is the binding constraint for large-scale exports. There is no published mechanism to request a higher limit for cloud-hosted tenants.

**Rough time estimates for full extraction (cloud-hosted):**

| Instance size | Tickets | Estimated API calls (with actions) | Estimated extraction time |
|---|---|---|---|
| Small | 10,000 | ~25,000 | ~3–4 hours |
| Medium | 50,000 | ~120,000 | ~14–18 hours |
| Large | 200,000+ | ~500,000+ | 3–4 days |

For self-hosted deployments, direct SQL access bypasses rate limits entirely. The published schema (Faults table, Asset, Contract tables) is sufficient to build a complete extraction. Use `fdeleted = 0` and `fmergedintofaultid = 0` filters at the database level to exclude soft-deleted and merged records from the start — the same filters that belong in any API-based extraction too.

## Making Your HaloITSM Data Work for You

[HaloITSM is more portable than many ITSM platforms](https://clonepartner.com/blog/blog/servicenow-vs-haloitsm-architecture-tco-and-migration). Between the UI exports, the SQL reporting engine, and a REST API covering 22+ resource types, you have real options for getting data out. The constraints — 700 requests per 5-minute rolling window with no `Retry-After` header, actions as separate entities requiring per-ticket API calls, 1-hour OAuth token expiry, one-company-per-contact, locked custom field types — are real but manageable if you know about them before you start.

Whether you're building a sync integration, running a compliance export, or planning a full platform migration, the right approach depends on your data volume, your timeline, and how much relational complexity you need to preserve.

> Planning a migration from HaloITSM? Book a 30-minute call and we'll map out an extraction plan based on your instance size and target platform.
>
> [Talk to us](https://cal.com/clonepartner/meet?duration=30)

## Frequently asked questions

### What is the HaloITSM API rate limit?

The HaloITSM API allows 700 requests per 300-second (5-minute) rolling window, per tenant. That's roughly 2.3 requests per second sustained. Exceeding this returns HTTP 429 responses.

### Can you export tickets with full history from HaloITSM?

Yes, but ticket actions (notes, status changes, calls) are separate API objects. You must export tickets and their associated actions separately, then join them by ticket ID. UI exports don't include action-level detail.

### How does HaloITSM API authentication work?

HaloITSM uses OAuth 2.0 client credentials. Create an API application under Configuration → Integrations → HaloITSM API, generate a Client ID and Secret, then use those to request a Bearer token for API calls.

### Can you export HaloITSM data to CSV?

Yes, through three methods: direct UI export from list views (Export → CSV), the SQL reporting engine which outputs to CSV/Excel/PDF, or by scripting against the REST API and converting JSON responses to CSV.

### What database does HaloITSM use?

HaloITSM uses Microsoft SQL Server. The reporting suite provides read-only SQL access with published schema documentation for the Faults (tickets) table and Asset/Contract tables.
