위임 관리자(부관리자)가 권한·역할·표현식·비밀 콘텐츠 경계를 우회하던 결함군을 계층 대칭성 원칙으로 전건 차단한다. 약한 경로가 정상 응답을 내보내는 것이 유일한 증상이라, 게이트를 생산 지점 한 곳(SSoT)에 두고 같은 데이터를 내보내는 소비 경로 전부가 그 게이트를 경유하도록 맞췄다. - 등급 상한(rank ceiling): 슈퍼관리자 보호·역할/사용자 역할 배정(추가·제거 대칭)·일괄 상태변경·순서변경을 상세 경로와 동일 강도로 재적용. 가드는 DB 쓰기에 선행하여 거부 시 상태 불변. - 레이아웃 표현식: new Function/with 실행을 AST 화이트리스트 평가기로 교체. 비-문자열 computed 키 정규화(normalizeKey)·Object facade(리플렉션 static 제거)·legacy 접근자 차단. 저장측 검증·정적 검사와 3계층 동형. - secret 게이트: 비밀글의 댓글·첨부·문의 독립 경로 재적용, hash 파일서빙 소유권·비밀·발행 상태 검사 통일. - 신뢰 스크립트 호스트: 확장 선언 기반 + same-origin 브라우저 정규화를 런타임·저장측·정적검사 3층 동형화. - 회귀 감지: 단위·Feature·E2E·시나리오 매니페스트 전축 + audit 룰 4종 신설.
56 KiB
Schedules API 레퍼런스
소유: 코어 · 생성:
php artisan api:docgen(실측 기반). @generated 블록은 재생성 시 갱신되며, 사람이 작성한 설명은 보존됩니다.
TL;DR (5초 요약)
1. 이 문서는 실제 API 호출로 실측한 Schedules 엔드포인트 레퍼런스입니다
2. 각 엔드포인트: 메서드/URI/권한 + 요청 파라미터 표 + 요청 예시(curl) + 실측 응답 필드 표 + 응답 예시(envelope)
3. 응답 필드의 예시값·응답 예시 JSON 은 실제 호출 응답에서 관측된 값입니다
4. 갱신: 코드 변경 후 php artisan api:docgen 재실행
5. 설명(TODO) 칸은 사람이 채웁니다
GET /api/admin/schedules
- 라우트명:
api.admin.schedules.index - 컨트롤러:
App\Http\Controllers\Api\Admin\ScheduleController@index - 인증/권한:
auth:sanctum+permission:core.schedules.read
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| page | query | integer | 아니오 | min 1 | 조회할 페이지 번호 (1부터 시작) |
| per_page | query | integer | 아니오 | min 1, max 100 | 페이지당 항목 수 |
| filters | query | array | 아니오 | max 10 | 추가 필터 조건 맵 (필드별 조건) |
| type | query | string | 아니오 | artisan, shell, url |
유형 필터 (해당 유형의 항목만 조회) |
| frequency | query | string | 아니오 | everyMinute, hourly, daily, weekly, monthly, custom |
실행 주기 |
| status | query | string | 아니오 | active, inactive |
상태 필터 (해당 상태의 항목만 조회) |
| last_result | query | string | 아니오 | success, failed, running, never |
마지막 실행 결과 필터: success(성공), failed(실패), running(실행중), never(미실행) 중 해당 결과인 스케줄만 조회 |
| without_overlapping | query | string | 아니오 | 0, 1 |
중복 실행 방지 여부 |
| run_in_maintenance | query | string | 아니오 | 0, 1 |
점검 모드 중 실행 여부 |
| extension_type | query | string | 아니오 | core, module, plugin |
확장 유형 (core/module/plugin/template) |
| extension_identifier | query | string | 아니오 | max 255 | 확장 식별자 |
| created_from | query | date | 아니오 | — | 생성일 범위의 시작일 (이 날짜 이후 생성된 스케줄만 조회) |
| created_to | query | date | 아니오 | — | 생성일 범위의 종료일 (이 날짜 이전 생성된 스케줄만 조회, created_from 이후여야 함) |
| sort_by | query | string | 아니오 | created_at, name, next_run_at, last_run_at, is_active, last_result |
정렬 기준 필드명 |
| sort_order | query | string | 아니오 | asc, desc |
정렬 방향 (asc 오름차순 / desc 내림차순) |
이 엔드포인트는 확장이 파라미터를 추가할 수 있습니다 (
core.schedule.list_validation_rules).
요청 예시
GET /api/admin/schedules?page=1&per_page=1&filters=%EC%98%88%EC%8B%9C%EA%B0%92&type=artisan&frequency=everyMinute&status=active&last_result=success&without_overlapping=0&run_in_maintenance=0&extension_type=core&extension_identifier=example-key&created_from=2026-01-01&created_to=2026-01-01&sort_by=created_at&sort_order=asc HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
목록 응답: data.data[] 배열 항목의 필드 + data.pagination.
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| id | integer | 1 |
기본 키 (내부 식별자) |
| name | string | API 문서 샘플 스케줄 |
작업명 |
| type | string | artisan |
작업 유형: artisan(Artisan 커맨드), shell(쉘 명령), url(URL 호출) |
| type_label | string | Artisan 커맨드 |
type 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| command | string | cache:clear |
명령어 또는 URL |
| expression | string | 0 3 * * * |
Cron 표현식 |
| frequency | string | daily |
실행 주기: everyMinute(매분), hourly(매시간), daily(매일), weekly(매주), monthly(매월), custom(사용자 정의) |
| frequency_label | string | 매일 |
frequency 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| without_overlapping | boolean | true |
중복 실행 방지 여부: 0(허용), 1(방지) |
| run_in_maintenance | boolean | false |
점검 모드 실행 여부: 0(비실행), 1(실행) |
| is_active | boolean | true |
active 여부 |
| last_result | string | success |
마지막 실행 결과: success(성공), failed(실패), running(실행중), never(미실행) |
| last_result_label | string | 성공 |
last_result 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| last_run_at | string | 2026-07-30T22:55:00+09:00 |
last run 일시 |
| last_duration | null | null |
마지막 실행의 소요 시간을 사람이 읽는 문자열로 포맷한 값 (예: "45초", "2분 3초" — 마지막 실행 이력의 duration 파생, 실행 이력이 없으면 null) |
| next_run_at | string | 2026-08-01T12:00:00+09:00 |
next run 일시 |
| creator | object | {"uuid":"a2640dae-e87c-4a28-b4f1-481fd961dc02","name":"AP… |
생성자 정보 객체 (uuid/name/email — creator 관계 파생) |
| created_at | string | 2026-07-31 |
생성 일시 |
| abilities | object | {"can_create":true,"can_update":true,"can_delete":true,"c… |
현재 사용자가 이 리소스에 수행 가능한 작업 불리언 맵 (can_update, can_delete 등 — 권한 맵 기반) |
응답 예시
HTTP/1.1 200
{
"success": true,
"message": "스케줄 목록을 조회했습니다.",
"data": {
"data": [
{
"id": 1,
"name": "API 문서 샘플 스케줄",
"type": "artisan",
"type_label": "Artisan 커맨드",
"command": "cache:clear",
"expression": "0 3 * * *",
"frequency": "daily",
"frequency_label": "매일",
"without_overlapping": true,
"run_in_maintenance": false,
"is_active": true,
"last_result": "success",
"last_result_label": "성공",
"last_run_at": "2026-07-30T22:55:00+09:00",
"last_duration": null,
"next_run_at": "2026-08-01T12:00:00+09:00",
"creator": {
"uuid": "a2640dae-e87c-4a28-b4f1-481fd961dc02",
"name": "API 문서 샘플 사용자"
},
"created_at": "2026-07-31",
"abilities": {
"can_create": true,
"can_update": true,
"can_delete": true,
"can_run": true
}
}
],
"statistics": {
"total": 1,
"active": 1,
"inactive": 0,
"success": 1,
"failed": 0,
"running": 0,
"never_run": 0
},
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 25,
"total": 1,
"from": 1,
"to": 1,
"has_more_pages": false
}
}
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(core.schedules.read)이 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
설명 예약 작업(스케줄) 목록을 페이지네이션과 함께 조회하며, 응답에는 상태별 통계도 포함됩니다. core.schedules.read 권한이 필요합니다. type/frequency/status/last_result/extension_type 등으로 필터링하고 sort_by/sort_order 로 정렬할 수 있습니다. 관리자 스케줄 관리 화면의 목록·필터·요약 카드 표시에 사용합니다.
POST /api/admin/schedules
- 라우트명:
api.admin.schedules.store - 컨트롤러:
App\Http\Controllers\Api\Admin\ScheduleController@store - 인증/권한:
auth:sanctum+permission:core.schedules.create
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| name | body | string | 예 | max 255 | 대상의 이름/명칭 |
| description | body | string | 아니오 | max 1000 | 설명 |
| type | body | string | 예 | artisan, shell, url |
작업 유형: artisan(Artisan 커맨드 실행), shell(쉘 명령 실행), url(URL 호출) |
| command | body | string | 예 | max 2000 | 실행할 명령 (type 에 따라 Artisan 커맨드 / 쉘 명령 / 호출할 URL). type=url 이면 내부 네트워크 주소(사설 IP·루프백·localhost·*.internal 등)는 거부되어 422 로 응답합니다 — 서버가 내부망으로 요청을 보내는 것을 막기 위함(SSRF). 사내 엔드포인트를 호출해야 하면 환경설정의 security.allow_internal_outbound_urls 를 켜세요. 이 설정을 켜도 userinfo(https://a@b/) 위장과 http/https 이외 scheme 은 계속 거부됩니다.type=shell 이면 기본적으로 모든 명령이 거부되어 422 로 응답합니다 — 스케줄 권한만 위임받은 계정이 서버에서 임의 OS 명령을 실행하는 것을 막기 위함입니다. 실행하려면 서버의 .env 에서 SCHEDULE_SHELL_ENABLED=true 로 게이트를 열고 SCHEDULE_SHELL_ALLOWED_BINARIES 에 허용할 실행 파일명을 등록해야 합니다(관리자 화면에서는 넓힐 수 없는 코드 소유 정책). 허용된 실행 파일이라도 셸 메타문자(` |
| expression | body | string | 예 | max 100 | 실행 시각을 정의하는 Cron 표현식 (예: 0 3 * * *, 다음 실행 시각 next_run_at 계산의 기준) |
| frequency | body | string | 예 | everyMinute, hourly, daily, weekly, monthly, custom |
실행 주기 |
| without_overlapping | body | boolean | 아니오 | — | 중복 실행 방지 여부 |
| run_in_maintenance | body | boolean | 아니오 | — | 점검 모드 중 실행 여부 |
| timeout | body | integer | 아니오 | min 1, max 86400 | 타임아웃 (초) |
| is_active | body | boolean | 아니오 | — | 활성 여부 (true 활성 / false 비활성) |
| extension_type | body | string | 아니오 | core, module, plugin |
확장 유형 (core/module/plugin/template) |
| extension_identifier | body | string | 아니오 | max 255 | 확장 식별자 |
이 엔드포인트는 확장이 파라미터를 추가할 수 있습니다 (
core.schedule.create_validation_rules).
요청 예시
POST /api/admin/schedules HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json
{
"name": "예시 이름",
"description": "예시 내용입니다.",
"type": "artisan",
"command": "예시값",
"expression": "예시값",
"frequency": "everyMinute",
"without_overlapping": true,
"run_in_maintenance": true,
"timeout": 1,
"is_active": true,
"extension_type": "core",
"extension_identifier": "example-key"
}
응답 필드 (data 내부)
단건 응답: data 객체의 필드.
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| id | integer | 12 |
기본 키 (내부 식별자) |
| name | string | 실측 예시값 |
대상의 이름/명칭 (다국어 필드는 로케일별 값 객체) |
| description | string | 실측 예시값 |
설명 (다국어 필드는 로케일별 값 객체) |
| type | string | artisan |
작업 유형: artisan(Artisan 커맨드), shell(쉘 명령), url(URL 호출) |
| type_label | string | Artisan 커맨드 |
type 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| command | string | 실측 예시값 |
명령어 또는 URL |
| expression | string | 실측 예시값 |
Cron 표현식 |
| frequency | string | everyMinute |
실행 주기: everyMinute(매분), hourly(매시간), daily(매일), weekly(매주), monthly(매월), custom(사용자 정의) |
| frequency_label | string | 매분 |
frequency 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| without_overlapping | boolean | true |
중복 실행 방지 여부: 0(허용), 1(방지) |
| run_in_maintenance | boolean | true |
점검 모드 실행 여부: 0(비실행), 1(실행) |
| timeout | integer | 1 |
실행 제한 시간 (초) |
| is_active | boolean | true |
active 여부 |
| last_result | string | never |
마지막 실행 결과: success(성공), failed(실패), running(실행중), never(미실행) |
| last_result_label | string | 미실행 |
last_result 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| last_duration | null | null |
마지막 실행 소요 시간 (초/밀리초 — 실행 이력 파생) |
| extension_type | string | core |
이 리소스를 소유한 확장의 타입 (core/module/plugin/template) |
| extension_identifier | string | probe_6a71e0dc9a253 |
이 리소스를 소유한 확장의 식별자 |
| creator | object | {"uuid":"a26219fc-94a0-4f63-9404-04c2a6ac99e4","name":"최고… |
생성자 정보 객체 (uuid/name/email — creator 관계 파생) |
| created_at | string | 2026-08-04 21:53:48 |
생성 일시 |
| updated_at | string | 2026-08-04 21:53:48 |
최종 수정 일시 |
| abilities | object | {"can_create":true,"can_update":true,"can_delete":true,"c… |
현재 사용자가 이 리소스에 수행 가능한 작업 불리언 맵 (can_update, can_delete 등 — 권한 맵 기반) |
응답 예시
HTTP/1.1 201
{
"success": true,
"message": "스케줄이 생성되었습니다.",
"data": {
"id": 12,
"name": "실측 예시값",
"description": "실측 예시값",
"type": "artisan",
"type_label": "Artisan 커맨드",
"command": "실측 예시값",
"expression": "실측 예시값",
"frequency": "everyMinute",
"frequency_label": "매분",
"without_overlapping": true,
"run_in_maintenance": true,
"timeout": 1,
"is_active": true,
"last_result": "never",
"last_result_label": "미실행",
"last_duration": null,
"extension_type": "core",
"extension_identifier": "probe_6a71e0dc9a253",
"creator": {
"uuid": "a26219fc-94a0-4f63-9404-04c2a6ac99e4",
"name": "최고관리자"
},
"created_at": "2026-08-04 21:53:48",
"updated_at": "2026-08-04 21:53:48",
"abilities": {
"can_create": true,
"can_update": true,
"can_delete": true,
"can_run": true
}
}
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(core.schedules.create)이 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
설명 새 예약 작업을 생성합니다. core.schedules.create 권한이 필요합니다. type(artisan/shell/url), command, expression, frequency 를 지정하며 생성자(creator)는 현재 사용자로 자동 기록됩니다. 검증 실패 시 422로 응답하고, 성공 시 201과 생성된 스케줄 리소스를 반환합니다. 관리자 스케줄 등록 폼에 사용합니다.
DELETE /api/admin/schedules/bulk
- 라우트명:
api.admin.schedules.bulk-delete - 컨트롤러:
App\Http\Controllers\Api\Admin\ScheduleController@bulkDelete - 인증/권한:
auth:sanctum+permission:core.schedules.delete
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| ids | query | array | 예 | min 1 | 대상 리소스 식별자 배열 (대량 작업 대상) |
이 엔드포인트는 확장이 파라미터를 추가할 수 있습니다 (
core.schedule.bulk_delete_validation_rules).
요청 예시
DELETE /api/admin/schedules/bulk?ids=%EC%98%88%EC%8B%9C%EA%B0%92 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
단건 응답: data 객체의 필드.
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| deleted_count | integer | 3 |
실제로 삭제된 스케줄 건수 (ScheduleService::bulkDelete 반환값) |
응답 예시
HTTP/1.1 200
{
"success": true,
"message": "선택한 스케줄이 삭제되었습니다.",
"data": {
"deleted_count": 3
}
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(core.schedules.delete)이 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
설명 전달된 ids 배열의 스케줄을 일괄 삭제합니다. core.schedules.delete 권한이 필요합니다. 삭제 처리 결과 요약을 반환하며, 검증 실패 시 422로 응답합니다. 목록에서 여러 스케줄을 선택해 한 번에 제거하는 동작에 사용합니다.
PATCH /api/admin/schedules/bulk-status
- 라우트명:
api.admin.schedules.bulk-status - 컨트롤러:
App\Http\Controllers\Api\Admin\ScheduleController@bulkUpdateStatus - 인증/권한:
auth:sanctum+permission:core.schedules.update
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| ids | body | array | 예 | min 1 | 대상 리소스 식별자 배열 (대량 작업 대상) |
| is_active | body | boolean | 예 | — | 활성 여부 (true 활성 / false 비활성) |
이 엔드포인트는 확장이 파라미터를 추가할 수 있습니다 (
core.schedule.bulk_update_status_validation_rules).
요청 예시
PATCH /api/admin/schedules/bulk-status HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json
{
"ids": [
"예시값"
],
"is_active": true
}
응답 필드 (data 내부)
단건 응답: data 객체의 필드.
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| updated_count | integer | 3 |
상태가 실제로 변경된 스케줄 건수 (ScheduleService::bulkUpdateStatus 반환값) |
응답 예시
HTTP/1.1 200
{
"success": true,
"message": "선택한 스케줄의 상태가 변경되었습니다.",
"data": {
"updated_count": 3
}
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(core.schedules.update)이 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
설명 전달된 ids 배열의 스케줄 활성 상태(is_active)를 일괄 변경합니다. core.schedules.update 권한이 필요합니다. 처리 결과 요약을 반환하며, 검증 실패 시 422로 응답합니다. 목록에서 여러 스케줄을 선택해 한 번에 활성화/비활성화하는 동작에 사용합니다.
DELETE /api/admin/schedules/history/{historyId}
- 라우트명:
api.admin.schedules.delete-history - 컨트롤러:
App\Http\Controllers\Api\Admin\ScheduleController@deleteHistory - 인증/권한:
auth:sanctum+permission:core.schedules.delete
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| historyId | path | string | 예 | — | 대상 history의 식별자 |
요청 예시
DELETE /api/admin/schedules/history/{historyId} HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
이 엔드포인트는 data 를 반환하지 않습니다 (성공 메시지만 — 컨트롤러가 success('schedule.history_delete_success') 를 데이터 없이 호출).
응답 예시
HTTP/1.1 200
{
"success": true,
"message": "실행 이력이 삭제되었습니다.",
"data": null
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(core.schedules.delete)이 없는 경우 |
| 404 | Not Found | 지정한 historyId 의 실행 이력이 존재하지 않는 경우 (schedule.history_not_found) |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
설명 특정 실행 이력 레코드를 삭제합니다. core.schedules.delete 권한이 필요합니다. 대상 이력이 없으면 404로 응답합니다. 스케줄 상세의 실행 이력 목록에서 개별 이력을 제거할 때 사용합니다.
GET /api/admin/schedules/statistics
- 라우트명:
api.admin.schedules.statistics - 컨트롤러:
App\Http\Controllers\Api\Admin\ScheduleController@statistics - 인증/권한:
auth:sanctum+permission:core.schedules.read
요청 파라미터
요청 파라미터 없음.
요청 예시
GET /api/admin/schedules/statistics HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
단건 응답: data 객체의 필드.
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| total | integer | 1 |
전체 개수 (집계) |
| active | integer | 1 |
활성(is_active=true) 스케줄 수 |
| inactive | integer | 0 |
비활성(is_active=false) 스케줄 수 |
| success | integer | 1 |
마지막 실행 결과가 성공(success)인 스케줄 수 |
| failed | integer | 0 |
마지막 실행 결과가 실패(failed)인 스케줄 수 |
| running | integer | 0 |
마지막 실행 결과가 실행중(running)인 스케줄 수 |
| never_run | integer | 0 |
아직 한 번도 실행되지 않은(last_result=never) 스케줄 수 |
응답 예시
HTTP/1.1 200
{
"success": true,
"message": "스케줄 통계를 조회했습니다.",
"data": {
"total": 1,
"active": 1,
"inactive": 0,
"success": 1,
"failed": 0,
"running": 0,
"never_run": 0
}
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(core.schedules.read)이 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
설명 스케줄 전체의 집계 통계를 조회합니다. core.schedules.read 권한이 필요합니다. 전체/활성/비활성 수와 마지막 실행 결과별(성공/실패/실행중/미실행) 건수를 반환합니다. 관리자 스케줄 대시보드의 요약 카드 표시에 사용합니다.
DELETE /api/admin/schedules/{schedule}
- 라우트명:
api.admin.schedules.destroy - 컨트롤러:
App\Http\Controllers\Api\Admin\ScheduleController@destroy - 인증/권한:
auth:sanctum+permission:core.schedules.delete
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| schedule | path | string | 예 | — | 대상 schedule의 식별자 |
요청 예시
DELETE /api/admin/schedules/{schedule} HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
이 엔드포인트는 data 를 반환하지 않습니다 (성공 메시지만 — 컨트롤러가 success('schedule.delete_success') 를 데이터 없이 호출).
응답 예시
HTTP/1.1 200
{
"success": true,
"message": "스케줄이 삭제되었습니다.",
"data": null
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(core.schedules.delete)이 없는 경우 |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
설명 단일 스케줄을 삭제합니다. core.schedules.delete 권한이 필요합니다. 경로의 schedule 은 라우트 모델 바인딩으로 해석되어 존재하지 않으면 404가 됩니다. 관리자 스케줄 관리 화면의 개별 삭제 동작에 사용합니다.
GET /api/admin/schedules/{schedule}
- 라우트명:
api.admin.schedules.show - 컨트롤러:
App\Http\Controllers\Api\Admin\ScheduleController@show - 인증/권한:
auth:sanctum+permission:core.schedules.read
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| schedule | path | string | 예 | — | 대상 schedule의 식별자 |
요청 예시
GET /api/admin/schedules/{schedule} HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
단건 응답: data 객체의 필드.
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| id | integer | 1 |
기본 키 (내부 식별자) |
| name | string | API 문서 샘플 스케줄 |
작업명 |
| description | string | 문서 실측용 스케줄 |
설명 |
| type | string | artisan |
작업 유형: artisan(Artisan 커맨드), shell(쉘 명령), url(URL 호출) |
| type_label | string | Artisan 커맨드 |
type 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| command | string | cache:clear |
명령어 또는 URL |
| expression | string | 0 3 * * * |
Cron 표현식 |
| frequency | string | daily |
실행 주기: everyMinute(매분), hourly(매시간), daily(매일), weekly(매주), monthly(매월), custom(사용자 정의) |
| frequency_label | string | 매일 |
frequency 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| without_overlapping | boolean | true |
중복 실행 방지 여부: 0(허용), 1(방지) |
| run_in_maintenance | boolean | false |
점검 모드 실행 여부: 0(비실행), 1(실행) |
| timeout | integer | 300 |
실행 제한 시간 (초) |
| is_active | boolean | true |
active 여부 |
| last_result | string | success |
마지막 실행 결과: success(성공), failed(실패), running(실행중), never(미실행) |
| last_result_label | string | 성공 |
last_result 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| last_run_at | string | 2026-07-30T22:55:00+09:00 |
last run 일시 |
| last_duration | null | null |
마지막 실행의 소요 시간을 사람이 읽는 문자열로 포맷한 값 (예: "45초", "2분 3초" — 마지막 실행 이력의 duration 파생, 실행 이력이 없으면 null) |
| next_run_at | string | 2026-08-01T12:00:00+09:00 |
next run 일시 |
| extension_type | null | null |
확장 소유 타입: core(코어), module(모듈), plugin(플러그인), NULL(사용자 정의) |
| extension_identifier | null | null |
확장 식별자 (예: core, sirsoft-board, sirsoft-payment) |
| creator | object | {"uuid":"a2640dae-e87c-4a28-b4f1-481fd961dc02","name":"AP… |
생성자 정보 객체 (uuid/name/email — creator 관계 파생) |
| created_at | string | 2026-07-31 22:55:00 |
생성 일시 |
| updated_at | string | 2026-07-31 22:55:00 |
최종 수정 일시 |
| abilities | object | {"can_create":true,"can_update":true,"can_delete":true,"c… |
현재 사용자가 이 리소스에 수행 가능한 작업 불리언 맵 (can_update, can_delete 등 — 권한 맵 기반) |
응답 예시
HTTP/1.1 200
{
"success": true,
"message": "스케줄 목록을 조회했습니다.",
"data": {
"id": 1,
"name": "API 문서 샘플 스케줄",
"description": "문서 실측용 스케줄",
"type": "artisan",
"type_label": "Artisan 커맨드",
"command": "cache:clear",
"expression": "0 3 * * *",
"frequency": "daily",
"frequency_label": "매일",
"without_overlapping": true,
"run_in_maintenance": false,
"timeout": 300,
"is_active": true,
"last_result": "success",
"last_result_label": "성공",
"last_run_at": "2026-07-30T22:55:00+09:00",
"last_duration": null,
"next_run_at": "2026-08-01T12:00:00+09:00",
"extension_type": null,
"extension_identifier": null,
"creator": {
"uuid": "a2640dae-e87c-4a28-b4f1-481fd961dc02",
"name": "API 문서 샘플 사용자"
},
"created_at": "2026-07-31 22:55:00",
"updated_at": "2026-07-31 22:55:00",
"abilities": {
"can_create": true,
"can_update": true,
"can_delete": true,
"can_run": true
}
}
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(core.schedules.read)이 없는 경우 |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
설명 단일 스케줄의 상세 정보를 조회하며 생성자(creator) 정보를 함께 로드합니다. core.schedules.read 권한이 필요합니다. 경로의 schedule 은 라우트 모델 바인딩으로 해석되어 없으면 404가 됩니다. 관리자 스케줄 상세/수정 화면의 초기 데이터 로딩에 사용합니다.
PUT /api/admin/schedules/{schedule}
- 라우트명:
api.admin.schedules.update - 컨트롤러:
App\Http\Controllers\Api\Admin\ScheduleController@update - 인증/권한:
auth:sanctum+permission:core.schedules.update
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| schedule | path | string | 예 | — | 대상 schedule의 식별자 |
| name | body | string | 예 | max 255 | 대상의 이름/명칭 |
| description | body | string | 아니오 | max 1000 | 설명 |
| type | body | string | 예 | artisan, shell, url |
작업 유형: artisan(Artisan 커맨드 실행), shell(쉘 명령 실행), url(URL 호출) |
| command | body | string | 예 | max 2000 | 실행할 명령 (type 에 따라 Artisan 커맨드 / 쉘 명령 / 호출할 URL). type=url 이면 내부 네트워크 주소(사설 IP·루프백·localhost·*.internal 등)는 거부되어 422 로 응답합니다 — 서버가 내부망으로 요청을 보내는 것을 막기 위함(SSRF). 사내 엔드포인트를 호출해야 하면 환경설정의 security.allow_internal_outbound_urls 를 켜세요. 이 설정을 켜도 userinfo(https://a@b/) 위장과 http/https 이외 scheme 은 계속 거부됩니다.type=shell 이면 기본적으로 모든 명령이 거부되어 422 로 응답합니다 — 스케줄 권한만 위임받은 계정이 서버에서 임의 OS 명령을 실행하는 것을 막기 위함입니다. 실행하려면 서버의 .env 에서 SCHEDULE_SHELL_ENABLED=true 로 게이트를 열고 SCHEDULE_SHELL_ALLOWED_BINARIES 에 허용할 실행 파일명을 등록해야 합니다(관리자 화면에서는 넓힐 수 없는 코드 소유 정책). 허용된 실행 파일이라도 셸 메타문자(` |
| expression | body | string | 예 | max 100 | 실행 시각을 정의하는 Cron 표현식 (예: 0 3 * * *, 다음 실행 시각 next_run_at 계산의 기준) |
| frequency | body | string | 예 | everyMinute, hourly, daily, weekly, monthly, custom |
실행 주기 |
| without_overlapping | body | boolean | 아니오 | — | 중복 실행 방지 여부 |
| run_in_maintenance | body | boolean | 아니오 | — | 점검 모드 중 실행 여부 |
| timeout | body | integer | 아니오 | min 1, max 86400 | 타임아웃 (초) |
| is_active | body | boolean | 아니오 | — | 활성 여부 (true 활성 / false 비활성) |
| extension_type | body | string | 아니오 | core, module, plugin |
확장 유형 (core/module/plugin/template) |
| extension_identifier | body | string | 아니오 | max 255 | 확장 식별자 |
이 엔드포인트는 확장이 파라미터를 추가할 수 있습니다 (
core.schedule.update_validation_rules).
요청 예시
PUT /api/admin/schedules/{schedule} HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json
{
"name": "예시 이름",
"description": "예시 내용입니다.",
"type": "artisan",
"command": "예시값",
"expression": "예시값",
"frequency": "everyMinute",
"without_overlapping": true,
"run_in_maintenance": true,
"timeout": 1,
"is_active": true,
"extension_type": "core",
"extension_identifier": "example-key"
}
응답 필드 (data 내부)
단건 응답: data 객체의 필드.
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| id | integer | 1 |
기본 키 (내부 식별자) |
| name | string | 실측 예시값 |
대상의 이름/명칭 (다국어 필드는 로케일별 값 객체) |
| description | string | 실측 예시값 |
설명 (다국어 필드는 로케일별 값 객체) |
| type | string | artisan |
작업 유형: artisan(Artisan 커맨드), shell(쉘 명령), url(URL 호출) |
| type_label | string | Artisan 커맨드 |
type 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| command | string | 실측 예시값 |
명령어 또는 URL |
| expression | string | 실측 예시값 |
Cron 표현식 |
| frequency | string | everyMinute |
실행 주기: everyMinute(매분), hourly(매시간), daily(매일), weekly(매주), monthly(매월), custom(사용자 정의) |
| frequency_label | string | 매분 |
frequency 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| without_overlapping | boolean | true |
중복 실행 방지 여부: 0(허용), 1(방지) |
| run_in_maintenance | boolean | true |
점검 모드 실행 여부: 0(비실행), 1(실행) |
| timeout | integer | 1 |
실행 제한 시간 (초) |
| is_active | boolean | true |
active 여부 |
| last_result | string | success |
마지막 실행 결과: success(성공), failed(실패), running(실행중), never(미실행) |
| last_result_label | string | 성공 |
last_result 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| last_run_at | string | 2026-07-30T22:55:00+09:00 |
last run 일시 |
| last_duration | null | null |
마지막 실행 소요 시간 (초/밀리초 — 실행 이력 파생) |
| extension_type | string | core |
이 리소스를 소유한 확장의 타입 (core/module/plugin/template) |
| extension_identifier | string | probe_6a71e0dceb9a2 |
이 리소스를 소유한 확장의 식별자 |
| creator | object | {"uuid":"a2640dae-e87c-4a28-b4f1-481fd961dc02","name":"AP… |
생성자 정보 객체 (uuid/name/email — creator 관계 파생) |
| created_at | string | 2026-07-31 22:55:00 |
생성 일시 |
| updated_at | string | 2026-08-04 21:53:48 |
최종 수정 일시 |
| abilities | object | {"can_create":true,"can_update":true,"can_delete":true,"c… |
현재 사용자가 이 리소스에 수행 가능한 작업 불리언 맵 (can_update, can_delete 등 — 권한 맵 기반) |
응답 예시
HTTP/1.1 200
{
"success": true,
"message": "스케줄이 수정되었습니다.",
"data": {
"id": 1,
"name": "실측 예시값",
"description": "실측 예시값",
"type": "artisan",
"type_label": "Artisan 커맨드",
"command": "실측 예시값",
"expression": "실측 예시값",
"frequency": "everyMinute",
"frequency_label": "매분",
"without_overlapping": true,
"run_in_maintenance": true,
"timeout": 1,
"is_active": true,
"last_result": "success",
"last_result_label": "성공",
"last_run_at": "2026-07-30T22:55:00+09:00",
"last_duration": null,
"extension_type": "core",
"extension_identifier": "probe_6a71e0dceb9a2",
"creator": {
"uuid": "a2640dae-e87c-4a28-b4f1-481fd961dc02",
"name": "API 문서 샘플 사용자"
},
"created_at": "2026-07-31 22:55:00",
"updated_at": "2026-08-04 21:53:48",
"abilities": {
"can_create": true,
"can_update": true,
"can_delete": true,
"can_run": true
}
}
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(core.schedules.update)이 없는 경우 |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
설명 기존 스케줄 정보를 수정합니다. core.schedules.update 권한이 필요합니다. store 와 동일한 필드(type/command/expression/frequency 등)를 받으며 검증 실패 시 422로 응답합니다. 경로의 schedule 은 라우트 모델 바인딩으로 해석되며, 수정된 스케줄 리소스를 반환합니다. 관리자 스케줄 수정 폼에 사용합니다.
POST /api/admin/schedules/{schedule}/duplicate
- 라우트명:
api.admin.schedules.duplicate - 컨트롤러:
App\Http\Controllers\Api\Admin\ScheduleController@duplicate - 인증/권한:
auth:sanctum+permission:core.schedules.create
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| schedule | path | string | 예 | — | 대상 schedule의 식별자 |
요청 예시
POST /api/admin/schedules/{schedule}/duplicate HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
단건 응답: data 객체의 필드.
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| id | integer | 13 |
기본 키 (내부 식별자) |
| name | string | API 문서 샘플 스케줄 (복사본) |
대상의 이름/명칭 (다국어 필드는 로케일별 값 객체) |
| description | string | 문서 실측용 스케줄 |
설명 (다국어 필드는 로케일별 값 객체) |
| type | string | artisan |
작업 유형: artisan(Artisan 커맨드), shell(쉘 명령), url(URL 호출) |
| type_label | string | Artisan 커맨드 |
type 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| command | string | cache:clear |
명령어 또는 URL |
| expression | string | 0 3 * * * |
Cron 표현식 |
| frequency | string | daily |
실행 주기: everyMinute(매분), hourly(매시간), daily(매일), weekly(매주), monthly(매월), custom(사용자 정의) |
| frequency_label | string | 매일 |
frequency 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| without_overlapping | boolean | true |
중복 실행 방지 여부: 0(허용), 1(방지) |
| run_in_maintenance | boolean | false |
점검 모드 실행 여부: 0(비실행), 1(실행) |
| timeout | integer | 300 |
실행 제한 시간 (초) |
| is_active | boolean | false |
active 여부 |
| last_result | string | never |
마지막 실행 결과: success(성공), failed(실패), running(실행중), never(미실행) |
| last_result_label | string | 미실행 |
last_result 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| last_duration | null | null |
마지막 실행 소요 시간 (초/밀리초 — 실행 이력 파생) |
| extension_type | null | null |
이 리소스를 소유한 확장의 타입 (core/module/plugin/template) |
| extension_identifier | null | null |
이 리소스를 소유한 확장의 식별자 |
| created_at | string | 2026-08-04 21:53:48 |
생성 일시 |
| updated_at | string | 2026-08-04 21:53:48 |
최종 수정 일시 |
| abilities | object | {"can_create":true,"can_update":true,"can_delete":true,"c… |
현재 사용자가 이 리소스에 수행 가능한 작업 불리언 맵 (can_update, can_delete 등 — 권한 맵 기반) |
응답 예시
HTTP/1.1 201
{
"success": true,
"message": "스케줄이 복제되었습니다.",
"data": {
"id": 13,
"name": "API 문서 샘플 스케줄 (복사본)",
"description": "문서 실측용 스케줄",
"type": "artisan",
"type_label": "Artisan 커맨드",
"command": "cache:clear",
"expression": "0 3 * * *",
"frequency": "daily",
"frequency_label": "매일",
"without_overlapping": true,
"run_in_maintenance": false,
"timeout": 300,
"is_active": false,
"last_result": "never",
"last_result_label": "미실행",
"last_duration": null,
"extension_type": null,
"extension_identifier": null,
"created_at": "2026-08-04 21:53:48",
"updated_at": "2026-08-04 21:53:48",
"abilities": {
"can_create": true,
"can_update": true,
"can_delete": true,
"can_run": true
}
}
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(core.schedules.create)이 없는 경우 |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
설명 기존 스케줄을 복제해 새 스케줄을 만듭니다. core.schedules.create 권한이 필요합니다. 원본을 바탕으로 새 레코드를 생성하며, 성공 시 201과 복제된 스케줄 리소스를 반환합니다. 유사한 설정의 스케줄을 빠르게 추가하는 "복제" 동작에 사용합니다.
GET /api/admin/schedules/{schedule}/history
- 라우트명:
api.admin.schedules.history - 컨트롤러:
App\Http\Controllers\Api\Admin\ScheduleController@history - 인증/권한:
auth:sanctum+permission:core.schedules.read
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| schedule | path | string | 예 | — | 대상 schedule의 식별자 |
| page | query | integer | 아니오 | min 1 | 조회할 페이지 번호 (1부터 시작) |
| per_page | query | integer | 아니오 | min 1, max 100 | 페이지당 항목 수 |
| status | query | string | 아니오 | success, failed, running |
상태 필터 (해당 상태의 항목만 조회) |
| trigger_type | query | string | 아니오 | scheduled, manual |
실행 방식 필터: scheduled(예약 시각 자동 실행), manual(관리자의 즉시 실행) 중 해당 이력만 조회 |
| started_from | query | date | 아니오 | — | 실행 시작일 범위의 시작일 (이 날짜 이후 시작된 이력만 조회) |
| started_to | query | date | 아니오 | — | 실행 시작일 범위의 종료일 (이 날짜 이전 시작된 이력만 조회, started_from 이후여야 함) |
| sort_by | query | string | 아니오 | started_at, ended_at, duration, status |
정렬 기준 필드명 |
| sort_order | query | string | 아니오 | asc, desc |
정렬 방향 (asc 오름차순 / desc 내림차순) |
이 엔드포인트는 확장이 파라미터를 추가할 수 있습니다 (
core.schedule.history_list_validation_rules).
요청 예시
GET /api/admin/schedules/{schedule}/history?page=1&per_page=1&status=success&trigger_type=scheduled&started_from=2026-01-01&started_to=2026-01-01&sort_by=started_at&sort_order=asc HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
목록 응답: data.data[] 배열 항목의 필드 + data.pagination.
목록 항목은 ScheduleHistoryResource::toListArray() 산물입니다 (단건 실행 응답과 달리 output/error_output/memory_usage(raw)/created_at/updated_at 은 포함되지 않습니다).
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| id | integer | 7 |
실행 이력의 기본 키 (내부 식별자) |
| schedule_id | integer | 1 |
이 이력이 속한 스케줄의 식별자 |
| started_at | string|null | 2026-07-08T12:14:49+09:00 |
실행 시작 일시 (사용자 타임존 포맷) |
| ended_at | string|null | 2026-07-08T12:14:49+09:00 |
실행 종료 일시 (사용자 타임존 포맷, 실행 중이면 null) |
| duration | integer|null | 0 |
실행 소요 시간 |
| duration_formatted | string|null | 45초 |
duration 값의 표시용 포맷 문자열 (모델 접근자 파생, 없으면 null) |
| status | string | success |
실행 결과 상태: success(성공), failed(실패), running(실행중) |
| status_label | string|null | 성공 |
status 값의 사람이 읽는 라벨 (schedule.result.* 현지화) |
| exit_code | integer|null | 0 |
실행 종료 코드 (0=성공, 그 외=실패) |
| memory_usage_formatted | string|null | 417.34 KB |
실행 중 메모리 사용량의 표시용 포맷 문자열 |
| trigger_type | string | manual |
실행 방식: scheduled(예약 자동 실행), manual(수동 즉시 실행) |
| trigger_type_label | string|null | 수동 실행 |
trigger_type 값의 사람이 읽는 라벨 (schedule.trigger_type.* 현지화) |
| triggered_by | object|null | {"uuid":"a234c2b1-cde8-437f-b28b-23323be2b98d","name":"관리자"} |
수동 실행을 트리거한 사용자 정보 (uuid/name — triggeredBy 관계가 로드되지 않았거나 자동 실행이면 null) |
data.pagination 은 current_page/last_page/per_page/total/from/to/has_more_pages 로 구성됩니다.
응답 예시
HTTP/1.1 200
{
"success": true,
"message": "실행 이력을 조회했습니다.",
"data": {
"data": [
{
"id": 7,
"schedule_id": 1,
"started_at": "2026-07-08T12:14:49+09:00",
"ended_at": "2026-07-08T12:14:49+09:00",
"duration": 0,
"duration_formatted": null,
"status": "success",
"status_label": "성공",
"exit_code": 0,
"memory_usage_formatted": "417.34 KB",
"trigger_type": "manual",
"trigger_type_label": "수동 실행",
"triggered_by": null
}
],
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 25,
"total": 1,
"from": 1,
"to": 1,
"has_more_pages": false
}
}
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(core.schedules.read)이 없는 경우 |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
설명 특정 스케줄의 실행 이력을 페이지네이션으로 조회합니다. core.schedules.read 권한이 필요합니다. status(success/failed/running), trigger_type(scheduled/manual), 기간(started_from/started_to)으로 필터링하고 sort_by/sort_order 로 정렬할 수 있습니다. 스케줄 상세의 실행 이력 탭 표시에 사용합니다.
POST /api/admin/schedules/{schedule}/run
- 라우트명:
api.admin.schedules.run - 컨트롤러:
App\Http\Controllers\Api\Admin\ScheduleController@run - 인증/권한:
auth:sanctum+permission:core.schedules.run
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| schedule | path | string | 예 | — | 대상 schedule의 식별자 |
요청 예시
POST /api/admin/schedules/{schedule}/run HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
단건 응답: data 객체의 필드.
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| id | integer | 6 |
기본 키 (내부 식별자) |
| schedule_id | integer | 1 |
schedule 식별자 (연관 리소스 참조) |
| started_at | string | 2026-08-04T21:53:49+09:00 |
started 일시 |
| ended_at | string | 2026-08-04T21:53:49+09:00 |
ended 일시 |
| duration | integer | 0 |
실행 소요 시간 (초/밀리초) |
| duration_formatted | null | null |
duration 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| status | string | success |
상태 값 (도메인별 상태 집합 — 사람이 읽는 라벨은 status_label, UI 변형은 status_variant 참조) |
| status_label | string | 성공 |
상태의 사람이 읽는 라벨 (상태 Enum label() 산물) |
| exit_code | integer | 0 |
실행 종료 코드 (0=성공, 그 외=실패) |
| memory_usage | integer | 427312 |
실행 중 최대 메모리 사용량 (바이트) |
| memory_usage_formatted | string | 417.3 KB |
memory_usage 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| output | string | INFO Application cache cleared s… |
실행 표준 출력 내용 |
| error_output | null | null |
실행 표준 에러 출력 내용 (없으면 빈 문자열/null) |
| trigger_type | string | manual |
동작을 유발한 방식/주체 구분 값 |
| trigger_type_label | string | 수동 실행 |
trigger_type 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| created_at | string | 2026-08-04 21:53:49 |
생성 일시 |
| updated_at | string | 2026-08-04 21:53:49 |
최종 수정 일시 |
응답 예시
HTTP/1.1 200
{
"success": true,
"message": "스케줄이 실행되었습니다.",
"data": {
"id": 6,
"schedule_id": 1,
"started_at": "2026-08-04T21:53:49+09:00",
"ended_at": "2026-08-04T21:53:49+09:00",
"duration": 0,
"duration_formatted": null,
"status": "success",
"status_label": "성공",
"exit_code": 0,
"memory_usage": 427312,
"memory_usage_formatted": "417.3 KB",
"output": "\n INFO Application cache cleared successfully. \n\r\n",
"error_output": null,
"trigger_type": "manual",
"trigger_type_label": "수동 실행",
"created_at": "2026-08-04 21:53:49",
"updated_at": "2026-08-04 21:53:49"
}
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(core.schedules.run)이 없는 경우 |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
설명 스케줄을 예약 시각과 무관하게 즉시 실행합니다. core.schedules.run 권한이 필요합니다. 실제 명령이 수행되고 실행 이력 레코드가 생성되며, 그 이력(trigger_type=manual)을 반환합니다. 관리자가 대상 작업을 수동으로 즉시 돌려 결과를 확인하는 "지금 실행" 동작에 사용합니다.