InfraVoice

Human Agent Portal API

The Human Agent Portal is the surface your people sign into — the live agents who take over a call when the AI hands off. This page covers what you drive from your own backend with your organization key: provisioning those agents' portal credentials, and reading their presence, attendance and shifts.

Base URL: https://your-infravoice-host/api/v1 Auth header: Authorization: Bearer usf-… (your organization key, from Account → Organization key) Response envelope: every route here returns the standard Go envelope {"success":true,"data":{…},"error":null,"meta":…,"timestamp":…}. The shapes shown below are the data field.

"Agent" here means a human, not an AI agent. A human agent is a person with an agent code and a password; an AI agent is the configured voice bot documented elsewhere. Nothing on this page reads or writes AI agent configuration, so the draft-and-publish workflow that governs AI agent config does not apply — every call on this page takes effect immediately.

The agents themselves sign in through the portal application, which holds its own session for them. You provision the credentials here; they use them there.


Endpoints

MethodEndpointPurpose
POST/api/v1/agent-portal/admin/set-passwordSet or replace an agent's portal password.
POST/api/v1/agent-portal/admin/reset-passwordGenerate a temporary password, optionally emailing it.
POST/api/v1/agent-portal/admin/send-credentialsEmail an agent their slug, code and password.
GET/api/v1/agent-portal/admin/password-auditPassword action history for one agent.
GET/api/v1/agent-portal/admin/presence/realtimeLive presence board for a workspace.
GET/api/v1/agent-portal/admin/presence/attendanceAttendance summary over a date range.
GET/api/v1/agent-portal/admin/presence/timeline/{agentID}Raw presence event log, one agent, one day.
GET/api/v1/agent-portal/admin/presence/alertsShift-adherence alerts for a workspace.
POST/api/v1/agent-portal/admin/presence/shiftsCreate or upsert a weekly shift.
GET/api/v1/agent-portal/admin/presence/shifts/{agentID}List an agent's shifts.
DELETE/api/v1/agent-portal/admin/presence/shifts/{shiftID}Delete a shift.
GET/api/v1/agent-portal/healthLiveness. Also /healthz, /ready, /live.

Nothing here is billed per call. The portal's own endpoints consume no credits; the telephony and voice usage that happens because of a handoff is billed on those services' own terms.

Create the human agent records themselves with POST /api/v1/call-center/agents — see the Call Center page — then set their password here.


Admin (owner-side)

Everything under /api/v1/agent-portal/admin/* takes your usf- organization key. Despite the /admin/ path these are ordinary workspace-owner functions, not superadmin: the caller's workspaces claim must include the target agent's workspace, and an agent or workspace_id belonging to someone else is rejected.

Credentials

set-password takes {agent_id, password} (minimum 8 characters) and returns {"status": "password_set"}. Use it when provisioning agents programmatically and delivering the password yourself.

reset-password takes {agent_id, send_email}:

Shell
curl -X POST https://your-infravoice-host/api/v1/agent-portal/admin/reset-password \
  -H "Authorization: Bearer usf-YOUR_ORG_KEY" \
  -H "Content-Type: application/json" \
  -d '{"agent_id": "3f6c1b2e-8d4a-4c19-9b77-2a5e0c11d904", "send_email": true}'
JSON
{
  "email_sent": true,
  "message": "Temporary password emailed to the agent"
}

With send_email: false the generated temp_password comes back in the response body. That is a live credential in plaintext — never log it, never echo it into a UI you do not control, and never write it to disk.

send-credentials takes {agent_id, temp_password} and emails the agent the three things they need to log in. It returns {"status": "email_sent"}, 400 NO_EMAIL if the agent has no email address, and 503 SMTP_DISABLED if mail is not configured on the deployment — so a 200 here, unlike forgot-password, really does mean an email was dispatched.

password-audit takes a required ?agent_id=<uuid> and returns the action history — id, action, performed_by, performed_by_id, ip_address, details, created_at — covering every set, reset and credential email for that agent.

Presence and attendance

These back the workforce-management views in the dashboard.

realtime requires ?workspace_id=<uuid> and returns one row per active human agent with id, display_name, agent_code, status, status_changed_at, updated_at and max_concurrent_calls:

Shell
curl "https://your-infravoice-host/api/v1/agent-portal/admin/presence/realtime?workspace_id=b21f7e8c-5a44-4f0e-9d2c-77c1e3a90f18" \
  -H "Authorization: Bearer usf-YOUR_ORG_KEY"

attendance takes ?workspace_id= plus optional from, to (inclusive YYYY-MM-DD dates, both defaulting to today) and agent_id, and returns one row per agent per UTC day: id, agent_id, display_name, agent_code, date, the durations online_seconds, available_seconds, busy_seconds, on_call_seconds, wrap_up_seconds and break_seconds, the counters session_count and break_count, first_login / last_logout, and — only for a day the agent has a shift on — scheduled_start, scheduled_end, late_login_seconds, early_logout_seconds and shift_adherence_pct. Days are computed from the agent's own session log, so two edges are worth knowing: time from a session that began before the range is credited to the days it covers, but its first_login and session_count stay with the day the agent actually logged in; and a session still open right now is counted up to now, not to the end of the day. timeline/{agentID} takes an optional ?date=YYYY-MM-DD (defaulting to today) and returns the raw event stream — id, event_type, source, session_id, ip_address, details, created_at — which is where the connect, disconnect and tab-visibility events sent from the client end up. alerts takes ?workspace_id= and an optional ?unacknowledged=true, returning at most 100 rows newest first, each with alert_type, severity, message, details and acknowledged.

Shifts are what make the alerts possible. POST /admin/presence/shifts takes {agent_id, day_of_week, shift_start, shift_end, timezone?}timezone defaults to UTC — and upserts on the agent, day and start time, so re-posting the same shift edits it rather than duplicating it. Adherence is evaluated automatically whenever an agent connects or disconnects.


Errors

Errors use the same envelope: {"success": false, "error": {"code": "…", "message": "…"}, "timestamp": "…"}.

HTTPCodeMeaning
400INVALID_BODYBody was not valid JSON.
400INVALID_PARAMattendance only: from/to was not a YYYY-MM-DD date, or to preceded from.
400INVALID_TOKENReset token used, revoked, or past its 1-hour expiry.
400NO_EMAILsend-credentials for an agent with no email address.
401UNAUTHORIZEDMissing, malformed or revoked organization key.
403FORBIDDENThe agent or workspace belongs to another organization.
429Rate limit; a Retry-After header is set.
500LOGIN_FAILED, TOKEN_FAILED, UPDATE_FAILED, QUERY_FAILEDServer-side failure at the named step.
502UPSTREAM_UNAVAILABLE, SCOPE_FAILEDA service this route proxies to was unreachable.
503SMTP_DISABLEDMail is not configured on this deployment.

Requests are rate limited per client IP as a token bucket refilling at 100 requests per second with a burst of 200; a 15-second heartbeat and a few seconds' dashboard poll are nowhere near it, but a tight retry loop after a 502 can be. The service also applies a 30-second request timeout — every route here is a small database read or write plus, in a few cases, one short internal proxy hop, so a request approaching that ceiling means an upstream problem, not a slow query.