Appearance
Working with other packages
Trackapt does the work itself, and it reads and writes what the rest of the industry uses.
Those are two separate claims and both are true. You can run a survey and a resource entirely inside Trackapt without opening anything else. You can also bring twenty years of existing work in, and hand your figures to a consultant who has never heard of Trackapt.
Why the exchange runs both ways
Nobody starts from nothing. You have a drillhole database somebody has curated since before you arrived, a folder of surveys, and a client's engineer who will check your volume in the package they know.
A system that could not read those files would be asking you to abandon the record, and a system that could not write them would be asking everyone you work with to buy it too. So the exchange runs in both directions, and the writers are proved by a round trip through Trackapt's own readers — which is the test that catches a swapped northing and easting, the fault that produces a mirrored plan and a plausible, wrong volume.
A blank to start from
Beside every file input is a Template button that hands you the file it reads, already the right shape. Take it, fill it in, and load it back — or send it to whoever is producing the data, so what arrives is right the first time.
This is worth doing before the first import rather than after the first failure. The readers below are forgiving about the order columns arrive in and strict about what has to be there at all, and that combination is why an import usually fails on the second attempt: the reader says which column it wants, whoever supplies the file guesses at a name for it, and the guess is only wrong in a way anybody notices once the rows have gone nowhere. A blank removes the guess, because the shape of the file is not described anywhere — it is the file.
Each carries the column names the reader actually looks for and two or three rows filled in as an example:
| Where | The blank it hands you |
|---|---|
| Import drillholes | Collars, downhole surveys and intervals — one apiece, beside each file |
| Import a survey | A pickup laid out for the instrument you chose above it, with ground shots, a feature line and a control peg |
| Import a boundary | One closed ring, in the string format the reader takes |
| New or edit block model | Block values, by centroid on the mine grid |
| New or edit wireframe | Section outlines, one closed string per section |
| A pit design | The toe and crest rings of a pit drawn elsewhere |
| A mine plan (under Import) | A schedule: one row per unit per period |
The survey blank follows the layout you picked
The instrument profiles differ in which of the first two numbers is the northing, and reading that the wrong way round is not an error you will see — it is a surface that builds perfectly and is mirrored. So the blank is built from whichever profile is selected, and changing the profile changes the blank.
The example rows are not decoration. An interval blank shows an assay column that is a number beside a lithology column that is text, because the reader decides which is which by looking at the values rather than at the name; a bench blank names its rings TOE 1100 and CREST 1110, which is the reading the pit design prefers.
What reads in
Survey pickups
| Format | Extension | Notes |
|---|---|---|
| Instrument CSV | .csv, .txt | Six column layouts, from named points to bare coordinates — you say which, or let the reader work it out |
| Surpac string file | .str | Recognised by its contents, so a .str written as .csv still reads correctly |
| LandXML | .xml | The general exchange format nearly every package writes |
| DXF drawing | .dxf | Points and polylines, with levels |
The DXF reader handles POLYLINE/VERTEX/SEQEND — the way every CAD package has written polylines since R12 — so a feature line arrives as a feature line rather than scattering into loose ground shots.
Codes are classified as ground, breakline or control at import, and your classifications are remembered for next time. See Surveys and pickups.
Drillhole databases
A drillhole database is three files joined on the hole name: collars, downhole surveys, and one or more interval tables. They come out of acQuire, out of Surpac, out of Datamine, or out of a spreadsheet somebody keeps by hand — as .csv, .txt or .dat — and they agree about almost nothing except that the first column is usually the hole name.
So columns are mapped, never guessed at. The reader proposes a mapping from the header row and shows it as a proposal; you confirm it before anything is filed.
Check the easting and the northing before you file
A collar file with the two the wrong way round loads perfectly, builds a perfectly good database, and puts every hole in the wrong place — mirrored about the diagonal, which on a north-south orebody looks almost plausible. It is the one column pair the reader will not decide for you.
Quoted fields are honoured, so a lithology description reading shale, weathered stays one column instead of shifting every assay after it by one.
Boundaries
An area somebody set out in Surpac or CAD can be filed as a boundary, so both sides measure the same ground rather than two similar-looking polygons.
What writes out
Everything that reads in also writes back out, on the mine grid, with no re-projection.
A survey
From an open survey:
| Format | What it carries |
|---|---|
| LandXML | Points and breaklines — the format every survey package reads |
| Surpac string file | Shots and feature lines |
| DXF drawing | Shots and feature lines, with levels |
Boundaries export as Surpac strings or DXF on the same terms.
A survey's triangles are left out by default
A ground surface is a height field, and the receiving package will triangulate it to its own rules. Carrying somebody else's triangulation invites two answers to one question, so the default file carries the points and the breaklines that decide the shape.
Where the other package wants this triangulation — a scheduler reading a topography it will never re-triangulate — the same header offers the surface as triangles: LandXML with its <Faces>, or a DXF of one 3D face per triangle on the layer SURVEY-TIN. Both are named … triangles so the two files are never confused. Where the account has named its grid, the LandXML carries it as its CoordinateSystem.
A wireframe
Open the solid — the same action that draws it in three dimensions — and it offers three:
| Format | What it carries |
|---|---|
| LandXML | The solid with its faces. First choice: text, and every mining package reads it |
| DXF drawing | One 3D face per triangle, on a layer named after the body |
| Surpac string file | The section outlines, not the skin |
Here the faces are the export
The opposite of a survey, and for a reason worth knowing. A solid's triangulation is the interpretation — a geologist decided it, section by section — and it cannot be re-derived from the points, because a closed body is not a function of easting and northing. A wireframe sent without its faces is a point cloud.
Why Surpac gets the outlines rather than the solid
Surpac takes a body as a string file plus a .dtm, and a .dtm written from guesswork is a file that looks right and loads as nothing. What a Surpac user does with somebody else's body is run a DTM from its outlines — which is also how this wireframe was built. If you want the solid itself in Surpac, send the DXF or the LandXML; both import.
A mine design
From an open design, as Surpac strings or a DXF drawing, with each kind of line on its own layer so a planner can toggle them apart:
| Design | What comes out |
|---|---|
| Pit | Every bench's toe and crest, as closed rings on PIT-TOE and PIT-CREST, each string named with its level |
| Road or ramp | The centreline on ROAD-CENTRELINE, and both running-surface edges on ROAD-EDGE — the string a grader is actually given |
| Drill rings | One line per hole, collar to toe, on DRILL-RINGS, named R<ring>-<hole> |
And as bodies, for a scheduler that takes mining blocks rather than strings — LandXML surfaces with their faces, or a DXF with one layer per body:
| Design | Bodies |
|---|---|
| Pit | PIT SURFACE, then one closed solid per bench (BENCH 3 1020.0-1030.0), and where the design carries stages, each stage's cut through each bench (STAGE A BENCH 3) |
| Waste dump | DUMP SURFACE, then one closed solid per lift (LIFT 2 1010.0-1020.0) |
| Road or ramp | ROAD SURFACE — the running surface as a strip |
A design is generated, so its export is too
What leaves is what the stored parameters currently produce. Revise the slope rules and the next export is a different pit — which is the whole point of not storing the geometry.
The other way round — a pit designed elsewhere. A pit drawn in another package arrives as its strings: a closed ring per toe and per crest, at their levels, as a Surpac string file or a DXF. On the design's editor, under As drawn elsewhere, read the file in and the pit is those benches: the slope rules describe it and are never run, the floor outline follows the lowest toe, and a plan for the pit reads exactly the benches that were drawn. Strings named TOE and CREST are read by name; unnamed rings by their level and size, the smaller ring at a level being the crest below and the larger the toe above. Back to the rules drops them, after asking. See A pit as drawn elsewhere.
A block model
As CSV: one row per block, with its centroid on the mine grid, its lattice indices ix, iy, iz, its dimensions, its volume, and every estimated field as its own column. Three files are offered:
| File | What it carries |
|---|---|
| Download as CSV | The estimated blocks — the file a consultant asks for |
| Every block as CSV | Every position of the lattice, estimated or not, with a blank where nothing has been said. What a scheduler wants when it will cut the model against its own solids — the blanks are air, and it needs to know where the air is |
| Definition as JSON | The lattice alone: origin, bearing, block size, counts, the attribute names, the reference the model carries elsewhere, and the account's grid. The file that lets the far end rebuild the lattice exactly rather than infer it from the centroids |
Where the model carries a reference elsewhere — the name it goes by in Vulcan or Deswik — that reference rides along as a model_ref column and in the definition, so the two sides can be sure they are talking about the same model.
Block models do not exchange as geometry — Surpac's .mdl, Datamine's .dm and Vulcan's .bmf are each proprietary and each a different shape — and the CSV is what all of them import. The lattice is implied by the centroids and the sizes, and every package rebuilds it on read. A rotated model exports as rotated blocks in true positions, rather than as a lattice the receiver has to rotate itself.
Blocks nobody has estimated are left out of the default file
A model is mostly air, and a file of millions of empty rows helps nobody — worse, a receiver treating a blank as zero would dilute every figure the model produces. The screen says how many blocks were written, so a smaller file than you expected is explicable rather than alarming. Ask for every block only when the far end needs the air, and then read its blanks as blanks.
Everything else
The drillhole register and its validation findings, a hole's log, the grade-tonnage curve, a design's warnings, every volume on a survey — all leave through the standard actions: reading-mode preview, Excel, PDF, print and share. See Taking data away.
Plans leave as a printed sheet at a stated scale, or as an image at print resolution. See Volumes and plans.
A plan, to and from a scheduling package
A scheduling package — Deswik NOVA, MineSched, Minemax, a consultant's own tool — takes a reserve in and gives a schedule back. Trackapt's plans speak both, so a plan can be handed over to be scheduled elsewhere and the answer read back in and published here, where the dashboards already judge it.
What leaves a plan
From an open plan's Exchange menu, once it has been computed:
| File | One row per | Carries |
|---|---|---|
| Reserve as CSV | Unit — a bench, or a stage's cut through a bench, in a pit | pit, bench, stage, unit, toe and crest RL, blocks, tonnes, ore and waste tonnes, grade, product, free-dig tonnes, and a column per quality the plan carries |
| Schedule as CSV | Unit per period | The period number, its label, from and to dates, the unit's identity, the fraction taken and the tonnes, ore, waste, grade and product that makes |
| Demands as CSV | Process per period | Demand against capacity, whether it was exceeded, and what the horizon stock had left |
| Whole plan as JSON | — | All three, with the plan's totals, its pits named, and the mode it was computed in — the document the exchange API hands out |
The reserve is pinned with the result: it is what the schedule was read against, and it is stored beside it, so the file a scheduler was sent and the plan that later reads its answer are the same reserve.
The unit is the join
unit is <pit>/<bench>/<stage> — the three parts as one string. A file that comes back carrying unit alone is split back into its parts; one carrying the three columns is read by them. Either way a row is matched to the reserve by identity, never by position.
What comes back
A schedule the other package decided — which units, which period, how much — comes back as CSV: from an open plan, Import a schedule (under Import) reads the file, shows what matched and what did not, and files it. The plan becomes an imported plan: the takes are exactly what the file said, period by period, and Compute reads the tonnes, the demands and the capacities off them without changing a single fraction. See A schedule decided elsewhere.
Columns are found by heading, never by position, and the reader tolerates the names schedulers use: pit or pit_name; bench, bench_no or bench_index; stage, pushback or cutback; period or a from date, which is resolved against the plan's own periods; and either fraction (0 to 1, or a percentage) or tonnes, from which the fraction is worked out against the reserve.
Send the schedule file back with the reserve's own unit column
Every scheduler can carry a text field through unchanged. Carry unit through and the match is exact, whatever the package did to the bench numbers.
References, and the mine grid, named once
Two small fields keep the two sides honest:
- Reference elsewhere on a block model, a wireframe or a design: the name the far end knows it by — a Vulcan model name, a NOVA solid id. It rides along in every file the record leaves in, and it is kept when the record is edited here.
- The mine grid, named once for the account under Integrations on the plans register: its name, its EPSG code where it has one, and its datum. Every LandXML the module writes then carries it as its
CoordinateSystem, and the block-model definition names it. Nothing is re-projected — Trackapt works on the mine grid and says which one it is.
The exchange API
Everything above is also available to a program, so a scheduler can pull the reserve and push the schedule without a person downloading files. The account holder, or a Level 6 user, opens Integrations on the plans register and:
- Makes a token, named for the package it is for, with a
readscope, orreadandwrite. The secret is shown once, when it is made; only its prefix is kept on screen afterwards. A token acts as the account holder for reading, so it sees every item. - Hands the secret to the other side, which sends it as
Authorization: Bearer tk_…on every call. - Revokes it when the integration ends. A revoked token is refused at once; the register keeps its name and when it was last used.
Version 1 lives under /api/exchange/v1:
| Method | Path | Scope | Returns |
|---|---|---|---|
GET | /whoami | any | The token's name, scopes and the account it acts for |
GET | /plans | read | The plan register: every plan's name, pit, mode, status and reference |
GET | /plans/:id | read | The plan as one exchange document — the same JSON as Whole plan |
GET | /plans/:id/reserve.csv | read | The reserve |
GET | /plans/:id/schedule.csv | read | The schedule |
GET | /plans/:id/demands.csv | read | The demands |
POST | /plans/:id/schedule | write | Files a schedule: the body is the CSV as text/csv, or JSON with a csv field. ?fileName= names it. The plan becomes an imported plan, not yet computed |
GET | /block-models/:id.csv | read | The model as CSV; ?all=true for every block |
GET | /block-models/:id/definition.json | read | The lattice definition |
GET | /surfaces/:id.xml | read | A survey as LandXML — points and breaklines, on the named grid |
GET | /designs/:id | read | A design with its generated geometry and its bodies |
The files a program pulls and the files a person downloads are the same bytes — one writer, in the shared kernel, serves both — so a schedule proved against a downloaded reserve proves against the API's.
Webhooks. Beside the tokens, an address can be registered to be told when a plan is published or unpublished. Each event is posted as JSON — the event, when, and the plan's id, name, status and horizon — with the event name in X-Trackapt-Event, and a signature in X-Trackapt-Signature — sha256= and an HMAC of the body under the hook's own secret, shown once when it is made. Verify the signature before trusting the body; a hook can be paused, and removed after asking.
A round trip with Deswik NOVA, in order
- Name the mine grid under Integrations, and give the block model and the pit design their NOVA references.
- Send NOVA the pit as bodies (LandXML), the block model as every block with its definition, and the topography as triangles, if NOVA is to cut its own reserve — or skip all three and send it the plan's reserve CSV, which is the reserve Trackapt read.
- Let NOVA schedule. Export its schedule as CSV, carrying
unitor thepit/bench/stagecolumns and either the fraction or the tonnes per period. - Import a schedule on the plan, or
POSTit through the API. Compute: the demands, the truck hours, the qualities of the feed and the dump balance are all read off NOVA's takes. - Publish. The figures reach the parameters the dashboards already judge, and the webhook tells NOVA's side that they did.
Bringing an existing operation across
A workable order, and none of it needs a second package running alongside:
- Create the tracker group and its items — the pits, dumps, stockpiles and pads the ground is surveyed against. Every survey names one, and it is what ties this month's survey to last month's.
- Import your most recent survey of each. That is your baseline; you can report against it immediately.
- Import the surveys you want history for, oldest first. Cut and fill are measured between any two of the same item, so the series becomes useful the moment there are two.
- Import the drillhole database — collars, surveys, intervals — and run Validate before anything is built on it. Faults an old database has been carrying quietly are worth finding now rather than in a resource statement.
- Rebuild the interpretations as wireframes from their section outlines, then define the block model and estimate onto it.
Import the old surveys even if you never open them
They cost nothing to keep, and the first time somebody disputes a monthly figure, the survey that settles it is the one from two years ago.
When something looks wrong
| What you see | Why, and what to do |
|---|---|
| A surface is mirrored, or a volume is plainly wrong | The column layout at import. Import the file again with the right one — a filed survey is not edited into shape. |
| Every hole is in the wrong place, mirrored about the diagonal | Easting and northing were mapped the wrong way round in the collar file. |
| A feature line arrived as loose points | An older DXF export, or the line was drawn as separate entities. Check the code's role at import — it must be breakline, not ground. |
| An assay column is full of lithology text | An unquoted comma in a description shifted the row. Re-export the table with quoting on. |
| A file will not read at all | Check the extension matches the format. A Surpac string file is recognised by its contents whatever it is called; the others are read by extension. |
| The exported file opens in the wrong place | Everything is written on the mine grid. If your other package is expecting a local grid, it is the receiving side that needs telling. |
| A wireframe's DXF looks like loose triangles | It is one 3D face per triangle, which is what makes it universally readable. Import it as a surface or a DTM at the far end and the body reassembles. |
| A block model CSV has far fewer rows than the model has blocks | Only estimated blocks are written by default. The count is reported when the file is made; Every block as CSV writes the rest, blank. |
| An imported schedule matched none of its rows | The file's pit, bench and stage do not name this plan's units. Send the reserve's unit column back through unchanged, or check the bench numbering — the reserve counts benches from 1 at the floor. |
| A schedule came back with less than it asked for | A row asked for more of a unit than the reserve had left, or a unit was taken after the one below it. The plan takes what it can and says so in the period's warnings; it does not reorder the file. |
| A token stopped working | It was revoked, or its scope is read and the call was a POST. GET /whoami says what a token is and may do. |
| A webhook's signature does not verify | Compute the HMAC over the raw body bytes, not over a re-serialised JSON, under the secret shown when the hook was made. |

