Properties
| Name | Type | Description |
|---|---|---|
| view | string | The view actually served: 'mine', 'team' or 'organisation'. An unrecognised view is REFUSED with 403, not silently narrowed -- available_views says which are allowed. Clients should still label what t |
| available_views | array | Which views this reader may ask for, in order: always 'mine'; 'team' for a team lead or anyone with global user:read; 'organisation' for global user:read. The client offers exactly these -- it has no |
| available_groupings | array | Which groupings the utilisation card may be asked for: 'team', 'person', or both. Empty on 'mine', which lists neither. 'team' is offered wherever the reader may see more than one team, and on a team |
| grouping | nullstring | The grouping actually in force, or null where the view lists neither. Exactly one of `consultants` and `teams` is present, matching this. |
| period | object | |
| people | integer | How many people are in scope for this view |
| people_logged | integer | How many of them logged anything. Without it a dormant-seat account reports a near-zero utilisation and the reader cannot tell non-adoption from under-selling. |
| logged_minutes | integer | Total minutes logged. Minutes throughout, matching how every reporting total is computed; the client formats them. |
| billable_minutes | integer | Of those, the billable share |
| non_billable_minutes | integer | Of those, the non-billable share |
| capacity_minutes | integer | Available minutes across the people in scope |
| all_logged_minutes | integer | Every minute logged in the view before any filter (TT-6648). Equal to logged_minutes when nothing is filtered; the difference is the time the filters leave out. |
| filters | object | |
| entry_count | integer | Number of logged hour entries |
| utilisation_percent | nullnumber | The headline figure: the metric's numerator over capacity. Null — not zero — when there is no capacity configured (utilisation is then undefined) or when no metric could be chosen for a window with no |
| target_percent | integer | The target to read these figures against. A stored target always wins; without one the default follows the metric (75% billable utilisation, 95% logged against capacity), because the two are not inter |
| metric | nullstring | Which headline figure this account is read on: 'billable_utilisation' (billable over capacity — "how much of what we could sell, did we sell?") or 'logged_capacity' (all logged time over capacity — "h |
| metric_auto_selected | boolean | True when the metric was detected from the data, false when an admin pinned it. An explicit choice is never re-derived, so an account whose data drifts is not moved off the metric it chose. |
| metric_evidence | nullnumber | The share of logged time that was billable, as a percentage — what detection was made on. Sent even when the metric is pinned, so an admin revisiting the setting can see whether their choice still fit |
| timed_out | boolean | True when a live query exceeded the statement timeout. Every figure is then a zero that means nothing, and the breakdown fields below are omitted entirely rather than sent empty. |
| as_of | nullstring | When these figures were computed (ISO 8601), taken from the OLDEST rollup row in the window -- a window is only as fresh as its stalest row, so reporting the newest would describe a month by whichever |
| settled_days_recomputed | integer | How many days in this window were already invoiced or locked and still had to be corrected by the nightly recompute -- that is, a reported month that no longer sums to what was billed. Zero for any re |
| show_names | boolean | The ACCOUNT's naming setting, reported on every view -- including 'mine', which names nobody but whose settings cog still offers the control to an admin. When false the server has already stripped use |
| settings_editable | boolean | Whether this reader may change the naming setting — admins only. The write endpoint refuses it regardless, so this only decides whether the control is offered. |
| minimum_team_size | integer | The ACCOUNT's group-size floor: the smallest team the team rows show. Reported on every view so an admin's settings cog can render it. Defaults to 5; an admin sets it within 2..50 through PUT insights |
| consultants | array | Per-person utilisation. Present exactly when `grouping` is 'person' -- which includes an admin who asked for it on the organisation or team view, not only a team lead reading their own team. Absent (n |
| teams | array | Per-team utilisation. Present exactly when `grouping` is 'team', which is the default wherever the reader may see more than one team -- a company of 200 listed per person would be 200 named individual |
| team_membership | string | Present with `teams`. 'period': each team row counts the people who were on that team during this window, day by day -- someone who moved teams mid-window counts on each for the days they were on it. |
| suppressed_teams | integer | How many team rows the minimum-group-size floor withheld, read against `minimum_team_size` (5 people unless the account set it). It counts teams the floor REMOVED, never rows a client has not drawn ye |
| by_tag | object | |
| by_project | object | |
| client_scope | string | Which slice the client rows cover: 'all', 'billable' or 'non_billable'. Independent of the other two tables' scopes. |
| clients | array | Where the time went by client. Organisation view only; empty otherwise. |
| engagements | object | |
| captured | object |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://raw.githubusercontent.com/api-evangelist/timely/main/json-schema/timely-v1-insights-response-schema.json",
"title": "V1.InsightsResponse",
"x-generated": "2026-10-27",
"x-method": "derived",
"x-generator": "derive-json-schema.py",
"x-source": "openapi/timely-openapi.json#/components/schemas/V1.InsightsResponse",
"type": "object",
"properties": {
"view": {
"type": "string",
"description": "The view actually served: 'mine', 'team' or 'organisation'. An unrecognised view is REFUSED with 403, not silently narrowed -- available_views says which are allowed. Clients should still label what they drew from THIS field rather than from what they asked for."
},
"available_views": {
"type": "array",
"description": "Which views this reader may ask for, in order: always 'mine'; 'team' for a team lead or anyone with global user:read; 'organisation' for global user:read. The client offers exactly these -- it has no signal of its own for \"leads a team\" -- and the server refuses anything else regardless.",
"items": {
"type": "string"
}
},
"available_groupings": {
"type": "array",
"description": "Which groupings the utilisation card may be asked for: 'team', 'person', or both. Empty on 'mine', which lists neither. 'team' is offered wherever the reader may see more than one team, and on a team lead's OWN team -- a team aggregate names nobody. It is also the DEFAULT on every view that lists anything, so My team and Organisation open on the same card; the two differ in the rows, not in the shape. 'person' is offered on My team only where the account names individuals: with naming off the rows are WITHHELD, not anonymised, so there is one grouping and nothing to switch between. The one exception is a reader who leads no team and may see nobody, whose My team is their own hours and has no team to group by. Read `show_names`, NOT the presence of 'person', to know whether rows carry names. The server narrows a grouping it did not offer rather than serving it.",
"items": {
"type": "string"
}
},
"grouping": {
"type": [
"null",
"string"
],
"description": "The grouping actually in force, or null where the view lists neither. Exactly one of `consultants` and `teams` is present, matching this."
},
"period": {
"type": "object",
"properties": {
"from": {
"type": "string",
"description": "ISO8601 start date (inclusive)"
},
"to": {
"type": "string",
"description": "ISO8601 end date (inclusive)"
}
},
"required": [
"from",
"to"
]
},
"people": {
"type": "integer",
"description": "How many people are in scope for this view",
"minimum": 0
},
"people_logged": {
"type": "integer",
"description": "How many of them logged anything. Without it a dormant-seat account reports a near-zero utilisation and the reader cannot tell non-adoption from under-selling.",
"minimum": 0
},
"logged_minutes": {
"type": "integer",
"description": "Total minutes logged. Minutes throughout, matching how every reporting total is computed; the client formats them.",
"minimum": 0
},
"billable_minutes": {
"type": "integer",
"description": "Of those, the billable share",
"minimum": 0
},
"non_billable_minutes": {
"type": "integer",
"description": "Of those, the non-billable share",
"minimum": 0
},
"capacity_minutes": {
"type": "integer",
"description": "Available minutes across the people in scope",
"minimum": 0
},
"all_logged_minutes": {
"type": "integer",
"description": "Every minute logged in the view before any filter (TT-6648). Equal to logged_minutes when nothing is filtered; the difference is the time the filters leave out.",
"minimum": 0
},
"filters": {
"type": "object",
"properties": {
"labels": {
"type": [
"null",
"object"
],
"description": "The tag filter applied: {only: [ids]} or {except: [ids]}, label id 0 being Untagged. Null when every tag is shown. Reaches every figure, utilisation included. An entry carrying a hidden tag is left out whole."
},
"projects": {
"type": [
"null",
"object"
],
"description": "The project filter applied: {only: [ids]} or {except: [ids]}. Null when every project is shown. Reaches the hours figures and the breakdowns, never utilisation: capacity belongs to a person, not a project."
},
"project_group": {
"type": [
"null",
"string"
],
"description": "'active' or 'archived' when the project filter is a group, with `projects.except` carving projects out of it. Null otherwise."
},
"clients": {
"type": [
"null",
"object"
],
"description": "The client filter applied, shaped like `projects` and reaching the same figures."
},
"hidden_capacity": {
"type": "string",
"description": "'keep' (the default) when capacity stays whole and time hidden by the tag filter reads as capacity nobody logged against, 'reduce' when that time also comes out of capacity."
}
},
"required": [
"labels",
"projects",
"project_group",
"clients",
"hidden_capacity"
]
},
"entry_count": {
"type": "integer",
"description": "Number of logged hour entries",
"minimum": 0
},
"utilisation_percent": {
"type": [
"null",
"number"
],
"description": "The headline figure: the metric's numerator over capacity. Null — not zero — when there is no capacity configured (utilisation is then undefined) or when no metric could be chosen for a window with no logged time."
},
"target_percent": {
"type": "integer",
"description": "The target to read these figures against. A stored target always wins; without one the default follows the metric (75% billable utilisation, 95% logged against capacity), because the two are not interchangeable."
},
"metric": {
"type": [
"null",
"string"
],
"description": "Which headline figure this account is read on: 'billable_utilisation' (billable over capacity — \"how much of what we could sell, did we sell?\") or 'logged_capacity' (all logged time over capacity — \"how much of people's time are we capturing?\"). Null when the window holds no logged time: a new or empty account has no billable minutes because it has no data, not because it does not bill, so no metric is adopted rather than guessed. Capacity is the denominator in both; only the numerator moves, and the per-person and per-team rows use the same one."
},
"metric_auto_selected": {
"type": "boolean",
"description": "True when the metric was detected from the data, false when an admin pinned it. An explicit choice is never re-derived, so an account whose data drifts is not moved off the metric it chose."
},
"metric_evidence": {
"type": [
"null",
"number"
],
"description": "The share of logged time that was billable, as a percentage — what detection was made on. Sent even when the metric is pinned, so an admin revisiting the setting can see whether their choice still fits. Null when nothing was logged."
},
"timed_out": {
"type": "boolean",
"description": "True when a live query exceeded the statement timeout. Every figure is then a zero that means nothing, and the breakdown fields below are omitted entirely rather than sent empty."
},
"as_of": {
"type": [
"null",
"string"
],
"description": "When these figures were computed (ISO 8601), taken from the OLDEST rollup row in the window -- a window is only as fresh as its stalest row, so reporting the newest would describe a month by whichever day the nightly job happened to touch last. Null means they were computed LIVE from `hours` on this request rather than read from the nightly rollup, which is the case until the read path moves onto the rollup; the page then says \"live\" rather than printing a timestamp that only means \"just now\"."
},
"settled_days_recomputed": {
"type": "integer",
"description": "How many days in this window were already invoiced or locked and still had to be corrected by the nightly recompute -- that is, a reported month that no longer sums to what was billed. Zero for any reader who is not an admin, because it exists for whoever reconciles invoices. Zero is the healthy state: the readiness panel is an exception report and says nothing at zero.",
"minimum": 0
},
"show_names": {
"type": "boolean",
"description": "The ACCOUNT's naming setting, reported on every view -- including 'mine', which names nobody but whose settings cog still offers the control to an admin. When false the server has already stripped user_id and name from any consultant rows, so a client cannot reveal them by ignoring this."
},
"settings_editable": {
"type": "boolean",
"description": "Whether this reader may change the naming setting — admins only. The write endpoint refuses it regardless, so this only decides whether the control is offered."
},
"minimum_team_size": {
"type": "integer",
"description": "The ACCOUNT's group-size floor: the smallest team the team rows show. Reported on every view so an admin's settings cog can render it. Defaults to 5; an admin sets it within 2..50 through PUT insights/settings."
},
"consultants": {
"type": "array",
"description": "Per-person utilisation. Present exactly when `grouping` is 'person' -- which includes an admin who asked for it on the organisation or team view, not only a team lead reading their own team. Absent (not empty) otherwise, so a client can tell \"this view lists teams\" from \"this view lists nobody\". Exactly one of `consultants` and `teams` is ever present; `available_groupings` says which may be asked for. Names are stripped server-side when the account has not opted in, so these rows can be anonymous.",
"items": {
"type": "object",
"properties": {
"user_id": {
"type": "integer"
},
"name": {
"type": "string"
},
"logged_minutes": {
"type": "integer",
"minimum": 0
},
"non_billable_minutes": {
"type": "integer",
"minimum": 0
},
"overtime_minutes": {
"type": "integer",
"minimum": 0
},
"missing_minutes": {
"type": "integer",
"minimum": 0
},
"billable_minutes": {
"type": "integer",
"minimum": 0
},
"capacity_minutes": {
"type": "integer",
"minimum": 0
},
"utilisation_percent": {
"type": [
"null",
"number"
]
}
},
"required": [
"logged_minutes",
"non_billable_minutes",
"overtime_minutes",
"missing_minutes",
"billable_minutes",
"capacity_minutes",
"utilisation_percent"
]
}
},
"teams": {
"type": "array",
"description": "Per-team utilisation. Present exactly when `grouping` is 'team', which is the default wherever the reader may see more than one team -- a company of 200 listed per person would be 200 named individuals. Absent (not empty) otherwise. Exactly one of `consultants` and `teams` is ever present.",
"items": {
"type": "object",
"properties": {
"id": {
"type": [
"null",
"integer"
]
},
"name": {
"type": "string"
},
"people": {
"type": "integer",
"minimum": 0
},
"logged_minutes": {
"type": "integer",
"minimum": 0
},
"non_billable_minutes": {
"type": "integer",
"minimum": 0
},
"overtime_minutes": {
"type": "integer",
"minimum": 0
},
"missing_minutes": {
"type": "integer",
"minimum": 0
},
"billable_minutes": {
"type": "integer",
"minimum": 0
},
"capacity_minutes": {
"type": "integer",
"minimum": 0
},
"utilisation_percent": {
"type": [
"null",
"number"
]
},
"trend_pp": {
"type": [
"null",
"number"
]
}
},
"required": [
"id",
"name",
"people",
"logged_minutes",
"non_billable_minutes",
"overtime_minutes",
"missing_minutes",
"billable_minutes",
"capacity_minutes",
"utilisation_percent",
"trend_pp"
]
}
},
"team_membership": {
"type": "string",
"description": "Present with `teams`. 'period': each team row counts the people who were on that team during this window, day by day -- someone who moved teams mid-window counts on each for the days they were on it. 'current': the rows count TODAY's members across the whole window, because the window starts before membership history was recorded (16 June 2026). A client comparing two windows should say so when either is 'current'."
},
"suppressed_teams": {
"type": "integer",
"description": "How many team rows the minimum-group-size floor withheld, read against `minimum_team_size` (5 people unless the account set it). It counts teams the floor REMOVED, never rows a client has not drawn yet. It is lifted only for a team lead reading a team they lead. A setting about naming PEOPLE must not change which teams appear. The figures above the breakdown still include everybody, so a withheld row makes the breakdown incomplete, not the page wrong.",
"minimum": 0
},
"by_tag": {
"type": "object",
"properties": {
"scope": {
"type": "string",
"description": "Which slice these rows cover: 'all', 'billable' or 'non_billable'. Narrows the rows only — the totals above stay whole. Independent of the project table's scope."
},
"overlaps": {
"type": "boolean",
"description": "True when an entry carries more than one tag. Each tag then receives the entry's FULL minutes, so the rows add to MORE than the logged total and must NOT be drawn as a partition."
},
"coverage_thin": {
"type": "boolean",
"description": "True when little non-billable time carries a tag, so this table is mostly \"Untagged\". The table is still drawn — the page explains it rather than hiding it."
},
"rows": {
"type": "array",
"description": "Where the time went, by tag, including an explicit \"Untagged\" row",
"items": {
"type": "object",
"properties": {
"id": {
"type": [
"null",
"integer"
]
},
"name": {
"type": "string"
},
"color": {
"type": [
"null",
"string"
]
},
"minutes": {
"type": "integer",
"minimum": 0
},
"billable_minutes": {
"type": "integer",
"minimum": 0
},
"parent_only": {
"type": "boolean"
},
"non_billable_minutes": {
"type": "integer",
"minimum": 0
}
},
"required": [
"id",
"name",
"color",
"minutes",
"billable_minutes",
"non_billable_minutes"
]
}
}
},
"required": [
"scope",
"overlaps",
"coverage_thin",
"rows"
]
},
"by_project": {
"type": "object",
"properties": {
"scope": {
"type": "string",
"description": "Which slice these rows cover: 'all', 'billable' or 'non_billable'. Independent of the tag table's scope."
},
"rows": {
"type": "array",
"description": "Where the time went, by project. Never empty where any time was logged — hours.project_id is NOT NULL.",
"items": {
"type": "object",
"properties": {
"id": {
"type": [
"null",
"integer"
]
},
"name": {
"type": "string"
},
"color": {
"type": [
"null",
"string"
]
},
"minutes": {
"type": "integer",
"minimum": 0
},
"billable_minutes": {
"type": "integer",
"minimum": 0
},
"parent_only": {
"type": "boolean"
},
"non_billable_minutes": {
"type": "integer",
"minimum": 0
}
},
"required": [
"id",
"name",
"color",
"minutes",
"billable_minutes",
"non_billable_minutes"
]
}
}
},
"required": [
"scope",
"rows"
]
},
"client_scope": {
"type": "string",
"description": "Which slice the client rows cover: 'all', 'billable' or 'non_billable'. Independent of the other two tables' scopes."
},
"clients": {
"type": "array",
"description": "Where the time went by client. Organisation view only; empty otherwise.",
"items": {
"type": "object",
"properties": {
"id": {
"type": [
"null",
"integer"
]
},
"name": {
"type": "string"
},
"color": {
"type": [
"null",
"string"
]
},
"minutes": {
"type": "integer",
"minimum": 0
},
"billable_minutes": {
"type": "integer",
"minimum": 0
},
"parent_only": {
"type": "boolean"
},
"non_billable_minutes": {
"type": "integer",
"minimum": 0
}
},
"required": [
"id",
"name",
"color",
"minutes",
"billable_minutes",
"non_billable_minutes"
]
}
},
"engagements": {
"type": "object",
"properties": {
"available": {
"type": "boolean",
"description": "False when profit cannot be computed for this account and reader"
},
"unavailable_reason": {
"type": [
"null",
"string"
],
"description": "Why, when it cannot: 'internal_costs_disabled', 'multiple_currencies' or 'rates_hidden'. Zeroes are never sent instead, because on screen they read as 'every engagement broke even'."
},
"clients": {
"type": "array",
"description": "Engagement profitability, one row per engagement subtotalled by client. Empty when unavailable.",
"items": {
"type": "object",
"properties": {
"id": {
"type": [
"null",
"integer"
]
},
"name": {
"type": [
"null",
"string"
]
},
"color": {
"type": [
"null",
"string"
]
},
"includes_contract_value": {
"type": "boolean"
},
"engagements": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"name": {
"type": "string"
},
"color": {
"type": [
"null",
"string"
]
},
"rate_type": {
"type": "string"
},
"fixed_price": {
"type": "boolean"
},
"revenue_apportioned": {
"type": "boolean"
},
"revenue_basis": {
"type": "string"
},
"budget": {
"type": [
"null",
"object"
]
},
"logged_minutes": {
"type": "integer",
"minimum": 0
},
"billable_minutes": {
"type": "integer",
"minimum": 0
},
"non_billable_minutes": {
"type": "integer",
"minimum": 0
},
"revenue": {
"type": "object",
"properties": {
"fractional": {
"type": "integer"
},
"formatted": {
"type": "string",
"minLength": 1
},
"amount": {
"type": "number"
},
"currency_code": {
"type": "string",
"minLength": 1
}
},
"required": [
"fractional",
"formatted",
"amount",
"currency_code"
]
},
"internal_cost": {
"type": "object",
"properties": {
"fractional": {
"type": "integer"
},
"formatted": {
"type": "string",
"minLength": 1
},
"amount": {
"type": "number"
},
"currency_code": {
"type": "string",
"minLength": 1
}
},
"required": [
"fractional",
"formatted",
"amount",
"currency_code"
]
},
"profit": {
"type": "object",
"properties": {
"fractional": {
"type": "integer"
},
"formatted": {
"type": "string",
"minLength": 1
},
"amount": {
"type": "number"
},
"currency_code": {
"type": "string",
"minLength": 1
}
},
"required": [
"fractional",
"formatted",
"amount",
"currency_code"
]
},
"profitability": {
"type": "number"
}
},
"required": [
"id",
"name",
"color",
"rate_type",
"fixed_price",
"revenue_apportioned",
"revenue_basis",
"logged_minutes",
"billable_minutes",
"non_billable_minutes",
"revenue",
"internal_cost",
"profit",
"profitability"
]
}
},
"logged_minutes": {
"type": "integer",
"minimum": 0
},
"billable_minutes": {
"type": "integer",
"minimum": 0
},
"non_billable_minutes": {
"type": "integer",
"minimum": 0
},
"revenue": {
"type": "object",
"properties": {
"fractional": {
"type": "integer"
},
"formatted": {
"type": "string",
"minLength": 1
},
"amount": {
"type": "number"
},
"currency_code": {
"type": "string",
"minLength": 1
}
},
"required": [
"fractional",
"formatted",
"amount",
"currency_code"
]
},
"internal_cost": {
"type": "object",
"properties": {
"fractional": {
"type": "integer"
},
"formatted": {
"type": "string",
"minLength": 1
},
"amount": {
"type": "number"
},
"currency_code": {
"type": "string",
"minLength": 1
}
},
"required": [
"fractional",
"formatted",
"amount",
"currency_code"
]
},
"profit": {
"type": "object",
"properties": {
"fractional": {
"type": "integer"
},
"formatted": {
"type": "string",
"minLength": 1
},
"amount": {
"type": "number"
},
"currency_code": {
"type": "string",
"minLength": 1
}
},
"required": [
"fractional",
"formatted",
"amount",
"currency_code"
]
},
"profitability": {
"type": "number"
}
},
"required": [
"id",
"name",
"color",
"includes_contract_value",
"engagements",
"logged_minutes",
"billable_minutes",
"non_billable_minutes",
"revenue",
"internal_cost",
"profit",
"profitability"
]
}
}
},
"required": [
"available",
"unavailable_reason",
"clients"
]
},
"captured": {
"type": "object",
"properties": {
"captured_minutes": {
"type": "integer",
"description": "Minutes Memory captured on the reader's own machine in the window, as the UNION of the captured intervals -- a meeting that is both a calendar entry and the video app counts once. Compare against `logged_minutes`. The gap is not missing work: breaks, calls and away-from-desk time sit in it too.",
"minimum": 0
},
"tools": {
"type": "array",
"description": "The largest tools, most time first, capped at six",
"items": {
"type": "object"
}
},
"other_minutes": {
"type": "integer",
"description": "The sum of every tool past the cap, drawn as one remainder slice",
"minimum": 0
},
"other_count": {
"type": "integer",
"description": "How many tools other_minutes collects",
"minimum": 0
},
"other_tools": {
"type": "array",
"description": "The tools other_minutes collects, most time first, capped at twenty. other_count says how many there are in all.",
"items": {
"type": "object"
}
}
},
"required": [
"captured_minutes",
"tools",
"other_minutes",
"other_count",
"other_tools"
]
}
},
"required": [
"view",
"available_views",
"available_groupings",
"grouping",
"period",
"people",
"people_logged",
"logged_minutes",
"billable_minutes",
"non_billable_minutes",
"capacity_minutes",
"all_logged_minutes",
"filters",
"entry_count",
"utilisation_percent",
"target_percent",
"metric",
"metric_auto_selected",
"metric_evidence",
"timed_out",
"as_of",
"settled_days_recomputed"
]
}
Work with this as data
Every JSON Schema here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for schemas
4 MCP tools reach this
find_json_schemasBrowse and filter every JSON Schema in the catalog.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.
Call it yourself
curl for this page
This JSON Schema
curl "https://apis.io/api/v1/json-schemas/timely-v1-insights-response"
All schemas
curl "https://apis.io/api/v1/json-schemas?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.