Admin Verification Document API
Admin endpoints for reviewing mentors' KYC verification documents — browsing the review queue, inspecting and downloading files, and approving / rejecting with a comment. The mentor side (upload, list, delete) is documented in Mentor Verification Document API.
- Base URL:
/api/v1/admin - Auth: Sanctum bearer token —
Authorization: Bearer {token} - Role: all endpoints require the
adminrole — non-admins receive403
Review rules
- Uploads start as
pending; a review setsapprovedorrejected—pendingis not a valid review target. - A rejection must carry a comment (
admin_notes), which is shown to the mentor. - Every review records the reviewing admin (
reviewed_by) and timestamp (reviewed_at). - The mentor is notified (database + mail) of every review outcome —
mentor.document_approved/mentor.document_rejected; the rejection mail includes the comment. - Once approved, the mentor can no longer update, replace, or delete the document. A mentor updating a
pending/rejecteddocument resets it topendingand wipes the previous review, so it re-enters the queue.
Response envelope
Success
{ "status": "success", "message": "…", "data": { } }
Error
{ "status": "error", "message": "…", "data": { } }
Status codes
| Code | Meaning |
|---|---|
| 200 | OK (list, show, download stream, status updated) |
| 401 | Missing/invalid token |
| 403 | Caller does not have the admin role |
| 404 | Document not found |
| 422 | Validation error, or document already has the requested status |
| 500 | Server error |
Admin document object
Admin responses include the owning mentor and review audit fields:
{
"id": "9b6f…",
"mentor_profile_id": "8a2c…",
"mentor_profile": {
"id": "8a2c…",
"legal_name": "John Doe",
"approval_status": "pending",
"approval_status_label": "Pending",
"user": { "…user object…" }
},
"document_type": "passport",
"document_type_label": "Passport",
"original_name": "passport.pdf",
"mime_type": "application/pdf",
"file_size": 204800,
"status": "pending",
"status_label": "Pending Review",
"admin_notes": null,
"reviewed_by": null,
"reviewer": null,
"reviewed_at": null,
"download_url": "https://api.example.com/api/v1/admin/verification-documents/9b6f…/download",
"created_at": "2026-07-01T09:00:00+00:00",
"updated_at": "2026-07-01T09:00:00+00:00"
}
file_sizeis in bytes; the raw storage path is never exposed — usedownload_url.reviewed_by/reviewer/reviewed_atare set on the first review and updated on later ones.mentor_profileandreviewerare present when the relations are loaded (list, show, review responses).
1. List verification documents (review queue)
GET /api/v1/admin/verification-documents
Returns all mentors' documents, oldest first (review-queue order), paginated.
Query parameters
| Param | Type | Default | Notes |
|---|---|---|---|
status |
string | — | Filter: pending, approved, or rejected. Unknown values are ignored. |
mentor_profile_id |
uuid | — | Only documents belonging to this mentor profile |
per_page |
int | 15 | Page size |
Example
GET /api/v1/admin/verification-documents?status=pending&per_page=20
200 Response
{
"status": "success",
"message": "Verification documents retrieved.",
"data": {
"verification_documents": [ { "…admin document object…" } ],
"pagination": { "total": 42, "per_page": 20, "current_page": 1, "last_page": 3 }
}
}
Errors: 401 unauthenticated · 403 not an admin
2. Show a verification document
GET /api/v1/admin/verification-documents/{id}
200 Response
{
"status": "success",
"message": "Verification document retrieved.",
"data": { "verification_document": { "…admin document object…" } }
}
Errors: 401 unauthenticated · 403 not an admin · 404 document not found
3. Download a verification document
GET /api/v1/admin/verification-documents/{id}/download
Streams the stored file as an attachment (Content-Disposition: attachment; filename=…).
Files live on a private disk — this endpoint is the only way to retrieve the binary for any
mentor's document.
200 Response: binary file stream (not JSON).
Errors: 401 unauthenticated · 403 not an admin · 404 document not found
4. Review a document (update status + comment)
PATCH /api/v1/admin/verification-documents/{id}/status
Approves or rejects a document. Records the reviewing admin (reviewed_by) and time
(reviewed_at), and notifies the mentor (database + mail) of the outcome — a rejection
mail includes the comment.
Body
| Field | Type | Required | Notes |
|---|---|---|---|
status |
string | yes | approved or rejected (pending is not a valid target) |
admin_notes |
string | required when rejecting | Max 1000 chars. Comment shown to the mentor — A comment is required when rejecting a verification document. |
Example — reject
{
"status": "rejected",
"admin_notes": "Document is expired, please upload a valid one."
}
200 Response
{
"status": "success",
"message": "Verification document status updated.",
"data": { "verification_document": { "…admin document object with status, admin_notes, reviewer, reviewed_at…" } }
}
Errors
| Code | When |
|---|---|
| 422 | status missing/invalid; admin_notes missing when rejecting |
| 422 | Document already has the requested status — Document is already {label}. |
| 404 | Document not found |
| 403 | Not an admin |
| 401 | Unauthenticated |
Related
GET /api/v1/admin/mentors/{profileId}(mentor application detail) also embeds the applicant's documents asdata.application.verification_documentsusing the same admin document object, so an application can be reviewed without extra requests.- Mentor Verification Document API — upload, list, download, delete (owner-scoped).