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

# Quick Start

> Build your first Phrase TMS plugin flow in four practical steps.

This quick start gives you the minimum end-to-end plugin flow: authenticate, create project and jobs, monitor progress, and download translated output.

## At a glance

You will implement this sequence:

1. Authenticate
2. Create project and job
3. Monitor progress
4. Export and set `DELIVERED`

## Prerequisites

* Phrase account with TMS access.
* Phrase Platform API token.
* Platform base URL and TMS API base URL for your tenant/region.
* At least one TMS project template available in your org.
* A sample source file to upload.
* Basic REST API familiarity.

Set base URLs once and reuse them in examples:

```bash theme={null}
PLATFORM_BASE_URL="https://<your-region>.phrase.com"
TMS_BASE_URL="https://<your-tms-host>/web"
```

<Note>Do not hardcode EU endpoints unless your tenant is on EU infrastructure.</Note>

## Step 1: Authenticate

Exchange your API token for a short-lived access token and send it as `Authorization: Bearer <token>`.

```bash theme={null}
curl --request POST "${PLATFORM_BASE_URL}/idm/oauth/token" \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange' \
  --data-urlencode 'subject_token=YOUR_API_TOKEN'
```

Use this token exchange flow for all subsequent API calls. Refresh before expiry or on a single retry after `401`.

See [Platform authentication](/en/api/platform/authentication) and [OAuth token endpoint](/en/api/platform/oauth/token-endpoint).

## Step 2: Create a project and job

1. List project templates: `GET /api2/v1/projectTemplates`
2. Create project from template: `POST /api2/v2/projects/applyTemplate/{templateUid}`
3. Create job in project: `POST /api2/v1/projects/{projectUid}/jobs`

```bash theme={null}
curl --request POST "${TMS_BASE_URL}/api2/v2/projects/applyTemplate/${TEMPLATE_UID}" \
  --header "Authorization: Bearer ${ACCESS_TOKEN}" \
  --header 'Content-Type: application/json' \
  --data '{"name":"My Plugin Quick Start Project"}'
```

<Note>Persist `projectUid`, `job.uid`, and any returned `asyncRequest.id`. You need these IDs later.</Note>

Reference docs:

* [List project templates](/en/api/tms/latest/project-template/list-project-templates)
* [Create project from template](/en/api/tms/latest/project/create-project-from-template)
* [Create job](/en/api/tms/latest/job/create-job)

## Step 3: Monitor progress

Use one of these methods:

* Simple start: poll `GET /api2/v1/projects/{projectUid}/jobs/{jobUid}/parts`
* Async operation status: poll `GET /api2/v1/async/{asyncRequestId}` when relevant
* Production approach: webhook events with polling fallback

```bash theme={null}
curl --request GET "${TMS_BASE_URL}/api2/v1/projects/${PROJECT_UID}/jobs/${JOB_UID}/parts" \
  --header "Authorization: Bearer ${ACCESS_TOKEN}"
```

Treat terminal failure statuses (`CANCELLED`, `REJECTED`) as non-deliverable outcomes.

## Step 4: Export and mark delivered

1. Start async download: `PUT /api2/v3/projects/{projectUid}/jobs/{jobUid}/targetFile`
2. Wait until async request is complete.
3. Download target file: `GET /api2/v2/projects/{projectUid}/jobs/{jobUid}/downloadTargetFile/{asyncRequestId}`
4. Mark delivered: `POST /api2/v1/projects/{projectUid}/jobs/{jobUid}/setStatus` with `requestedStatus: DELIVERED`

```json theme={null}
{
  "requestedStatus": "DELIVERED",
  "notifyOwner": true,
  "propagateStatus": true
}
```

Reference docs:

* [Download target file async](/en/api/tms/latest/job/download-target-file-async-1)
* [Download target file by async request](/en/api/tms/latest/job/download-target-file-based-on-async-request)
* [Edit job status](/en/api/tms/latest/job/edit-job-status)

## Optional: implementation patterns (pseudocode)

Use these patterns when moving from sample calls to production code. You can skip this section for a first pass.

### Auth caching and one-time `401` retry

```text theme={null}
CACHE = { token: null, expiresAt: 0 }

function getAccessToken():
  if CACHE.token exists and now < CACHE.expiresAt - safetyWindow:
    return CACHE.token
  tokenResponse = POST ${PLATFORM_BASE_URL}/idm/oauth/token
  CACHE.token = tokenResponse.access_token
  CACHE.expiresAt = now + tokenResponse.expires_in
  return CACHE.token

function authRequest(method, url, body):
  token = getAccessToken()
  response = HTTP(method, url, header={"Authorization": "Bearer " + token}, body=body)
  if response.status == 401:
    CACHE.token = null
    token = getAccessToken()
    response = HTTP(method, url, header={"Authorization": "Bearer " + token}, body=body)
  return response
```

### Async polling with bounded backoff

```text theme={null}
function waitForAsync(asyncRequestId, timeout):
  delay = 2s
  until timeout:
    status = GET /api2/v1/async/{asyncRequestId}
    if status.asyncResponse exists:
      if status.asyncResponse.errorCode exists:
        fail(status.asyncResponse)
      return status.asyncResponse
    sleep(delay + jitter)
    delay = min(delay * 2, 60s)
```

### Export completion flow

```text theme={null}
start = PUT /api2/v3/projects/{projectUid}/jobs/{jobUid}/targetFile
waitForAsync(start.asyncRequest.id)
file = GET /api2/v2/projects/{projectUid}/jobs/{jobUid}/downloadTargetFile/{start.asyncRequest.id}
importToSourceSystem(file)
POST /api2/v1/projects/{projectUid}/jobs/{jobUid}/setStatus {"requestedStatus":"DELIVERED"}
```

## Next steps

<CardGroup cols={3}>
  <Card title="Full Integration Workflow" icon="list-checks" href="/en/guides/build-a-tms-plugin/full-integration-workflow">
    Add production-grade behaviors and resilience.
  </Card>

  <Card title="Live Preview" icon="monitor" href="/en/guides/build-a-tms-plugin/live-preview">
    Add contextual preview support for translators.
  </Card>

  <Card title="Error Handling & Limits" icon="shield-alert" href="/en/guides/build-a-tms-plugin/error-handling-and-limits">
    Harden retries, limits, and failure behavior.
  </Card>
</CardGroup>
