Stock Audit

Support & API Reference for the Stock Audit iOS app.

Getting Started

Stock Audit connects to your own hosted inventory management server. Before signing in you will need:

Enter these on the Sign In screen and tap Sign In.

How to Conduct an Audit

  1. After signing in, tap the + button on the Audit History screen.
  2. Select the category of items you want to audit.
  3. The app presents items one at a time. Enter the physical stock count you observe on the shelf or in the stockroom.
  4. Tap Submit & Continue to record the count and advance to the next item. If the physical count matches the system stock exactly, tap Matching with System Stock instead.
  5. Once all items are counted a completion summary is shown. Open Valuation Summary to review discrepancies.

To correct a previously submitted count, open the audit from Audit History, then long-press any item row to edit it.

Valuation Summary

The Valuation Summary shows:

Tap the share icon to export the report as plain text and send it via Mail, Messages, or any other app.

Audit History

The home screen lists all audits for the current calendar month. Pull down to refresh. Tap any audit to view its item-level detail. Incomplete audits can be resumed by tapping Continue.

Frequently Asked Questions

The app says "Could Not Connect" on the login screen.
Check that your device is connected to the internet, and that the server URL is reachable. Ensure that the username and password provided are valid and correct.

Can I use the app without a server?
No. Stock Audit is a client app that requires a compatible backend server. Please refer to the Backend API Reference for the required endpoints.

Is my data sent to a third party?
No. All data is transmitted directly between your iPhone and your own server. Stock Audit does not send any data to external services.

How do I add new products or units?
Products and units are managed on the server side. Please refer to your inventory system's documentation or contact your server administrator.


Backend API Reference

Stock Audit talks to a REST API served from the base URL you configure at sign-in. All endpoints accept and return JSON. Authentication is session-based (Django-style): a successful login sets a sessionid cookie that must be sent with every subsequent request. POST requests also require a X-CSRFToken header carrying the value of the csrftoken cookie (obtained after login). The login endpoint itself is CSRF-exempt.

Base URL: All paths below are relative to the server base URL the user enters in the app (e.g. https://your-api-server.com).

1. Login

POST /api/login/

Authenticates the user and opens a session. CSRF-exempt — no token needed for this call.

Request body

"username": "john",
"password": "secret"

Success response — HTTP 200

"ok": true,
"username": "john",
"csrftoken": "abc123..."

Failure response — HTTP 400 / 401

"ok": false,
"error": "Invalid credentials."

On success the server must set a Set-Cookie: sessionid=... header (and optionally csrftoken=...). The app stores both cookies and attaches them to all subsequent requests automatically.

2. Get Available Audit Units

GET /api/audit/unit_descriptions/

Returns the list of categories/locations that can be audited.

Response — HTTP 200

"units": [
  {
    "unitcode": 1,
    "unitdescription": "Warehouse A"
  },
  ...
]

3. Start a New Audit

POST /api/audit/start/

Creates a new audit session for the given unit and returns its metadata.

Request body

"unit_description": "Warehouse A"

Response — HTTP 200

"audit_id": 42,
"unit_description": "Warehouse A",
"total_items": 120,
"username": "john"

4. Get Next Unaudited Item

GET /api/audit/{audit_id}/next_item/

Returns the next product that has not yet been manually counted. When all items have been counted, returns "done": true.

Response — item pending (HTTP 200)

"done": false,
"audit_id": 42,
"productcode": "P001",
"productname": "Paracetamol 500mg",
"computer_stock": 100.0,
"manual_stock": null

Response — audit complete (HTTP 200)

"done": true

5. Submit Manual Count

POST /api/audit/{audit_id}/update_stock/

Records the physical count for one product. Can also be called to overwrite an existing count (used by the edit flow).

Request body

"productcode": "P001",
"manual_stock": 95.0

Response — HTTP 200
Any JSON body (app ignores it). A 200 status is sufficient.

6. Get Audit Status

GET /api/audit/{audit_id}/status/

Returns the current progress counters for an audit.

Response — HTTP 200

"audit_id": 42,
"unit_description": "Warehouse A",
"completed": 80,
"total": 120,
"remaining": 40,
"username": "john"
Note: The app reads "completed" as an integer (item count), not as a boolean.

7. List Audits

GET /api/audit/list/?start_date=YYYY-MM-DD&end_date=YYYY-MM-DD

Returns all audits started within the given date range for the authenticated user.

Response — HTTP 200

"audits": [
  {
    "audit_id": 42,
    "unit_description": "Warehouse A",
    "completed": true,
    "start_datetime": "2026-04-01T09:30:00Z",
    "end_datetime": "2026-04-01T10:15:00Z",
    "completed_items": 120,
    "total_items": 120,
    "username": "john"
  },
  ...
]

Datetime strings must be ISO 8601 format (e.g. 2026-04-01T09:30:00Z or with fractional seconds).

8. Get All Audit Items

GET /api/audit/{audit_id}/items/

Returns every item in the audit, including those not yet counted. Used to display the detail table.

Response — HTTP 200

"audit_id": 42,
"unit_description": "Warehouse A",
"username": "john",
"items": [
  {
    "productcode": "P001",
    "productname": "Paracetamol 500mg",
    "computer_stock": 100.0,
    "manual_stock": 95.0
  },
  {
    "productcode": "P002",
    "productname": "Amoxicillin 250mg",
    "computer_stock": 50.0,
    "manual_stock": null
  },
  ...
]

manual_stock is null for items not yet counted.

9. Get Valuation Summary

GET /api/audit/{audit_id}/valuation/

Returns a financial breakdown of all stock discrepancies, using unit prices from the inventory system.

Response — HTTP 200

"audit_id": 42,
"unit_description": "Warehouse A",
"username": "john",
"shortage_items": [
  {
    "productcode": "P001",
    "productname": "Paracetamol 500mg",
    "quantity": 5.0,
    "unit_price": 12.50,
    "total_value": 62.50
  }
],
"excess_items": [ ... ],
"shortage_total_value": 62.50,
"excess_total_value": 0.0

quantity is the absolute difference between manual and system stock. total_value = quantity × unit_price.

10. Delete an Audit

POST /api/audit/{audit_id}/delete/

Permanently deletes an audit and all its item records.

Request body
Empty (send Content-Type: application/json with an empty body or {}).

Response — HTTP 200
Any JSON body. A 200 status is sufficient.

Error Response Format

For any error, the server should return an appropriate HTTP status code and a JSON body in this shape:

"error": "A human-readable description of the error."
The app stores both sessionid and csrftoken as cookies and automatically attaches them. If you implement the backend with Django, enabling SessionMiddleware and CsrfViewMiddleware covers this out of the box.

Contact & Support

If you experience a problem not covered above, please send an email to stockauditapp.ios@gmail.com.