Concepts
Everything a provider needs to understand before writing code. The reference has the field-level detail.
The BlastCase
A case is everything a model may read about one blast. The platform assembles it from the design, the receivers and the laws fitted to the site’s measurements, and adds the question being asked. The contract also carries the as-built record and raw calibration data, for when the platform fills them in.
design: holes from collar to toe as decks, products, delays, the initiation system and drilling accuracy, plus the maximum instantaneous charge as the platform computed it for compliance. Hole and charging fields follow IREDES, the drill-and-blast data exchange standard, so a provider that already reads IREDES maps them field by field. A what-if question may carry only the charge.asBuilt: the holes as drilled and loaded, and the firing record from the detonator log. Absent before the blast.site: rock domains and, when a model needs it, a terrain surface passed by reference.receivers: monitors, structures, boundaries and points of interest, each with a position, the distance the platform resolved to it (surveyed, entered, or to the nearest charge), or both, and the limits that apply there.calibration: what the site has measured (see Calibration data).measured: the blast’s own ground-motion records, once it has fired. Sent only for a diagnosis.request: the output kinds wanted, receivers or a grid, the percentiles to report and a sampling seed.consent: the data owner’s terms for this case, and its purpose: a prediction, or a diagnosis of a fired blast.
The caseId is the SHA-256 of the case’s canonical JSON, without caseId and createdAt, and without the uri of any BlobRef (any object carrying uri, sha256 and mediaType): the bytes are named by their hash, and a signed URL changes from run to run. The same blast asked the same question always has the same id, and a provider can recompute it to check what it received.
The manifest
A model describes itself in a manifest served at GET /manifest: its id and version, the output kinds it produces, the inputs each one needs, the domain it is validated on, how it runs, what it costs and how it handles data.
Inputs are declared as case paths such as calibration.seedWaveforms: required, optional, or in a group that stand in for one another (requiredAnyOf, such as the charge from the stated MIC or from the holes). A model missing a required input, or every input of a group, declines with missing_input. The platform removes everything a model does not declare before sending the case, and hashes the case id again over what remains. A provider never receives data it did not ask for, and a change to data it does not read never re-runs it.
Pricing is one of included, per_run, per_hole, quote (a binding price per case from POST /quote) or licence, where the operator brings their own licence and the run itself is not charged.
The ModelResult
A result is a list of typed outputs, each discriminated by kind. Every output carries a validity verdict: within the domain the model was validated on, extrapolated beyond it, or outside it, with a code saying which way, such as above_fitted_range or near_field.
An output the model will not produce goes under unavailable with a reason: not_supported, missing_input, outside_validity or insufficient_calibration. A kind answered per receiver names the receiver it declines at in receiverId, or null when it declines at every receiver; a kind answered for the whole case names none. Leaving it out is not an answer. Declining is better than a confident number outside the model’s domain.
provenance pins the result to the model id, the exact version, the case id, the inputs actually read and any parameters the model fitted. Reports cite it.
Some questions run backwards. max_charge asks for the largest charge per delay whose prediction at the case’s design percentile stays under each receiver’s limit: the figure a blast is planned to.
Uncertainty is part of the answer
Quantities are Estimate objects: a median plus the percentiles the case asked for, and optionally raw ensemble members. Compliance decisions are made on upper percentiles, not medians, and a prediction without a spread cannot be scored for coverage.
Where a receiver has a limit, report the probability of exceeding it. It is the number an operator acts on.
Calibration data
Rock masses are inhomogeneous, and the constitutive properties a first-principles model needs are rarely measurable in the field. Quantities that can be measured, such as particle velocity, detonation velocity and displacement, make a model easier to calibrate and to validate. The contract has a place for each. A case from the platform carries the fitted site and airblast laws today.
siteLaw: the scaled-distance attenuation law fitted to the site’s own readings, with the fit statistics a prediction interval needs (degrees of freedom, the spread of scaled distances) and the dominant frequency the site records at each distance.airblastLaw: the same for overpressure on cube-root scaled distance.seedWaveforms: single-hole ground-motion records with charge and distance, the input for seed-waveform superposition.vod: measured velocity of detonation per hole.outcomes: readings from earlier blasts at the site.strainAmplitude: the site's fit of the strain a blast puts in its rock near the charges, as a factor on the amplitude a damage model extrapolates inward from the site law, with what it was fitted to (backbreak, half-cast counts, a scan or a strain array) and the model and version it was fitted with.
Diagnosis of a fired blast
Most kinds predict. hole_diagnosis reads a blast that has fired: from the blast’s own ground-motion records and its detonator log, what each hole did. Such a case has consent.purpose of diagnosis, asks only for hole_diagnosis, and carries the records as measured.records: each one’s rows, the receiver it was made at and how its axes lie. A record’s time against T0 is not known, since a recorder starts on the motion reaching it; finding it is the model’s work.
Every charged hole gets a verdict (on time, late, early, not detected, weak or strong) and a confidence that covers only what the verdict claims: that the hole fired and when, its size, or that it did not fire. Size is also a claim of its own (size.call), so a hole can be on time and weak at once, and alternatives are separate claims that need not sum to one. evidence carries the motion the model attributes to the hole alone, so a reader can see what a verdict rests on.
The published examples include a fired blast as a diagnosis case, its two records and the platform’s own answer: /developers/examples/v0/diagnosis-case.json and /developers/examples/v0/diagnosis-run.json. Its second row fires late, its third row does not fire, and it has one strong hole and one weak one.
strain_amplitude reads a fired blast too: from the backbreak seen behind some of its holes (measured.backbreak), the factor on a damage model’s amplitude that makes the radius it reports on each the distance seen. The answer is what a later case of the site carries as calibration.strainAmplitude, with the model and version that fitted it as fittedWith, since a factor means something only to the model that made it.
Sync and async runs
A sync model answers POST /runs within 30 seconds with the run succeeded. An async model answers 202 with the run queued, then sends run.running, run.succeeded or run.failed to the callback URL. The platform will poll GET /runs/{runId} as a fallback.
Every POST /runs carries an Idempotency-Key. A retried request with the same key must return the original run, not start a second one. Deliver webhooks at least once; each carries an event id, so a duplicate can be recognised and dropped.
Caching and reproducibility
Results are stored against the case id and the model version. An identical case sent to the same version is answered from storage: it is not run again and not charged again. A new model version is a new key, so earlier results stay exactly as they were issued.
Models that sample must honour request.seed, so a run can be reproduced from its case alone.
Scoring against measurements
When a blast fires, the platform’s monitors record what happened at the receivers. Each recorded prediction for that blast is held to those readings at the same receiver: under the P50, within the P95 or above it. The platform’s own models are scored this way, and in early access so are a team’s connected models. Over many blasts the same scores add up to bias, P95 coverage and skill, per site and per model.
Scores are private to the operator’s account. A team that connects its own model sees that model’s answers and scores in its own account, and nothing is published without the provider’s agreement.
Consent and data handling
Each case states what it is for (a prediction, or a diagnosis, which sends the blast’s own records), how long the provider may keep it and whether it may be used for training (never, unless the data owner opts in). A provider that cannot honour those terms must refuse the run with consent_refused. The manifest declares where cases are processed, so an operator can see where a case would go before choosing a model.
Versioning
Every document carries specVersion. During the preview, v0 may gain fields, and readers must ignore fields they do not know. Breaking changes will come as a new major version with a deprecation window, announced to partners in advance.
Conventions: SI units throughout (metres, kilograms, milliseconds, mm/s, pascals). Coordinates are +X east, +Y north, +Z up, in the case’s coordinate system. Times are UTC ISO 8601. Firing times are milliseconds from T0. An absent field means unknown, never zero.