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

# 작업 생성 및 조회

> Starfort 배치 비식별화 작업 API. POST /v1/guard/s3로 작업 생성, GET으로 상태 폴링, 장시간 처리를 안정 운영하는 패턴을 설명합니다 (Starfort v1.4 문서)

배치 연동의 골격은 **작업 생성 → 주기 조회(폴링) → 산출물 수거** 세 단계입니다. 두 API 모두 [동일한 API Key](/ko/v1.4/api/authentication)로 인증합니다.

## 작업 생성 API

```
POST https://bastion-guardian-api.starfort.io/v1/guard/s3
```

**요청 헤더**

| 헤더                         | 필수 | 설명                 |
| -------------------------- | -- | ------------------ |
| `X-Starfort-Guard-Api-Key` | 예  | `sf_`로 시작하는 발급 키   |
| `Content-Type`             | 예  | `application/json` |

**요청 본문**

```json theme={"dark"}
{
  "src_s3_url": "s3://your-bucket/inbox/2026/contract-001.docx",
  "tgt_s3_url": "s3://your-bucket/deidentified/",
  "process_type": "INPUT",
  "options": { "on_pass": "copy_original" }
}
```

| 필드                | 필수  | 설명                                                                                                                                               |
| ----------------- | --- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `src_s3_url`      | 예   | 원본 파일 주소. `s3://<버킷>/<객체 키>` 형식으로 **하나의 파일**을 가리키며(1 작업 = 1 객체), [Storage Connection](/ko/v1.4/api/batch/storage-connection)의 읽기 허용 범위 안이어야 합니다. |
| `tgt_s3_url`      | 예   | 결과 저장 위치. `/`로 끝나면 **폴더**로 해석되어 원본 파일명 그대로 저장되고, 아니면 **그 이름의 파일**로 저장됩니다. 쓰기 허용 범위 안이어야 합니다.                                                     |
| `process_type`    | 예   | 어떤 정책 묶음으로 검사할지 정하는 처리 유형(예: `"INPUT"`)입니다. 해당 Guardian이 선언한 범위 내여야 하며, 대소문자를 구분하지 않습니다.                                                         |
| `options.on_pass` | 아니오 | PASS 판정 시 산출물 — `"copy_original"`(기본, 원본 사본 저장) / `"skip"`(저장 안 함).                                                                              |

<Note>
  배치 요청 본문은 **snake\_case**(`process_type`)를 사용합니다 — 인라인 [Guard API](/ko/v1.4/api/request-format)의 `processType`(camelCase)과 표기가 다릅니다.
</Note>

**응답 — `202 Accepted`**

```json theme={"dark"}
{ "job_id": "cmd8h2xk10003abcdxyz01234", "status": "PENDING" }
```

`job_id`를 보관해 조회에 사용합니다.

**검증 시점** — 접수 시점에는 인증 · Kill Switch · `process_type` · 허용 범위만 동기로 검증합니다(실패 시 작업이 만들어지지 않고 즉시 거부됩니다). 원본의 존재 · 크기 · 형식은 처리 시점에 검사되어, 문제가 있으면 작업이 `FAILED`로 확정됩니다. [배치 오류](/ko/v1.4/api/batch/errors)를 참고하세요.

**재시도와 중복** — 멱등 토큰은 없습니다. 동일 요청을 재전송하면 각각 별개의 작업이 생성됩니다. 응답 유실 시 중복 접수될 수 있으나, 같은 입력·정책의 산출물이 같은 이름으로 원자적으로 덮어써지므로 `tgt`의 최종 상태는 동일합니다. 접수된 작업의 `job_id`를 잃었다면 아래 원본 주소 검색으로 복구하세요.

## 작업 조회 API

```
GET https://bastion-guardian-api.starfort.io/v1/guard/s3/jobs/{job_id}
```

**응답 — `200`**

```json theme={"dark"}
{
  "job_id": "cmd8h2xk10003abcdxyz01234",
  "status": "COMPLETED",
  "action": "MASK",
  "src_s3_url": "s3://your-bucket/inbox/2026/contract-001.docx",
  "tgt_s3_url": "s3://your-bucket/deidentified/contract-001.docx",
  "results": [
    {
      "policy_name": "개인정보 정책", "policy_type": "PII", "action": "MASK",
      "detected_items": [
        { "rule_type": "regex", "rule_name": "resident_number:_all_gender_with_separators", "action": "MASK", "confidence": 1.0, "mask_word": "RESIDENT_NUMBER_1", "alert_message": "resident number detected" }
      ]
    }
  ],
  "error": null,
  "created_at": "2026-07-23T09:00:00.000Z",
  "completed_at": "2026-07-23T09:00:41.000Z"
}
```

| 필드                            | 설명                                                                                                                                         |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `status`                      | 작업 상태 4종 — `PENDING` / `PROCESSING` / `COMPLETED` / `FAILED`. [배치 개요](/ko/v1.4/api/batch/overview)를 참고하세요.                                 |
| `action`                      | `COMPLETED`일 때의 판정(`PASS` / `MASK` / `BLOCK`), 그 외에는 `null`. [Actions](/ko/v1.4/concepts/actions-pass-mask-block)를 참고하세요.                  |
| `tgt_s3_url`                  | **실제 저장된 결과 파일의 확정 주소**(폴더로 요청한 경우 파일명까지 포함). 저장된 파일이 없으면 `null`.                                                                          |
| `results`                     | 정책별 탐지 결과(걸린 정책 · 탐지 항목 · 마스킹 토큰 · 신뢰도) — [Guard API 응답](/ko/v1.4/api/response-format)의 결과 구조와 동일하며, **산출물 본문은 포함하지 않습니다**(본문은 버킷에만 있습니다). |
| `error`                       | `FAILED`일 때의 사유(`code` / `message` / `details`). [배치 오류](/ko/v1.4/api/batch/errors)를 참고하세요.                                                |
| `created_at` / `completed_at` | 접수 시각 / 확정 시각.                                                                                                                             |

* 조회는 해당 작업을 **생성한 프로젝트의 API Key로만** 가능합니다.
* [Kill Switch](/ko/v1.4/admin/kill-switch) 발동 중에는 작업 생성과 조회가 모두 거부됩니다.
* 작업 조회의 보존 기간은 운영 정책을 따르며, 지난 작업의 이력은 [Opticon](/ko/v1.4/admin/monitoring-opticon)에서 확인합니다 — 각 작업의 트레이스에 접수 정보(`src_s3_url` · `tgt_s3_url` · `process_type` · `job_id`)와 판정 · 오류가 함께 기록됩니다.

### 원본 주소로 작업 검색

`job_id`를 잃은 경우 원본 주소로 최근 작업을 검색해 복구합니다:

```
GET /v1/guard/s3/jobs?src_s3_url=s3://your-bucket/inbox/2026/contract-001.docx
```

해당 원본 객체로 접수된 **최근 작업 목록**을 최신순으로 반환합니다(기본 최대 20건, `results` 미포함 — 상세는 `job_id` 단건 조회로 확인하세요).

```json theme={"dark"}
{ "jobs": [ { "job_id": "cmd8h2xk10003abcdxyz01234", "status": "COMPLETED", "action": "MASK", "src_s3_url": "s3://your-bucket/inbox/2026/contract-001.docx", "tgt_s3_url": "s3://your-bucket/deidentified/contract-001.docx", "error": null, "created_at": "2026-07-23T09:00:00.000Z", "completed_at": "2026-07-23T09:00:41.000Z" } ] }
```

## 폴링 패턴

<Steps>
  <Step title="작업 생성">`POST /v1/guard/s3`를 호출하고 응답의 `job_id`를 보관합니다.</Step>
  <Step title="주기 조회">`GET /v1/guard/s3/jobs/{job_id}`를 주기적으로 호출합니다. `status`가 `PENDING` / `PROCESSING`이면 계속 대기합니다.</Step>
  <Step title="확정 상태 분기">`COMPLETED`이면 `action`으로 분기하고(`PASS` / `MASK`는 `tgt_s3_url`에서 산출물 수거, `BLOCK`은 산출물 없음 — 사유는 `results`), `FAILED`이면 `error.code`로 분기합니다.</Step>
</Steps>

```bash theme={"dark"}
curl -X POST https://bastion-guardian-api.starfort.io/v1/guard/s3 \
  -H "X-Starfort-Guard-Api-Key: sf_xxxx..." -H "Content-Type: application/json" \
  -d '{ "src_s3_url": "s3://your-bucket/inbox/customer-list.xlsx", "tgt_s3_url": "s3://your-bucket/deidentified/", "process_type": "INPUT" }'
# → 202 { "job_id": "cmd8h2xk1...", "status": "PENDING" }

curl https://bastion-guardian-api.starfort.io/v1/guard/s3/jobs/cmd8h2xk1... \
  -H "X-Starfort-Guard-Api-Key: sf_xxxx..."
# → 200 { "status": "COMPLETED", "action": "MASK", "tgt_s3_url": "s3://your-bucket/deidentified/customer-list.xlsx", ... }
```
