Overview
Vaccination moves individuals between compartments: a donor pool (typically Susceptible) and a vaccinated counterpart (typically Susceptible_vax), in the age groups a campaign targets and during its time window. Protection comes from the vaccinated layer using attenuated parameters (lower susceptibility, lower severity, etc.).
Quick start
The vaccination block of the API request only defines the rollout (e.g., schedule, doses, targets, flows), and the actual effects from vaccination are modeled with parameters from the model block.
The V-SEIHR model preset is one of the examples which uses vaccination feature, where we have vaccinated branch of compartments with VE_S and VE_H efficacy parameters. In this preset, vaccination by default generates the flow Susceptible → Susceptible_vax.
{
"model": {
"preset": "V-SEIHR",
"parameters": {
"R0": 2.5,
"incubation_period": 3.0,
"infectious_period": 2.5,
"hosp_duration": 5.0,
"hosp_proportion": 0.05,
"VE_S": 0.7, // vaccine efficacy against infection
"VE_H": 0.85
}
},
"population": {"name": "United_States"},
"simulation": {"start_date": "2025-01-01", "end_date": "2025-06-30", "Nsim": 10},
"vaccination": {
// "flows" is optional on V-SEIHR (defaults to S → S_vax pair); set it to override.
// "flows": [{"source": "Susceptible", "target": "Susceptible_vax"}],
"campaigns": [
{
"start_date": "2025-02-01",
"end_date": "2025-04-30",
"rollout": {"type": "flat_count", "daily_doses": 100000}
}
]
}
}
vaccination block
The block declares which compartments are involved in the rollout (flows) and which campaigns drive doses (campaigns). On V-SEIHR the default flow is Susceptible → Susceptible_vax; custom models must declare flows explicitly.
| Field | Required | Description |
|---|---|---|
flows | for custom models | List of {source, target} compartment pairs. V-SEIHR defaults to Susceptible → Susceptible_vax. See Flows for shapes (including dose sinks) and validation. |
campaigns | yes (≥1) | List of campaigns, each with its own dates, target age groups, and dose schedule. Multiple campaigns may overlap and their per-step dose schedules add. See Campaigns for the per-campaign fields and rollout strategies. |
From doses to a per-individual rate
Rate calculation
Each campaign turns a daily dose budget into a per-individual vaccination rate by spreading those doses across the live eligible pool:
Here is the set of age groups campaign targets, is the set of source compartments configured in flows, and is the live count in source and age group at step . The denominator is recomputed every step, so it tracks the pool as people leave or re-enter. In the simplest case (a single Susceptible → Susceptible_vax flow), it collapses to "daily doses divided by live susceptibles".
Flows
flows is a list of {source, target} pairs naming which compartments compete for doses and where vaccinated individuals move to. Every source contributes to the rate denominator above, and every flow with a non-null target emits a source → target transition. Entries with target: null are dose sinks: they shrink the rate denominator without moving anyone, useful when real campaigns can't pre-screen recipients (doses landing on already-recovered people are still consumed).
A few common shapes:
// 1. Perfect targeting (V-SEIHR default).
"flows": [{"source": "Susceptible", "target": "Susceptible_vax"}]
// 2. Dose sink: S + R compete for doses but only S transitions.
// Models a real-world campaign that cannot pre-screen recipients.
"flows": [
{"source": "Susceptible", "target": "Susceptible_vax"},
{"source": "Recovered", "target": null}
]
// 3. Multi-target: one budget shared across two susceptible strata.
// Each source draws from the shared budget in proportion to its live size,
// and each pair emits its own `<source>_to_<target>` transition at the same
// per-individual rate.
"flows": [
{"source": "Susceptible", "target": "Susceptible_vax"},
{"source": "Susceptible_2", "target": "Susceptible_2_vax"}
]
For example with shape #2: 4,000 susceptibles and 56,000 recovered sharing 1,000 daily doses yield an expected S → S_vax count of ; the rest are absorbed by R.
Dose allocation
The per-individual rate is shared across all targeted groups and sources, so each (source, group) cell receives doses in proportion to its live population. With a single flow [{S, S_vax}], a flat_count campaign targeting two age groups holding 4,000 and 6,000 susceptibles and a 1,000-dose-per-day budget delivers 400 and 600 doses respectively (in expectation).
At each step the simulator updates each source compartment independently with a multinomial draw over all of its out-edges. Every active vaccination flow leaving contributes the campaign rate from above, alongside any non-vaccination rates on the same source (e.g. infection ).
Bundling them into the total per-individual out-rate
the per-step counts out of are sampled jointly as
where enumerates the destinations reachable from (the vaccination target is one of them) and splits the total leave probability among them in proportion to each edge's rate.
In expectation, thus receives
If vaccination is the only out-edge of , the multinomial draw reduces to a binomial draw.
Vaccine efficacy
How much protection vaccination confers is a property of the model, not the rollout block. The V-SEIHR preset defines VE_S (against infection) and VE_H (against hospitalization); see the preset page for how they enter the dynamics. Custom models can mirror the same pattern with their own efficacy expressions.
Inspecting the rollout
Each transitioning flow surfaces as a regular transition in the response. For the default V-SEIHR rollout, look for Susceptible_to_Susceptible_vax under results.transitions.data. Note that flows with dose sinks (target: null) emit no transition.
The request itself is echoed back under metadata.vaccination, including the resolved flows list.
Use the API Reference to explore the vaccination schema field-by-field and try requests interactively.