How to Approve a License Submission
A complete training guide for Stafferin supervisors: filter your team's pending licenses, review the type, number and expiry, then Approve or Reject. Compliance lives or dies on this page — get it right, every time.
Before you start
License Approval is a compliance-grade workflow. Every approval becomes part of an auditable record — for your organization, your insurers, and the security regulators in your region. Slow, careful, exact: that is the brief.
Approval is irreversible from the app. Once you tap Approve or Reject, the row leaves the active list. There is no Undo button on this screen. If you misclick, contact your admin immediately — they may need to re-open the record manually. Slow is smooth, smooth is fast.
Self-approval is blocked. The app explicitly stops you from approving or rejecting your own license: "Cannot take action on your own license". This is by design. If your own license is up for review, ask a peer supervisor or your admin to handle it.
Open License Approval
From the Stafferin admin home menu, tap License Approval. The page loads with a filter bar at the top and the message "Please select filters and click Apply to view licenses" in the body. Until you tap Apply, no rows are shown — by design, to avoid pulling the whole organization's records on every open.
The License Approval landing — filters first, results on demand.
What you should see
- An app bar titled "License Approval" in the supervisor's gold/amber theme.
- A filter bar with four fields: Employee, Status, From Expiry Date, To Expiry Date, plus an Apply button.
- A centered placeholder in the body: "Please select filters and click Apply to view licenses" until you Apply.
- Status defaults to
REQUESTED— the most common case, so you can hit Apply with one tap to see what is pending. - Both From and To dates default to today. You will likely need to widen the To date — see the callout below.
Watch your default dates. The model initializes both From and To Expiry to today. If you tap Apply without changing them, the search asks for licenses expiring on exactly today — almost certainly empty. Always widen the To date (e.g., +90 days) to see what is genuinely up for renewal.
"Failed to load employees"? The Employee dropdown loads on first open. If it errors out, the snackbar tells you so and you'll need a working data signal to retry — pull-to-refresh or back out and re-enter.
How it works at a glance
Before we dive into the details, here is the whole license-approval journey on a single line. Watch the indicator move through each step — that is exactly the order you will do them in the app.
Decision flowchart
Here is what happens behind the scenes. The orange diamonds are decision points — places where you decide which way the review goes.
(longer date range or
"All" status)
license card
action on your
own license" —
ask a peer
number, expiry
"License rejected
successfully"
"License approved
successfully"
Plain-English version: The supervisor view shows what the guard submitted. Your job is to check it carefully, then tap one of two buttons. The app records who you are, when you acted, and whether you said yes or no. Everything else is detail.
Watch the full license-approval flow
Six frames. Each one is a real screen from the app. Tap a step on the right to jump there, or use Pause / Restart.
Step-by-step demo
- Open License Approval — empty placeholder, filter bar at top.
- Set Employee, Status & Expiry range, tap Apply.
- Pending licenses appear — name, type, number, expiry.
- Read each card carefully. Verify type and expiry.
- Tap Approve (or Reject) — spinner shows while in flight.
- "License approved successfully" — row disappears.
One row at a time. The buttons disable while a row is in flight. You cannot mass-approve. This is intentional — every approval is its own auditable decision.
Reading a license submission
Each card on the License Approval page summarises one license submission. The fields are simple but the details matter.
A REQUESTED license card. Action buttons only show on REQUESTED rows.
What each field means
-
Employee name — top-left, with person icon
Shown as "First Last". If the record has no name, the app shows "Unknown". That should be a red flag — request a re-submission with proper details before approving.
-
Status pill — top-right, color-coded
Three values map to the API:
REQUESTED(orange),APPROVED(green),REJECTED(red). Action buttons only show onREQUESTED. -
License Type — what kind of license
Free-text field today: whatever the guard typed when uploading. Watch for typos and synonyms (e.g., "Sec License" vs "Security Licence") — they may indicate the same physical document.
-
License Number — the issuing authority's reference
Each jurisdiction has its own format. Familiarize yourself with the valid formats for your region. Mismatched format is a fraud red flag.
-
Expiry Date — when it stops being valid
Localized display (e.g. "Jun 15, 2026"). If it shows "N/A", the date wasn't parseable — flag the submission to the guard for re-entry.
-
Approve / Reject buttons — only on REQUESTED
Already-approved or rejected rows show no buttons. The card simply displays the recorded outcome.
Common license types you'll review
The app does not enforce a license-type taxonomy today; the guard types it freely. These are the most common categories you should expect:
Security Guard License
Mandatory in most jurisdictions. Issued by the regional regulator (e.g., MCSCS in Ontario, BSIS in California, SIA in the UK). Without it, the guard cannot work most posts.
First Aid & CPR
Standard or Emergency level certificates. Common providers: Red Cross, St. John Ambulance, Heart & Stroke. Usually 3-year expiry.
Weapons / Firearms Permit
Required only for armed posts. Heavily regulated; verify against the issuing authority's database when in doubt.
Use-of-Force Training
Often required for high-risk posts. Some jurisdictions package this with the security license, others issue separately.
Driver's License
Required for mobile / patrol posts. Verify class matches the vehicle assigned (full vs. graduated).
WHMIS / Hazard Awareness
Workplace Hazardous Materials. Typically required for industrial, warehouse, or chemical sites.
Basic Security Training
The pre-licensing course completion certificate. Sometimes required separately even when the security license is present.
Other
Anything else: working-at-heights, defensive driving, K9 handling, etc. Read the type field carefully and verify against your site requirements.
Heads up — license type is freeform today. Two guards may use slightly different wording for the same document. When you spot inconsistency, encourage your team to use a consistent label so reports are clean.
Document preview & verification
The guard uploads the license as a PDF (max 10 MB) when they submit. The supervisor view should let you preview it before approving — a name and a number alone aren't enough for compliance.
What the guard submitted
On the guard side (the License page), the submission flow is:
-
Pick a PDF file
The guard taps "Add License" and selects a PDF only (no images, no Word docs). Files larger than 10 MB are rejected with "File size exceeds 10MB limit. Please select a smaller file."
-
Fill in the metadata
License type (free text), license number, expiry date. They tap Submit.
-
Submission lands as REQUESTED
Their license shows up in your supervisor queue with status REQUESTED. They wait for your review.
Verifying authenticity
You are the human in the loop. The app does not auto-validate licenses against the issuing authority. Use this checklist:
If anything looks off — Reject. A genuine renewal can always be re-submitted. A fraudulent or unfit license that gets approved is a compliance breach. Default to caution: reject and ask the guard to re-submit with clearer documentation.
Tip — keep a personal log. When you reject, jot the reason in your own notebook. The current app does not capture rejection reasons (planned), so the guard will not see your reason on their side. Reach out directly to explain.
Approve or Reject — the actual decision
Once you've reviewed the submission, take action. Two buttons; pick one. Both are final from this screen.
Approve (green) and Reject (red) — only on REQUESTED rows.
The two buttons
-
Approve — the green check
Sends
POST /license/approve/{licenseId}. While in flight the button shows a spinner and the label changes to "Approving...". The opposite button (Reject) is disabled. On success: green toast "License approved successfully" and the row disappears from the list. -
Reject — the red cross
Sends
POST /license/reject/{licenseId}. Spinner shows "Rejecting...". Approve is disabled. On success: "License rejected successfully" and the row clears. Heads up: the API does not currently capture a rejection reason — the guard sees status REJECTED with no explanation. Contact them out-of-band. -
Self-approval — blocked
If the license belongs to your own employee record, neither button works — the snackbar fires "Cannot take action on your own license" and nothing is sent. Get a peer supervisor to review your own submissions.
Status transitions
A license has three states. Once it leaves REQUESTED, you cannot change its state from this page.
| Status | Pill color | What it means | Your action |
|---|---|---|---|
| Requested | Orange | Guard submitted, awaiting your review. | Read the card. Tap Approve or Reject. |
| Approved | Green | You (or another supervisor) approved it. Guard sees a green pill. | None — record is closed. |
| Rejected | Red | You (or another supervisor) rejected it. Guard sees a red pill. | None — the guard must re-submit a corrected one. |
| Expired (derived) | Orange | License was approved but the expiry date has passed. | Prompt the guard to renew — new submission required. |
Why does the pill say "REQUESTED" not "Pending"? The app's design system maps REQUESTED to a Pending color/icon, but the card text shows the raw API state (REQUESTED). If you see all-caps status text on the pill, that's normal — the colors are still right.
Rejection is final from this screen. The app does not let you "un-reject" or undo. If you reject by mistake, contact your admin immediately. The guard will need to re-submit; ideally tell them why so they don't repeat the mistake.
Errors & how to fix them
Every error message you can see during license approval, with what it actually means and what to do.
Loading errors
| If you see… | It means | Do this |
|---|---|---|
| "Failed to load employees (Status: 500). Please try again." | The Employee dropdown list call failed. Backend or network issue. | Pull-down to refresh. If persists, check signal & retry. Status code is just for support — not your concern. |
| "Unable to load employees. Please check your connection and try again." | An exception bubbled up from the employee call — usually a network timeout. | Check WiFi / data, retry. If still failing, you'll need to come back online before reviewing. |
| "Failed to load licenses (Status: NNN). Please try again." | The license list call failed after you tapped Apply. | Tap Apply again. If repeats, simplify your filters (try just one employee, no date range) and retry. |
Filter / Apply errors
| If you see… | It means | Do this |
|---|---|---|
| "Please select employees and click Apply" | You tried to load licenses without choosing an employee filter. | Pick an employee (or "All Employees") in the dropdown, then Apply. |
| "Please select employee(s) before applying" | Same intent, fired earlier in the validation chain. | Pick at least one employee filter value, then Apply. |
| "From Date cannot be after To Date" | Your From Expiry is later than your To Expiry — impossible range. | Re-pick the dates. From should be on or before To. |
Approve / Reject errors
| If you see… | It means | Do this |
|---|---|---|
| "Cannot take action on your own license" | The license belongs to your own employee record. Self-approval is blocked. | Ask a peer supervisor or your admin to handle this row instead. |
| "Failed to approve license. Please try again." | Server rejected the approve call. May be permission, may be transient. | Retry once. If still failing, contact admin — your role may have changed. |
| "Failed to reject license. Please try again." | Same shape, but for the reject call. | Retry. If still failing, contact admin. |
| "Unable to approve license. Please check your connection and try again." | Exception caught client-side — usually a network drop mid-request. | Check signal, retry. The server may have already accepted — refresh the list to see the current status before re-tapping. |
| "Unable to reject license. Please check your connection and try again." | Same as above for reject. | Same: check signal, refresh, then retry only if still REQUESTED. |
| "Approving..." stuck on button | Network is slow or the request is taking a long time. | Wait 10 seconds. If still stuck, the row may already have been processed — back out and re-Apply to see current state. |
Empty states
| If you see… | It means | Do this |
|---|---|---|
| "Please select filters and click Apply to view licenses" | Initial state before you've applied any filters. | Pick filters, tap Apply. |
| "No licenses found" | Your filters returned zero results. Could mean nothing's pending, or your filters are too narrow. | Widen the date range, switch Status to "All", or pick a different employee. |
FAQ
What if I approve the wrong license by mistake?
The app does not let you un-approve. Contact your admin right away — they may be able to re-open the record manually or amend the approval. Going forward, slow down: the row stays on screen long enough to read; there is no time pressure on this page.
Can I undo a rejection?
Same answer: not from this screen. Ask your admin. The guard will need to re-submit a fresh license record to get a new REQUESTED row in your queue.
Why can't I approve my own license?
Conflict-of-interest. The app explicitly blocks self-approval with the message "Cannot take action on your own license". Ask a peer supervisor or your admin to review yours.
Why doesn't the rejected guard see my reason?
The current Reject API takes only the license ID — no reason or notes are sent to the server. The guard sees status REJECTED on their side but no explanation. Reach out directly (in person, message, or phone) to tell them why and what to fix. A "rejection notes" feature is on the roadmap.
Can I see a guard's full license history (past approvals/rejections)?
Yes — switch the Status filter from "Requested" to "Approved", "Rejected", or "All". The list will show licenses in that status. You won't see who acted on each one from this view, but the records are there.
Why doesn't the page auto-refresh when a new license is submitted?
By design — the supervisor view only loads when you tap Apply. Pull-down to refresh after acting on a row, or change a filter and Apply again to pull the latest list.
What file format does the guard upload?
PDF only, up to 10 MB. Other formats (JPG, PNG, DOCX) are rejected at upload time on the guard side. If the supervisor view shows a license without a viewable document, that's a sign the upload failed silently — ask the guard to re-submit with a clean PDF.
What if the license number format looks wrong?
That's exactly what your review is for. Reject the submission and tell the guard what's wrong (typo, missing prefix, wrong region). They can re-submit with a corrected number.
Why does the page default Status to "Requested"?
Because that's the action queue — rows you actually need to act on. You can change to All / Approved / Rejected for audit or history, but the default makes the most common use case one tap.
What happens to APPROVED licenses when their expiry date passes?
The license remains in APPROVED status in the database, but compliance reports flag it as expired (derived from the expiry date being in the past). The guard sees an "Expired" indicator on their License page and is prompted to submit a renewal — which lands as a new REQUESTED row in your queue.
Can I bulk-approve multiple licenses at once?
No. Every approval is an individual action with its own auditable timestamp. This is intentional — you're attesting to each one personally.
Why does the Apply button look slightly faded sometimes?
It's at reduced opacity when there are no unapplied changes — meaning the displayed list already matches your filter selection. Once you change anything (employee, status, date), the button brightens to indicate "tap me to refresh".
Why are licenses sometimes labelled "Unknown" by name?
The employee record is missing a first or last name. Treat it as a data-quality flag — tell your admin so the employee record gets fixed before you approve anything tied to it.
How can I make sure I'm reviewing fresh submissions?
Filter Status = Requested and set From Expiry = today, To Expiry = several months ahead. That captures both newly-submitted licenses and ones expiring soon. Refresh once a day, or whenever a guard tells you they've submitted.
Is there an audit log of my approvals and rejections?
Server-side, yes — every action is timestamped with your user ID. The supervisor view does not currently surface "history of my own actions" but the data is there for your admin to query.
Quick reference card
Print this section and keep it in your pocket for the first few reviews. After ten approvals, you won't need it.
Compliance first, speed second. Every approval is an audit record with your name on it. If a license looks wrong, reject it and ask the guard to re-submit. Better one extra round-trip than a rubber-stamped fraud on the books.