data register / data act
Register of exportable data structures and formats — Markerra Studio
How to download your data
For game organizers (a Markerra Studio account). If you play in the app, write to kontakt@markerra.app for a copy of your data — see the Privacy policy.
- Sign in to the Markerra Studio organizer panel.
- Below your game list, open “Your account”.
- Click “Download my data (JSON)” — the file is saved to your device.
You do not need to e-mail us. The e-mail route in section 1 below remains available in parallel — it is especially useful when the panel reports an incomplete file or is not working, and when the account was already closed while switching to another provider.
Last updated: 6 October 2026 · Export format: markerra-studio-export-1
This register implements Article 26(b) of Regulation (EU) 2023/2854 (the Data Act). It describes the data structures, data formats and relevant standards and open interoperability specifications in which a Markerra Studio game organizer receives their exportable data referred to in Article 25(2)(e) of the Data Act and described in §15 of the Studio Terms of Service ("Termination and data transfer"). This register is updated together with the code — any change to the export format is recorded in the version history below and in this document in the same release, and a change that is not backward-compatible also raises the version number.
1. How to obtain the data
The organizer downloads their own data while the account is available, using the "Download my data (JSON)" button in the Studio panel, under "Your account". The panel saves the response as a file named markerra-studio-export-<YYYY-MM-DD>.json. Requesting the export by e-mail is not required — the e-mail route described in §15 of the Terms (a request to kontakt@markerra.app, answered within 14 days) remains available in parallel, as a supplement in case the row limit is exceeded (see section 5) or the panel is unavailable. After the transition period ends, we provide a separate period of at least 30 days to retrieve the data (§15 of the Terms). If the account was closed as part of switching, the operator arranges secure retrieval of the protected copy through the same e-mail route, after verifying identity.
2. Data format and standards used
- File format: JSON (JavaScript Object Notation), conforming to RFC 8259 (The JavaScript Object Notation (JSON) Data Interchange Format) — an open, widely used interoperability specification with no proprietary elements.
- Character encoding: UTF-8.
- Dates and timestamps: ISO 8601 (e.g.
2026-09-04T10:15:30.000Z), always in Coordinated Universal Time (UTC). - Identifiers: Appwrite database document identifiers (
$id) — strings assigned by the database platform, stable over time, also used as keys linking records across export sections (e.g.campaignIdon a marker refers to the$idof the corresponding campaign). - Geographic coordinates: latitude and longitude as decimal numbers (degrees), within the ranges -90…90 (latitude) and -180…180 (longitude) — the same ranges enforced when a game is created. These are standard decimal-degree geographic coordinates as used by mapping and GPS services (equivalent to the WGS 84 reference system); the code does not name the reference system explicitly, so this sentence is an inference from common industry practice, not a direct code citation.
- No proprietary formats: the export uses no format or library requiring a licence, specific software, or a closed specification. The entire document can be read by any JSON parser conforming to RFC 8259.
3. Response structure (envelope)
The export response is a single JSON object with the following fields:
| Field | Type | Description |
|---|---|---|
status |
string | "ok" on success. |
generatedAt |
date (ISO 8601) | The moment the export was generated. |
format |
string | Export format identifier — today "markerra-studio-export-1". |
account |
object | The organizer's account data, see 4.1. |
games |
array of objects | The organizer's games, see 4.2. |
campaigns |
array of objects | Published game configurations, see 4.3. |
markers |
array of objects | Markers (points) of published games, see 4.4. |
payments |
array of objects | The organizer's payments, see 4.5. |
acceptances |
array of objects | Rule acceptances the organizer made as a player — from every game played with the account, including the demo and other organizers' games; see 4.6. |
notes |
object | Descriptions of export sections in Polish and English — today a description of the acceptances section, see 4.7. |
truncated |
boolean | true if any section was cut off at the combined 5,000-row ceiling — see section 5. |
4. Structure of each section
Besides the fields listed below, every row coming from the database carries three database system fields: $id (identifier), $createdAt and $updatedAt (ISO 8601 timestamps) — these three are kept in the export deliberately, since without them the data could not be unambiguously matched during a transfer or used as evidence in a complaint. Row permission and internal database address fields ($permissions, $databaseId, $collectionId) are removed from the export — these are technical details of the provider's infrastructure, not the client's data.
4.1 account (object, no system fields — account data, not a table row)
| Field | Type | Description |
|---|---|---|
userId |
string | The organizer's Appwrite account identifier. |
email |
string | The account's e-mail address. |
name |
string | The account's name. |
4.2 games — the organizer's game rows (studio_games table)
| Field | Type | Description |
|---|---|---|
ownerId |
string | The game owner's account identifier. |
name |
string | The game's name, set in the panel. |
status |
string (optional) | The game's status in the panel. |
pointsJson |
text (nested JSON as a string) | The list of game points exactly as entered by the organizer in the builder — see 7.1. |
settingsJson |
text (nested JSON as a string) | Game settings (description, city, duration, organizer data, pre-publication acknowledgements, stages) — see 7.2. |
publishedCampaignId |
string (optional) | A reference to the published configuration, written by the organizer; in case of a mismatch, the campaignId in the campaigns section is authoritative, not this field. |
joinCode |
string (optional) | The join code as saved by the organizer. |
4.3 campaigns — published game configurations (campaigns table, addressed as studio-<game id>)
| Field | Type | Description |
|---|---|---|
campaignId |
string | The published game's identifier. |
active |
boolean | Whether the game is active. |
status |
string (optional) | Publication status. |
archivedAt |
ISO 8601 date (optional) | Archival timestamp, if archived. |
appName |
string | The publisher app's name ("Markerra"). |
clientName |
string | The organizer's name shown to players. |
radiusMeters |
float | The game zone's radius, in meters. |
targetLatitude, targetLongitude |
floats | The game zone's center/target coordinates — see the rules in section 2. |
rewardCodePrefix |
string | The reward code prefix. |
rewardLandingUrl |
string | The finale page address. |
markersJson |
text (nested JSON as a string) | The list of points issued to players — see 7.3. |
routeJson |
text (nested JSON as a string) | The game description issued to players (title, description, city, duration, notes, the game organizer's details, stages) — see 7.4. |
allowedCirclesJson |
text (nested JSON as a string, optional) | Allowed geographic circles for the game. |
organizerJson |
text (nested JSON as a string, optional) | Registration details of the platform operator (Markerra) — the same as in the public Markerra demo. These are not the game organizer's details (those are in routeJson.host, see 7.4 and 7.5) — see 7.6. |
participantRulesJson |
text (nested JSON as a string, optional) | The participation rules in force for this game (document version and minimum age). |
studioPaidUntil |
ISO 8601 date (optional) | The date until which publication is paid for. |
joinCode |
string (optional) | The join code certified by the server — authoritative in case of a mismatch with studio_games.joinCode. |
4.4 markers — points of published games (markers table)
| Field | Type | Description |
|---|---|---|
campaignId |
string | Reference to campaigns.campaignId. |
markerId |
string | The point's identifier. |
titlePl, titleEn |
strings | The point's name in both languages. |
legacyDatabaseKey |
string (optional) | A legacy key, if any. |
active |
boolean (optional) | Whether the point is active. |
Point secrets (QR/NFC token hashes from the marker_tokens table) are not included in the export — they are useless for a transfer, being one-way cryptographic hashes from which the physical marker cannot be reconstructed.
4.5 payments — the organizer's payments (studio_payments table, stripe* fields other than those listed below removed)
| Field | Type | Description |
|---|---|---|
gameId |
string | Reference to the game. |
ownerId |
string | The paying account's identifier. |
campaignId |
string | Reference to the published configuration. |
variant |
string | The pricing variant. |
amountTotal |
integer | The amount paid (in the smallest currency unit). |
currency |
string | The currency. |
status |
string | The payment's status. |
stripeSessionId |
string | The payment session identifier — the organizer's own data, needed to file a complaint with the payment provider. |
stripePaymentIntentId |
string (optional) | The transaction identifier — kept for the same reason as above. |
buyerEmail |
string (optional) | The buyer's e-mail. |
consentsJson |
text (nested JSON as a string) | The consents recorded at checkout (including the request that the paid period begin with the first successful publication after payment, before the withdrawal period ends, acknowledgement of how withdrawal during the publication period is settled and that the right of withdrawal expires once the service is fully performed, and the Terms version at the time of order). |
paidAt, expiresAt |
ISO 8601 dates | The moment of payment and the end of the paid period. |
firstPublishedAt |
ISO 8601 date (optional) | The moment the paid game was first actually launched. |
refundedTotal |
integer (optional) | The refunded amount. |
refundedAt |
ISO 8601 date (optional) | The moment of the refund. |
confirmationSentAt |
ISO 8601 date (optional) | The moment the durable-medium contract confirmation was sent. |
buyerType |
string (optional) | The buyer's type (consumer/business). |
buyerCountry |
string (optional) | The buyer's country code (two letters). |
amountTax |
integer (optional) | The tax amount included in the price. |
fxRateToPln |
float (optional) | The currency exchange rate applied. |
viesCheckJson |
text (nested JSON as a string, optional) | Evidence of the buyer's EU VAT number verification, where applicable. |
Internal payment-provider identifiers other than stripeSessionId and stripePaymentIntentId are removed from the export by a default-deny rule — any new field starting with stripe added to the table in the future drops out of the export by the mere fact that it is not on the allow-list, without any change to the export code being needed.
4.6 acceptances — rule acceptances the organizer made as a player (participant_rule_acceptances table)
| Field | Type | Description |
|---|---|---|
userId |
string | The accepting account's identifier (here: the organizer's). |
campaignId |
string | The game in which the acceptance was recorded. |
organizerId |
string | The identifier from the registration details the game provides with its participation rules. In Markerra Studio games it is the identifier of the platform operator (Markerra) — the same as in the public Markerra demo — so it does not identify the organizer of that game. |
documentKind |
string | The kind of document. Currently "studio-participant-rules" — the participation rules of a Markerra Studio game — or "organizer-participant-rules" — the participation rules of a game set up outside Studio, e.g. the public Markerra demo. |
documentVersion |
string | The document's version at the time of acceptance. |
language |
string | The document's language. |
documentSha256 |
string | The SHA-256 checksum of the accepted document's content — evidence that exactly this content was accepted. |
minimumAge |
integer | The minimum age required by this version of the rules. |
ageConfirmed |
boolean | Whether age was confirmed. |
ageBracket |
string (optional) | The age-confirmation path used. |
ageSource |
string (optional) | Where the age confirmation comes from: "birthDate" — age calculated from the date of birth entered in the app at sign-in or at this acceptance (the date itself is not stored), or "priorAcceptance" — age confirmed by an earlier acceptance on this account (found by the server itself). No value in acceptances made before this field was introduced or made in an older app version that does not send it. |
acceptedAt |
ISO 8601 date | The moment of acceptance. |
evidenceVersion |
integer | The version of the acceptance-evidence format. |
This section carries only the organizer's own acceptances, filtered by their userId — not their players' acceptances. It includes acceptances from every game played with this account: the organizer's own games, the public Markerra demo and other organizers' games. A row from another organizer's game carries that game's identifier (campaignId); in a Studio game its organizerId is the identifier of the platform operator (Markerra), the same as in the demo — it does not identify that game's organizer. The notes.acceptances field describes the same scope in the file itself (see 4.7). Player data (including user_markers, reward_claims, and other people's analytics events) is not included in the export, in any section: this is data for which Markerra, not the organizer, is the controller with respect to players, so the organizer has no entitlement to receive it through this export.
4.7 notes — section descriptions (object, no system fields — a description attached to the file, not a table row)
| Field | Type | Description |
|---|---|---|
acceptances |
object {pl, en} (strings) |
Description of the scope of the acceptances section in Polish (pl) and English (en). English wording: “Your acceptances of participation rules as a player — from every game played with this account, including the demo and other organizers’ games. The export does not include your players’ acceptances.” |
The notes field explains the file and carries no database data. It is an additional field: a reader that does not know it reads all other fields and sections unchanged, which is why the format identifier remains markerra-studio-export-1 (see section 6).
5. Technical limits (Article 26(a))
The response has a combined ceiling of 5,000 rows across all sections. Once exceeded, the response carries truncated: true instead of silently cutting data — the organizer is shown, in the panel, information about completing the export via the e-mail route described in §15 of the Terms. Call frequency is limited by the same rate limiter as game publication; on excess, the response carries a 429 status with a retry-after header.
6. Export format version history
| Format version | Since | Change |
|---|---|---|
markerra-studio-export-1 |
deployment of the studio-export action (DA-02) |
First version — the envelope and the six sections described in sections 3–4. |
markerra-studio-export-1 |
introduction of game stages in the panel (17.09.2026) | Backward-compatible addition: the gameplay fields in games[].settingsJson (see 7.2) and in campaigns[].routeJson (see 7.4) — game stage settings and layout. All other fields and sections are unchanged, so the version number did not change. Row added with the correction of 7.10.2026. |
markerra-studio-export-1 |
deployment of the notes field |
Backward-compatible addition: the notes field describing the acceptances section (see 4.7). All other fields and sections are unchanged, so the version number did not change. |
markerra-studio-export-1 |
introduction of the ageSource field (age confirmed once) |
Backward-compatible addition: the ageSource field in acceptances rows (see 4.6). All other fields and sections are unchanged, so the version number did not change. |
7. Nested structures
7.1 games[].pointsJson — game points as entered by the organizer in the builder
An array of point objects, as saved by the organizer, each with: pid (point identifier, string), title (name, up to 128 characters), type (how the point is completed: "gps", "qr", "nfc" or "code"), task (task description, up to 1024 characters, optional), lat/lng (coordinates, optional — required for type "gps", rules as in section 2), and token (for "qr"/"nfc") or code (for "code") — the point's secret as entered by the organizer. This is the raw working record from the game builder, not the contract issued to players (described in 7.3).
7.2 games[].settingsJson — game settings
An object with the fields: desc (game description, up to 1024 characters, optional), city (up to 120 characters, optional), time (estimated duration, up to 60 characters, optional), organizer (organizer data, structure as in 7.5), publishAck (evidence that the three acknowledgements required before publication were made: version, unmoderated, noThirdPartyData, lawfulAndSafe, at — an ISO 8601 timestamp), and gameplay (stage settings as saved by the panel).
The gameplay field is optional: null or no field means a game without stages. In a game with stages it is an object with the fields version (currently 1), order ("ordered" — stages in sequence, or "free" — in any order) and stages (an array of 1 to 25 stages in the order set in the panel, each with: id (stage identifier), title (stage name, up to 120 characters), kind ("points" or "area"), markerIds (identifiers of the stage's points — pid values from 7.1), requiredCount (for kind: "area" the number of points to find, or null — all points in the area; for kind: "points" always null) and, optionally, radiusMeters (the area radius in metres entered by the organizer, or null — fitted automatically; used only for kind: "area")). This is the raw working record from the panel (the server checks and converts it at publication) — the published form of the stages, with the computed search area, is described by routeJson.gameplay in 7.4.
7.3 campaigns[].markersJson — points issued to players
An array of objects: markerId (identifier), title (bilingual name, object {polish, english}), type (as in 7.1), task (task description), and optionally location: {latitude, longitude} for points with coordinates. This is the contract issued to the player app — derived from pointsJson, without the point's secrets (token/ code are not included here).
7.4 campaigns[].routeJson — game description issued to players
An object with bilingual fields ({polish, english} for each): title (game title), subtitle (description), city (location), difficulty, estimatedTime, rewardTitle, privacyNote (information on location use), safetyNote (safety information). In addition, host — the game organizer's details the game shows to players (structure in 7.5), and gameplay — the game's stages, optional, only in a game with stages: an object with the fields version (currently 1), order ("ordered" — stages in sequence, or "free" — in any order) and stages (an array of 1 to 25 stages, each with: id (stage identifier), title (stage name, up to 120 characters), kind ("points" or "area"), markerIds (identifiers of the stage's points, as markerId in 7.3), requiredCount (the number of points needed to complete the stage), and for kind: "area" additionally area: {center: {latitude, longitude}, radiusMeters} — the search area).
7.5 games[].settingsJson.organizer and campaigns[].routeJson.host — the game organizer's details
An object with the fields: kind ("person" or "company"), name (up to 80 characters), email (up to 120 characters), and for kind: "company" additionally legalName (full legal name, up to 160 characters), taxId (tax identification number, up to 40 characters) and address (up to 200 characters). settingsJson.organizer (as saved by the panel) also has confirmed (a boolean — the organizer's confirmation of responsibility for the game's content, rules and finale), and for kind: "person" the fields legalName, taxId and address may be empty. In routeJson.host (a copy made at publication) the email address is named contactEmail, there is no confirmed field, and the company fields appear only for kind: "company". These are the game organizer's details — not to be confused with organizerJson (see 7.6).
7.6 campaigns[].organizerJson — registration details of the platform operator
Registration details of the platform operator (Markerra) as the app provider, which the game provides to players with its participation rules. A Markerra Studio game receives them from the server as a copy of the public Markerra demo's details (at publication; the server may refresh them when a player joins), so they are the same in every Studio game and do not describe the game's organizer — the organizer's details are in routeJson.host (see 7.4 and 7.5). An object with the fields: organizerId (the operator's identifier — the same value goes into the organizerId field of acceptances, see 4.6), legalName (legal name), registeredAddress (registered address), registration (an object with the fields nip — tax identification number (NIP), 10 digits — and regon — statistical number (REGON), 9 digits), supportEmail (contact address), complaintsEmail (complaints address) and privacyUrls (an object with the fields polish and english — HTTPS addresses of the Privacy policy).