> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://api-docs.hindsiteind.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://api-docs.hindsiteind.com/_mcp/server.

# Post Work Order Tasks Id External Reviewers

POST https://app.hindsiteind.com/api/v2/work_order_tasks/{id}/external_reviewers
Content-Type: application/json

Emails a request to review a completed work order task to an external reviewer, either an existing external user by `user_id` or a new one registered from `name` and `email`; only admins, the parent work order's assigned managers and leads, and location managers who did not contribute to the task's form may call it, and only when external reviews are enabled for the organisation.

Reference: https://api-docs.hindsiteind.com/hindsite-api/reviews/post-work-order-tasks-id-external-reviewers

## Authentication

- `Authorization` header (bearer token, required) — OAuth 2.0 Client Credentials Flow. To obtain an access token: 1. Request API credentials from HINDSITE support to receive your `client_id` and `client_secret` 2. Make a POST request to obtain an access token: ``` POST https://app.hindsiteind.com/oauth/token Content-Type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET ``` 3. The response will contain your access token: ```json { "access_token": "your_access_token_here", "token_type": "Bearer", "expires_in": 7200, "created_at": 1234567890 } ``` 4. Include the token in subsequent API requests: ``` Authorization: Bearer your_access_token_here ```

## Request

### Path parameters

- `id` (string, required)

### Body (application/json)

This endpoint expects a postV2WorkOrderTasksIdExternalReviewers.

- `user_id` (string, optional) — ULID of an existing active external user in the organisation. When given, `name` and `email` are ignored.
- `name` (string, optional) — Name for a new external user; required when `user_id` is not given
- `email` (string, optional) — Email for a new external user; required when `user_id` is not given

## Response

### 201

The requested external reviewer

- `id` (string, optional) — ULID
- `user` (User, optional) — The reviewer, including `last_active_at` and `archived`
- `reviewable_id` (string, optional) — ULID of the work order or work order task under review
- `reviewable_type` (enum, optional)
  - Allowed values: `WorkOrder`, `WorkOrderTask`
- `status` (enum, optional) — `pending` while awaiting a response (including after a reminder), `approved` or `rejected` once they respond, `commented` for someone who only commented without being asked to review
  - Allowed values: `pending`, `approved`, `rejected`, `commented`
- `requested_at` (datetime, optional, nullable) — When the review request was last emailed (ISO 8601); null if no request was emailed, such as someone who reviewed without being asked
- `stale` (boolean, optional) — true when the reviewer's latest approval or rejection is older than the latest change to the work
- `external` (boolean, optional) — true for an external (non-member) reviewer
- `remindable` (boolean, optional) — true when the caller can send this reviewer a reminder: they are not the caller, their access is not revoked, and they can receive email
- `removable` (boolean, optional) — true while the reviewer has not reviewed, so can be removed
- `revocable` (boolean, optional) — true for an external reviewer who has reviewed and whose access is not yet revoked
- `revocation` (ReviewerRevocation, optional, nullable) — null unless the reviewer's access has been revoked
- `reviews` (list of Review, optional) — Oldest first
- `created_at` (long, optional) — Unix timestamp (seconds since epoch)
- `updated_at` (long, optional) — Unix timestamp (seconds since epoch)

## Errors

### 403 Forbidden Error

Caller is not an admin, an assigned manager or lead of the parent work order, or a location manager, or contributed to the task's form

- `error` (string, optional)

### 404 Not Found Error

Work order task not found, or the caller cannot access it, or `user_id` is not an active external user in the organisation

- `error` (string, optional)

### 422 Unprocessable Entity Error

The task is not completed, has no form, has active defects, or its work order is cancelled; external reviews are not enabled for the organisation; more internal approvals are needed first; `name` or `email` is missing or invalid, or `email` already belongs to a member or an external user; or the person is already a reviewer. The body carries an `error` message.

- `error` (string, optional)

## Types

### User

- `id` (string, optional) — ULID
- `email` (string, optional)
- `name` (string, optional)
- `is_admin` (boolean, optional)
- `location_manager` (boolean, optional)
- `last_active_at` (long, optional) — Unix timestamp (seconds since epoch)
- `archived` (boolean, optional)
- `organisation_id` (string, optional) — ULID
- `created_at` (long, optional) — Unix timestamp (seconds since epoch) when the record was created
- `updated_at` (long, optional) — Unix timestamp (seconds since epoch) when the record was last updated

### ReviewerRevocation

- `created_at` (datetime, optional) — When access was revoked (ISO 8601)
- `revoked_by` (User, optional, nullable) — The user who revoked access; null if that user no longer exists
- `updated_at` (long, optional) — Unix timestamp (seconds since epoch)

### Review

- `id` (string, optional) — ULID
- `status` (enum, optional)
  - Allowed values: `comment`, `approved`, `rejected`
- `comment` (string, optional, nullable) — null when the review was submitted without a comment
- `created_at` (datetime, optional) — ISO 8601
- `updated_at` (long, optional) — Unix timestamp (seconds since epoch)

## Examples

**Request**

```json
{}
```

**Response**

```json
{
  "id": "string",
  "user": {
    "id": "string",
    "email": "string",
    "name": "string",
    "is_admin": true,
    "location_manager": true,
    "last_active_at": 1,
    "archived": true,
    "organisation_id": "string",
    "created_at": 1,
    "updated_at": 1
  },
  "reviewable_id": "string",
  "reviewable_type": "WorkOrder",
  "status": "pending",
  "requested_at": "2024-01-15T09:30:00Z",
  "stale": true,
  "external": true,
  "remindable": true,
  "removable": true,
  "revocable": true,
  "revocation": {
    "created_at": "2024-01-15T09:30:00Z",
    "revoked_by": {
      "id": "string",
      "email": "string",
      "name": "string",
      "is_admin": true,
      "location_manager": true,
      "last_active_at": 1,
      "archived": true,
      "organisation_id": "string",
      "created_at": 1,
      "updated_at": 1
    },
    "updated_at": 1
  },
  "reviews": [
    {
      "id": "string",
      "status": "comment",
      "comment": "string",
      "created_at": "2024-01-15T09:30:00Z",
      "updated_at": 1
    }
  ],
  "created_at": 1,
  "updated_at": 1
}
```

**SDK Code**

```python
import requests

url = "https://app.hindsiteind.com/api/v2/work_order_tasks/id/external_reviewers"

payload = {}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://app.hindsiteind.com/api/v2/work_order_tasks/id/external_reviewers';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://app.hindsiteind.com/api/v2/work_order_tasks/id/external_reviewers"

	payload := strings.NewReader("{}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://app.hindsiteind.com/api/v2/work_order_tasks/id/external_reviewers")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://app.hindsiteind.com/api/v2/work_order_tasks/id/external_reviewers")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://app.hindsiteind.com/api/v2/work_order_tasks/id/external_reviewers', [
  'body' => '{}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://app.hindsiteind.com/api/v2/work_order_tasks/id/external_reviewers");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://app.hindsiteind.com/api/v2/work_order_tasks/id/external_reviewers")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```