{"openapi":"3.1.0","info":{"title":"Telgea API","version":"1.0.0","description":"The Telgea Open API provides comprehensive programmatic access to manage users, phone numbers, plans, and telecommunication resources within your organization. Built for developers who need reliable, scalable telecommunications infrastructure.\n\nThe API follows REST conventions: resources are addressed by URL, actions are expressed through HTTP\nmethods, and all request and response bodies are JSON. Every endpoint is versioned under `/v1`.\n\n## Authentication\n\nAll requests must carry an API key in the `x-api-key` header:\n\n```\nx-api-key: <your_api_key>\n```\n\n## Idempotency\n\nEvery request that changes state (`POST`, `PATCH`, `DELETE`) accepts an optional\n`Idempotency-Key` header:\n\n```\nIdempotency-Key: <a UUID you generate per request>\n```\n\nSend a value unique to the request — a UUID is the usual choice — of 1 to 255 printable ASCII characters.\nIf the connection drops before the response reaches you, send the request again with the same key:\nrather than creating a second resource or failing with a conflict, the API returns the original\nresponse, so a retry is always safe.\n\nA key identifies **one request to one endpoint**, and is remembered for **24 hours**. Within that\nwindow the same key replays the original outcome *whatever it was* — including a failure, which is\nnot re-attempted. So change the key, not just the body, whenever you mean to send a new request:\nreusing one after correcting a rejected payload returns the rejection, not the corrected result. The\nsame key on a different endpoint is simply a different request, and keys are private to your API key\nand organisation, so your numbering can never collide with another customer's.\n\nThe header is ignored on `GET`, and a malformed one is rejected with `400` before the request has\nany effect.\n\n## Core Capabilities\n\n| Resource | What you can do |\n|---|---|\n| **Users** | Create employees in your organization |\n| **Teams** | Group users for billing and access control |\n| **User Plans** | Provision SIM cards, assign local and travel numbers, terminate plans |\n| **Port-Ins** | Port phone numbers in from other network operators, validate porting data, track status |\n| **Billing Entities** | Define billing units, attach tax information, assign teams |\n| **Usage** | Retrieve raw call, SMS, and data records to bill on |\n| **Analytics** | Query aggregated voice, SMS, and data consumption with date-range filters |\n\n## Security & Compliance\n\n**Transport security** — All traffic is encrypted in transit over TLS 1.2+. Plain HTTP requests are\nnot accepted.\n\n**Credential isolation** — API keys are organization-scoped. A key issued by organization A cannot\nread or modify data belonging to organization B under any circumstances.\n\n**Data residency** — Data is stored and processed in the EU. Telgea is GDPR-compliant. Personal data\n(names, email addresses, phone numbers) is handled in accordance with Telgea's Data Processing\nAgreement, available on request.\n\n**Rate limits** — Each API key allows 1000 requests per 24 hours, shared across every endpoint.\nRequests beyond the budget return `429`. When polling usage, page through an organisation with the\ndefault page size rather than issuing one request per subscriber.\n\n## Errors\n\nEvery error is an [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) Problem Details body, served as\n`application/problem+json`. Its members sit at the top level:\n\n```json\n{\n  \"type\": \"https://developer.telgea.com/errors/http/UNAUTHORIZED\",\n  \"title\": \"Unauthorized\",\n  \"status\": 401,\n  \"detail\": \"This request could not be authenticated.\",\n  \"code\": \"UNAUTHORIZED\",\n  \"requestId\": \"20bc8767-c7a1-48a3-a1cc-6e7a02573935\"\n}\n```\n\nBranch on `code` or `type`, never on `detail`. `type` opens a page explaining the error, and\n`requestId` identifies the request to support. Some errors add `camelCase` extension members,\nsuch as `fields` on a validation error; each operation's error schema lists the ones it can carry.\nThe [error guide](https://developer.telgea.com/docs/guides#error-handling) lists every code.\n\n| HTTP status | Meaning |\n|---|---|\n| `400` | Request body or query parameters failed validation, or the request was refused as sent |\n| `401` | Missing or invalid API key |\n| `403` | Insufficient permissions, revoked organization access, or a country not enabled for your organization |\n| `404` | Resource not found |\n| `405` | Method not allowed on this path |\n| `409` | The request conflicts with the current state of a resource |\n| `422` | The request was understood but cannot be processed with these values |\n| `429` | Rate limit exceeded — back off and retry after the indicated time |\n| `500` | Unexpected server error |\n| `503` | A system the request depends on is temporarily unavailable — safe to retry with backoff |\n\n## Versioning\n\nThe current stable version is **v1**. Breaking changes will be introduced under a new version prefix\n(`/v2`, etc.) and announced with a deprecation window. Non-breaking additions (new fields, new\nendpoints) may be made to existing versions without notice."},"servers":[{"url":"https://api.telgea.com","description":"Production"}],"security":[{"ApiKeyAuth":[]}],"tags":[{"name":"Users","description":"Manage employees and contractors in your organization."},{"name":"Teams","description":"Group users for billing, access control, and reporting."},{"name":"User Plans","description":"Provision SIM cards, phone numbers, and data plans for users."},{"name":"Numbers","description":"The lines you sell: obtain one, look it up, replace its SIM, stop it and end it."},{"name":"Port-Ins","description":"Port phone numbers from other providers into Telgea."},{"name":"Usage","description":"Retrieve raw voice, SMS, and data usage records for billing and suspension."},{"name":"Analytics","description":"Aggregated voice, SMS, and data consumption for reporting and dashboards."},{"name":"Data Pools","description":"Track the shared data pool your numbers draw on."},{"name":"Rates","description":"Look up pay-as-you-go retail rates for calling, messaging, and roaming data."},{"name":"Cost Thresholds","description":"What people may spend per month on a usage type, such as international calls, before it is paused."}],"x-telgea-problem-types":[{"type":"https://developer.telgea.com/errors/hub/USER_NOT_FOUND","status":404,"code":"NOT_FOUND","title":"User not found","detail":"No matching user exists in your organization.","occursWhen":"A request names a user that your organization does not have.","resolution":"Check the userId or email you sent. GET /v1/users lists the users in your organization.","members":{}},{"type":"https://developer.telgea.com/errors/hub/USER_ALREADY_EXISTS_WITH_EMAIL","status":409,"code":"CONFLICT","title":"Email address not available","detail":"This email address is not available for a new user.","occursWhen":"A user is created, or an email is changed, to an address another user already holds.","resolution":"Look the address up with GET /v1/users?email=, or send a different address.","members":{}},{"type":"https://developer.telgea.com/errors/hub/DEFAULT_TEAM_IMMUTABLE","status":409,"code":"CONFLICT","title":"Default team cannot be changed","detail":"This is your organization's default team, Unassigned, so it cannot be changed.","occursWhen":"A request renames or otherwise updates the default team, the team every user in no other team belongs to. GET /v1/teams marks it with `isDefault`.","resolution":"Leave the default team out of the request. To move a user out of it, assign them to another team with PATCH /v1/users/{userId}.","members":{}},{"type":"https://developer.telgea.com/errors/hub/MARKET_NOT_SERVICEABLE","status":403,"code":"COUNTRY_NOT_SUPPORTED","title":"Market not served","detail":"This market is not served, so no rates are available for it.","occursWhen":"Rates are requested for a market that has no coverage.","resolution":"Check the market code against a supported ISO 3166-1 alpha-2 country, or contact support about coverage.","members":{}},{"type":"https://developer.telgea.com/errors/hub/ORGANIZATION_VERIFICATION_REQUIRED","status":403,"code":"COUNTRY_NOT_SUPPORTED","title":"Business verification required","detail":"Your organization has not passed the business verification this country requires, so no plan or port-in was created.","occursWhen":"A plan or port-in is created in a country that requires business verification, before your organization has passed it.","resolution":"Contact support and quote requestId to have your organization verified. Once it has passed, send the request again.","members":{"countryCode":{"type":"string","description":"The country the plan or port-in was for, as an ISO 3166-1 alpha-2 code.","examples":["MX"]}}},{"type":"https://developer.telgea.com/errors/number-service/MSISDN_HELD_BY_TELGEA","status":409,"code":"CONFLICT","title":"Number already with Telgea","detail":"This number is already with Telgea, so no port-in was created.","occursWhen":"A port-in is submitted for a number that is already served by Telgea.","resolution":"Check that the msisdn is the number you meant to port in; a number Telgea already serves cannot be ported in. If you expected it to be free, quote requestId to support.","members":{}},{"type":"https://developer.telgea.com/errors/hub/PORT_IN_ALREADY_IN_PROGRESS","status":409,"code":"CONFLICT","title":"Port-in already in progress","detail":"A port-in for this number is already in flight, so no second one was created.","occursWhen":"A port-in is submitted for a number while an earlier port-in for it has not finished.","resolution":"Wait for the earlier port-in to finish. If it failed, failure.reason on that port-in says why, and you can then submit again.","members":{}},{"type":"https://developer.telgea.com/errors/number-service/MSISDN_IN_TERMINATION_GRACE_PERIOD","status":409,"code":"CONFLICT","title":"Number in termination grace period","detail":"This number's plan ended recently, so no port-in was created.","occursWhen":"A port-in is submitted for a number whose plan ended recently.","resolution":"planEndedAt says when the plan ended. To keep the number with its user, quote requestId to support, who can restore the ended plan. Otherwise port in a different number.","members":{"planEndedAt":{"type":"string","description":"When the number's plan ended, as an ISO 8601 date-time in UTC.","examples":["2026-09-28T09:00:00.000Z"],"format":"date-time"}}},{"type":"https://developer.telgea.com/errors/number-service/NUMBER_OPERATION_NOT_SUPPORTED","status":400,"code":"BAD_REQUEST","title":"Operation not supported","detail":"This line's operator does not offer the change you asked for, so nothing was changed.","occursWhen":"A line is suspended, unsuspended or restored on an operator that does not offer it.","resolution":"Suspending a line, lifting a suspension and restoring an ended plan are not available on every operator. Ordering, porting, replacing a SIM and ending a plan are.","members":{}},{"type":"https://developer.telgea.com/errors/number-service/NUMBER_NOT_FOUND","status":404,"code":"NOT_FOUND","title":"Number not found","detail":"No line in your organization has this id.","occursWhen":"A request names a line that your organization does not hold.","resolution":"Check the numberId you sent. GET /v1/numbers lists the lines in your organization.","members":{}},{"type":"https://developer.telgea.com/errors/number-service/NUMBER_ALREADY_IN_STATE","status":409,"code":"CONFLICT","title":"Number already in state","detail":"This number is already in the state you asked for, so nothing was changed.","occursWhen":"A number is moved to the state it is already in, such as suspending a suspended line.","resolution":"state is the state the number is already in. Nothing was changed, so no retry is needed.","members":{"state":{"type":"string","enum":["PENDING","PORTING","PORTING_FAILED","PROVISIONING","READY","REPLACING","CHANGING","SUSPENDING","SUSPENDED","RESTORING","RECONFIGURING","DEACTIVATING","DEACTIVATED","PORTING_DISCARDED","PORTING_OUT","PORTED_OUT"],"description":"The state the number is already in, which is the state the request asked for.","examples":["SUSPENDED"]}}},{"type":"https://developer.telgea.com/errors/number-service/NUMBER_STATE_INVALID","status":400,"code":"BAD_REQUEST","title":"Number state invalid","detail":"This number is not in a state that allows this action.","occursWhen":"An action is requested on a number whose current state does not allow it.","resolution":"currentState is the state the number is in. Retry once the number is active.","members":{"currentState":{"anyOf":[{"type":"string","enum":["PENDING","PORTING","PORTING_FAILED","PROVISIONING","READY","REPLACING","CHANGING","SUSPENDING","SUSPENDED","RESTORING","RECONFIGURING","DEACTIVATING","DEACTIVATED","PORTING_DISCARDED","PORTING_OUT","PORTED_OUT"]},{"type":"null"}],"description":"The state the number is in, or null when it has no state yet.","examples":["PROVISIONING"]}}},{"type":"https://developer.telgea.com/errors/number-service/NUMBER_MISSING_SIM","status":400,"code":"BAD_REQUEST","title":"Number has no SIM","detail":"No SIM has been issued for this number yet.","occursWhen":"An action that needs a SIM is requested on a number before its SIM is issued.","resolution":"Retry once a SIM has been issued for this number.","members":{}},{"type":"https://developer.telgea.com/errors/number-service/NUMBER_MISSING_MSISDN","status":400,"code":"BAD_REQUEST","title":"Number has no phone number","detail":"This number has not been assigned a phone number yet.","occursWhen":"An action that needs a phone number is requested on a number before one is assigned.","resolution":"Retry once a phone number has been assigned to it.","members":{}},{"type":"https://developer.telgea.com/errors/number-service/CONNECTION_STATUS_FAILED","status":503,"code":"SERVICE_UNAVAILABLE","title":"Connection status unavailable","detail":"The network serving this line did not answer, so its connection status could not be read.","occursWhen":"A line's connection status is read and the network serving the line fails to answer.","resolution":"Retry in 5 minutes. A failed read is answered again for the rest of its 5-minute window, so retrying sooner can return this same answer.","members":{}},{"type":"https://developer.telgea.com/errors/number-service/PORT_IN_PLAN_STATE_INVALID","status":400,"code":"BAD_REQUEST","title":"Plan state does not allow a port-in","detail":"This user's plan is not in a state that allows a port-in, so no port-in was created.","occursWhen":"A port-in is requested for a user whose plan is not in one of the states a port-in accepts.","resolution":"currentState is the state the plan is in and requiredStates lists the states a port-in accepts.","members":{"currentState":{"type":"string","enum":["INACTIVE","PROVISIONING","PORTING","PORTING_FAILED","ACTIVE","TERMINATING","TERMINATING_WITH_DELETION"],"description":"The state the user's plan is in.","examples":["ACTIVE"]},"requiredStates":{"type":"array","items":{"type":"string","enum":["INACTIVE","PROVISIONING","PORTING","PORTING_FAILED","ACTIVE","TERMINATING","TERMINATING_WITH_DELETION"]},"description":"The plan states a port-in accepts.","examples":[["INACTIVE","PORTING"]]}}},{"type":"https://developer.telgea.com/errors/number-service/PORT_IN_NOT_FOUND","status":404,"code":"NOT_FOUND","title":"Port-in not found","detail":"No matching port-in exists in your organization.","occursWhen":"A port-in is requested by an id that does not exist in your organization.","resolution":"Check the port-in id, or list the port-ins of a number with GET /v1/port-ins/number/{numberId}.","members":{}},{"type":"https://developer.telgea.com/errors/number-service/PORT_IN_NOT_DISCARDABLE","status":400,"code":"BAD_REQUEST","title":"Port-in cannot be discarded","detail":"This port-in is not in a state that allows discarding it, so nothing was changed.","occursWhen":"A port-in is discarded before it was rejected or failed, or after a newer port-in for the same number took the number over.","resolution":"Only a REJECTED or FAILED port-in can be discarded, and not while a newer port-in for the same number is in flight or once one has succeeded. GET /v1/port-ins/number/{numberId} lists every port-in for the number.","members":{}},{"type":"https://developer.telgea.com/errors/order/TERMINATION_DATE_IN_PAST","status":400,"code":"BAD_REQUEST","title":"Termination date in the past","detail":"The termination date has already passed, so no termination was scheduled.","occursWhen":"A plan termination is scheduled for a date before today.","resolution":"Send today or a later date. A line that should stop immediately takes today.","members":{}},{"type":"https://developer.telgea.com/errors/order/USER_SUBSCRIPTION_NOT_FOUND","status":404,"code":"NOT_FOUND","title":"No plan to end","detail":"No plan to end exists for this user in your organization, so no termination was scheduled.","occursWhen":"A plan termination is requested for a user who has no plan in your organization.","resolution":"Check the userId in the path. If GET /v1/user-plans/{userId} shows this user with an active line, quote requestId to support, who can end it.","members":{}},{"type":"https://developer.telgea.com/errors/order/CATALOGUE_ENTRY_UNAVAILABLE","status":403,"code":"COUNTRY_NOT_SUPPORTED","title":"Country not available to your organization","detail":"Nothing your organization can buy covers this country, so no plan was created.","occursWhen":"A plan is created for a country your organization has no offering in.","resolution":"Check the country code against the countries enabled for your organization, or contact support to enable it.","members":{"countryCode":{"type":"string","description":"The country asked for, as an ISO 3166-1 alpha-2 code.","examples":["NO"]}}},{"type":"https://developer.telgea.com/errors/order/HOME_PLAN_ALREADY_ACTIVE","status":409,"code":"CONFLICT","title":"User already has a plan","detail":"This user already has an active plan, so no second plan was created.","occursWhen":"A plan is created for a user whose current plan has not ended.","resolution":"End the current plan first, or check the userId.","members":{}},{"type":"https://developer.telgea.com/errors/order/ORDER_COOLDOWN_ACTIVE","status":429,"code":"TOO_MANY_REQUESTS","title":"Too soon after the last one","detail":"The last one of these for this number finished too recently for another, so nothing was placed.","occursWhen":"A SIM replacement is requested inside the cooldown that follows the last replacement of the same number.","resolution":"Retry at or after the HTTP-date in the Retry-After header.","members":{}},{"type":"https://developer.telgea.com/errors/order/USAGE_THRESHOLD_TEAM_OUTSIDE_ORGANIZATION","status":404,"code":"NOT_FOUND","title":"Team not found","detail":"No team in your organization has this id, so nothing was read or changed.","occursWhen":"A cost threshold is listed, set or removed for a team id your organization does not hold.","resolution":"Check the teamId against GET /v1/teams.","members":{"teamId":{"type":"string","description":"The team named, as its UUID.","examples":["2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70"]}}},{"type":"https://developer.telgea.com/errors/order/USAGE_THRESHOLD_USER_OUTSIDE_ORGANIZATION","status":404,"code":"NOT_FOUND","title":"User not found","detail":"No user in your organization has this id, so nothing was read or changed.","occursWhen":"A cost threshold is listed, set, removed or read for a user id your organization does not hold.","resolution":"Check the userId against GET /v1/users.","members":{"userId":{"type":"string","description":"The user named, as their UUID.","examples":["9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01"]}}},{"type":"https://developer.telgea.com/errors/order/USAGE_THRESHOLD_COST_CENTER_MISSING","status":422,"code":"UNPROCESSABLE_ENTITY","title":"No currency for the threshold","detail":"No cost center names a currency for this scope, so the threshold has no money to be written in.","occursWhen":"A cost threshold is set for a team with no cost center while the organization has no primary one.","resolution":"Set a primary cost center for the organization, or one for the team, in the console's billing settings.","members":{"teamId":{"anyOf":[{"type":"string","description":"The team named, as its UUID.","examples":["2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70"]},{"type":"null"}],"description":"The team whose cost center names no currency, as its UUID; null when the organization itself has no primary cost center.","examples":["2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70"]}}},{"type":"https://developer.telgea.com/errors/order/USAGE_THRESHOLD_CURRENCY_NOT_QUOTED","status":422,"code":"UNPROCESSABLE_ENTITY","title":"Currency not convertible","detail":"The cost-center currency is one no exchange rate covers, so spend could never be compared with a threshold in it.","occursWhen":"A cost threshold is set for a scope whose cost center bills in a currency the European Central Bank does not quote.","resolution":"Bill the cost center in a quoted currency, or contact support.","members":{"currency":{"type":"string","description":"The cost-center currency no exchange rate covers, as an ISO 4217 code.","examples":["XAU"]}}},{"type":"https://developer.telgea.com/errors/order/USAGE_THRESHOLD_WRITE_CONFLICT","status":409,"code":"CONFLICT","title":"Threshold written at the same moment","detail":"Another write of the same threshold landed at the same moment, so this one was refused and nothing was changed.","occursWhen":"Two calls set the same scope's cost threshold at once.","resolution":"Read the threshold back and set it again if it is not what you meant.","members":{}},{"type":"https://developer.telgea.com/errors/order/USAGE_THRESHOLD_TYPE_NOT_SUPPORTED","status":422,"code":"UNPROCESSABLE_ENTITY","title":"Usage type not supported","detail":"No threshold can stand on this usage type yet, so nothing was read or changed.","occursWhen":"A cost threshold is set, removed or read on a usage type the platform cannot yet enforce.","resolution":"Use VOICE. The Markets page in the documentation lists which usage types a threshold can stand on.","members":{"usageType":{"type":"string","description":"The usage type no threshold can stand on yet.","examples":["SMS"]}}},{"type":"https://developer.telgea.com/errors/consumption/INVALID_USAGE_CURSOR","status":400,"code":"BAD_REQUEST","title":"Invalid usage cursor","detail":"This cursor was not issued by the usage feed, so no records were returned.","occursWhen":"The usage feed is read with a cursor it did not hand out.","resolution":"Pass nextCursor from the previous response unchanged, or omit cursor to start from the first page.","members":{}},{"type":"https://developer.telgea.com/errors/consumption/POOL_NOT_FOUND","status":404,"code":"NOT_FOUND","title":"Pool not found","detail":"No data pool in your organization has this id.","occursWhen":"A request names a data pool that your organization does not have.","resolution":"Check the poolId you sent. GET /v1/data-pools lists the pools in your organization.","members":{}},{"type":"https://developer.telgea.com/errors/consumption/DATA_ALREADY_STOPPED","status":409,"code":"CONFLICT","title":"Data already stopped","detail":"Data is already stopped for this user, so no second stop was recorded.","occursWhen":"Data is stopped for a user whose data an earlier stop already cut off.","resolution":"Restore it with a DELETE on the same data-restriction path before stopping it again.","members":{}},{"type":"https://developer.telgea.com/errors/consumption/DATA_NOT_STOPPED","status":409,"code":"CONFLICT","title":"Data not stopped","detail":"No stop placed through the data-restriction endpoint is in effect for this user, so there was nothing to restore.","occursWhen":"Data is restored for a user with no stop placed through the data-restriction endpoint.","resolution":"No action is needed. A stop placed by a usage policy is lifted by that policy, not by this endpoint.","members":{}},{"type":"https://developer.telgea.com/errors/consumption/SUBSCRIBER_HAS_NO_DATA_POOL","status":422,"code":"UNPROCESSABLE_ENTITY","title":"No data pool","detail":"This user has no line in one of your data pools, so there is no data to stop.","occursWhen":"Data is stopped for a user who holds no line drawing on one of your data pools.","resolution":"Data can only be stopped on a line that draws on one of your pools; check this user holds a provisioned line that does.","members":{}},{"type":"https://developer.telgea.com/errors/consumption/DATA_STOP_NOT_SUPPORTED","status":422,"code":"UNPROCESSABLE_ENTITY","title":"Data stop not supported","detail":"This user's lines are with an operator that does not offer stopping data on its own, so nothing was changed.","occursWhen":"Data is stopped for a user whose lines are with an operator that cannot stop data alone.","resolution":"Those lines carry one plan for the whole country and cannot have data stopped separately. Ending the line still works: POST /v1/numbers/{numberId}/termination on the Partner API, or POST /v1/user-plans/{userId}/termination on the Enterprise API.","members":{}},{"type":"https://developer.telgea.com/errors/consumption/DATA_STOP_NOT_APPLIED","status":400,"code":"BAD_REQUEST","title":"Data stop not applied","detail":"None of this user's numbers could be stopped, so no stop is in effect.","occursWhen":"Data is stopped for a user none of whose numbers could be stopped at the network, for example because no number is active with a SIM.","resolution":"Check the number is active and has a SIM, since data can only be stopped on one that is. Retry once it is, with a new Idempotency-Key if you sent one. If it keeps failing, quote requestId to support.","members":{}},{"type":"https://developer.telgea.com/errors/consumption/DATA_RESTORE_NOT_APPLIED","status":400,"code":"BAD_REQUEST","title":"Data restore not applied","detail":"The network did not turn this user's data back on, so the stop is still in effect.","occursWhen":"Data is restored for a user, and the network does not apply the restore.","resolution":"Retry the request, with a new Idempotency-Key if you sent one; it resumes where this one left off. If it keeps failing, quote requestId to support.","members":{}},{"type":"https://developer.telgea.com/errors/provider-platform/EXECUTION_DATE_NOT_OFFERED","status":400,"code":"BAD_REQUEST","title":"Transfer date not offered","detail":"This executionDate is not a date the market offers for a port-in, so no port-in was created.","occursWhen":"A port-in is validated or submitted with an executionDate outside the dates its market offers.","resolution":"Send one of the type's executionDate.dates from GET /v1/port-ins/fields/{countryCode}. The dates change at the market's midnight, executionDate.validUntil, so fetch them again after it.","members":{"executionDate":{"type":"string","description":"The executionDate that was sent, as YYYY-MM-DD.","examples":["2027-03-06"],"format":"date"},"firstDate":{"description":"The first date the market offers now, as YYYY-MM-DD. Absent on a day it offers none.","examples":["2027-03-01"],"format":"date","type":"string"},"lastDate":{"description":"The last date the market offers now, as YYYY-MM-DD. Absent on a day it offers none.","examples":["2027-03-12"],"format":"date","type":"string"}}},{"type":"https://developer.telgea.com/errors/http/BAD_REQUEST","status":400,"code":"BAD_REQUEST","title":"Bad request","detail":"This request was refused, and no more specific code describes why.","occursWhen":"The request was refused for a reason no more specific code describes, such as the resource it acts on not being in a state that allows the action.","resolution":"Fetch the resource to check its current state before retrying. A malformed payload returns VALIDATION_ERROR instead.","members":{}},{"type":"https://developer.telgea.com/errors/http/VALIDATION_ERROR","status":400,"code":"VALIDATION_ERROR","title":"Validation error","detail":"The request does not match this endpoint's schema, so nothing was processed.","occursWhen":"A path parameter, query parameter or body field is missing or malformed.","resolution":"Correct the fields listed in fields and send the request again.","members":{}},{"type":"https://developer.telgea.com/errors/http/INVALID_REQUEST","status":400,"code":"INVALID_REQUEST","title":"Invalid request","detail":"This request combines parameters that cannot be used together, so nothing was processed.","occursWhen":"A request sends a combination of parameters the endpoint does not accept.","resolution":"Check the parameters against the API reference. Use BAD_REQUEST in new integrations.","members":{}},{"type":"https://developer.telgea.com/errors/http/UNAUTHORIZED","status":401,"code":"UNAUTHORIZED","title":"Unauthorized","detail":"This request could not be authenticated.","occursWhen":"The request carries no API key, or one that is not valid.","resolution":"Send a valid API key in the x-api-key header. If the same key works on other endpoints, quote requestId to support.","members":{}},{"type":"https://developer.telgea.com/errors/http/FORBIDDEN","status":403,"code":"FORBIDDEN","title":"Forbidden","detail":"Your API key is not allowed to perform this action.","occursWhen":"The API key lacks a permission the action needs.","resolution":"Check the permissions granted to this key and the identifiers in the request before retrying.","members":{}},{"type":"https://developer.telgea.com/errors/http/ORGANIZATION_ACCESS_REVOKED","status":403,"code":"ORGANIZATION_ACCESS_REVOKED","title":"Organization access revoked","detail":"Access for this organization has been revoked.","occursWhen":"The organization's access to the API has been revoked.","resolution":"Contact support to restore access, and quote requestId.","members":{}},{"type":"https://developer.telgea.com/errors/http/COUNTRY_NOT_SUPPORTED","status":403,"code":"COUNTRY_NOT_SUPPORTED","title":"Country not supported","detail":"This country is not available for your organization.","occursWhen":"A request names a country that is not enabled for the organization.","resolution":"Check the country code against a supported ISO 3166-1 alpha-2 country, or contact support to enable it.","members":{}},{"type":"https://developer.telgea.com/errors/http/NOT_FOUND","status":404,"code":"NOT_FOUND","title":"Not found","detail":"No resource matching this request exists in your organization.","occursWhen":"An identifier in the request names nothing in the organization.","resolution":"Check the identifiers in the request path before retrying.","members":{}},{"type":"https://developer.telgea.com/errors/http/METHOD_NOT_ALLOWED","status":405,"code":"METHOD_NOT_ALLOWED","title":"Method not allowed","detail":"This method is not allowed on this path.","occursWhen":"A request uses a method the path does not accept.","resolution":"Check the method against the API reference. The Allow response header lists what this path accepts.","members":{}},{"type":"https://developer.telgea.com/errors/http/CONFLICT","status":409,"code":"CONFLICT","title":"Conflict","detail":"This request conflicts with an existing resource, so nothing was created or changed.","occursWhen":"The request would duplicate or contradict a resource that already exists.","resolution":"Fetch the resource if it is already in your organization, or send different values.","members":{}},{"type":"https://developer.telgea.com/errors/http/UNPROCESSABLE_ENTITY","status":422,"code":"UNPROCESSABLE_ENTITY","title":"Unprocessable entity","detail":"This request was understood but could not be processed with the values it contains.","occursWhen":"The request is well formed, but its values cannot be acted on.","resolution":"Check the values in the request body against the API reference and correct them.","members":{}},{"type":"https://developer.telgea.com/errors/http/TOO_MANY_REQUESTS","status":429,"code":"TOO_MANY_REQUESTS","title":"Too many requests","detail":"This request was rate limited because too many requests were made in a short period.","occursWhen":"Requests arrive faster than the endpoint allows.","resolution":"Retry with exponential backoff.","members":{}},{"type":"https://developer.telgea.com/errors/http/RATE_LIMIT_EXCEEDED","status":429,"code":"RATE_LIMIT_EXCEEDED","title":"Rate limit exceeded","detail":"This API key has used its request quota for the current window, so the request was not processed.","occursWhen":"The API key has used its request quota for the current window.","resolution":"Retry-After says how many seconds until the window resets. Wait that long, then retry at a lower rate. Use TOO_MANY_REQUESTS in new integrations.","members":{}},{"type":"https://developer.telgea.com/errors/http/INTERNAL_ERROR","status":500,"code":"INTERNAL_ERROR","title":"Internal error","detail":"This request could not be completed.","occursWhen":"The request failed for a reason on our side.","resolution":"Check the request against the API reference and retry once with backoff. If it keeps failing, quote requestId to support.","members":{}},{"type":"https://developer.telgea.com/errors/http/SERVICE_UNAVAILABLE","status":503,"code":"SERVICE_UNAVAILABLE","title":"Service unavailable","detail":"This request could not be completed because a system it depends on is temporarily unavailable.","occursWhen":"A system the request depends on was unreachable or dropped the connection. The status is usually 503; a 502 or 504 carries this type too.","resolution":"Retry with exponential backoff. The connection may have dropped after we received the request, so read the resource back first if this one creates or changes something.","members":{}}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","name":"x-api-key","in":"header","description":"API key for authentication. Obtain from your organization settings."}},"schemas":{"ListUsersResponse":{"type":"object","properties":{"page":{"type":"integer","description":"The page these items came from.","example":1},"pageSize":{"type":"integer","description":"Items per page, as requested.","example":50},"itemsCount":{"type":"integer","description":"Total items across all pages. Divide by pageSize to get the number of pages.","example":142},"items":{"type":"array","items":{"$ref":"#/components/schemas/UserListItem"},"description":"Users on this page."}},"required":["page","pageSize","itemsCount","items"]},"UserListItem":{"type":"object","properties":{"id":{"type":"string","description":"UUID of the user. Use it to provision a plan, submit a port-in, or update the user.","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01"},"email":{"type":"string","format":"email","description":"Email address. Unique within your organization.","example":"anna.holm@acme.example"},"firstName":{"type":"string","description":"First name.","example":"Anna"},"lastName":{"type":"string","description":"Last name.","example":"Holm"},"teamId":{"type":"string","nullable":true,"description":"UUID of the team the user belongs to, or null.","example":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70"},"employeeId":{"type":"string","nullable":true,"description":"Your own identifier for this person, as sent on create or update, or null.","example":"EMP-0142"},"costCode":{"type":"string","nullable":true,"description":"Cost center code used on invoices, or null.","example":"CC-4100"}},"required":["id","email","firstName","lastName","teamId","employeeId","costCode"]},"BadRequestError":{"type":"object","properties":{"type":{"type":"string","description":"URI naming the problem type. It opens the page on developer.telgea.com that explains this refusal.","example":"https://developer.telgea.com/errors/http/BAD_REQUEST"},"title":{"type":"string","description":"Short, stable summary of the problem type. It does not change from one occurrence to the next.","example":"Bad request"},"status":{"type":"integer","description":"The HTTP status of this response.","example":400},"detail":{"type":"string","description":"What went wrong on this request, in one sentence.","example":"This request was refused, and no more specific code describes why."},"code":{"type":"string","enum":["BAD_REQUEST","INVALID_REQUEST"],"description":"Stable machine-readable code. Branch on this, never on the detail text.","example":"BAD_REQUEST"},"requestId":{"type":"string","description":"Identifier for this request. Quote it to support and we can find the exact call.","example":"req_123"}},"required":["type","title","status","detail","code","requestId"],"example":{"type":"https://developer.telgea.com/errors/http/BAD_REQUEST","title":"Bad request","status":400,"detail":"This request was refused, and no more specific code describes why.","code":"BAD_REQUEST","requestId":"req_123"}},"ValidationError":{"type":"object","properties":{"type":{"type":"string","description":"URI naming the problem type. It opens the page on developer.telgea.com that explains this refusal.","example":"https://developer.telgea.com/errors/http/VALIDATION_ERROR"},"title":{"type":"string","description":"Short, stable summary of the problem type. It does not change from one occurrence to the next.","example":"Validation error"},"status":{"type":"integer","description":"The HTTP status of this response.","example":400},"detail":{"type":"string","description":"What went wrong on this request, in one sentence.","example":"The request does not match this endpoint's schema, so nothing was processed."},"code":{"type":"string","enum":["VALIDATION_ERROR"],"description":"Stable machine-readable code. Branch on this, never on the detail text.","example":"VALIDATION_ERROR"},"requestId":{"type":"string","description":"Identifier for this request. Quote it to support and we can find the exact call.","example":"req_123"},"fields":{"type":"array","items":{"$ref":"#/components/schemas/ValidationFieldViolation"},"maxItems":20,"description":"One entry per rejected field, at most 20. Every entry describes the same request location: query, path and body are validated in that order and the first that fails answers the request."}},"required":["type","title","status","detail","code","requestId","fields"]},"ValidationFieldViolation":{"type":"object","properties":{"field":{"type":"string","example":"fields.authorizationCode","description":"Dotted path to the rejected field, with [i] for array indices. Empty when the failure is about the request as a whole rather than one field."},"location":{"type":"string","enum":["body","query","path","header","cookie"],"description":"Part of the request the field was read from. One request is validated in one location at a time.","example":"body"},"code":{"type":"string","enum":["REQUIRED","INVALID_TYPE","INVALID_FORMAT","INVALID_VALUE","TOO_SMALL","TOO_LARGE","UNKNOWN_FIELD","INVALID"],"description":"Why this field was rejected. Branch on this rather than on the message.","example":"REQUIRED"},"message":{"type":"string","description":"The rejection in one sentence, safe to show an end user.","example":"This field is required."}},"required":["field","location","code","message"]},"UnauthorizedError":{"type":"object","properties":{"type":{"type":"string","description":"URI naming the problem type. It opens the page on developer.telgea.com that explains this refusal.","example":"https://developer.telgea.com/errors/http/UNAUTHORIZED"},"title":{"type":"string","description":"Short, stable summary of the problem type. It does not change from one occurrence to the next.","example":"Unauthorized"},"status":{"type":"integer","description":"The HTTP status of this response.","example":401},"detail":{"type":"string","description":"What went wrong on this request, in one sentence.","example":"This request could not be authenticated."},"code":{"type":"string","enum":["UNAUTHORIZED"],"description":"Stable machine-readable code. Branch on this, never on the detail text.","example":"UNAUTHORIZED"},"requestId":{"type":"string","description":"Identifier for this request. Quote it to support and we can find the exact call.","example":"req_123"}},"required":["type","title","status","detail","code","requestId"]},"ForbiddenError":{"type":"object","properties":{"type":{"type":"string","description":"URI naming the problem type. It opens the page on developer.telgea.com that explains this refusal.","example":"https://developer.telgea.com/errors/http/FORBIDDEN"},"title":{"type":"string","description":"Short, stable summary of the problem type. It does not change from one occurrence to the next.","example":"Forbidden"},"status":{"type":"integer","description":"The HTTP status of this response.","example":403},"detail":{"type":"string","description":"What went wrong on this request, in one sentence.","example":"Your API key is not allowed to perform this action."},"code":{"type":"string","enum":["FORBIDDEN","ORGANIZATION_ACCESS_REVOKED","COUNTRY_NOT_SUPPORTED"],"description":"Stable machine-readable code. Branch on this, never on the detail text.","example":"FORBIDDEN"},"requestId":{"type":"string","description":"Identifier for this request. Quote it to support and we can find the exact call.","example":"req_123"},"missingPermission":{"type":"string","description":"The API-key permission this request needs and the key lacks. Present only when that is the reason.","example":"users:create"},"revokedAt":{"type":"string","description":"When the organization's access was revoked, as an ISO 8601 UTC time. Present only on ORGANIZATION_ACCESS_REVOKED.","example":"2026-09-17T08:15:00.000Z"},"countryCode":{"type":"string","description":"The ISO 3166-1 alpha-2 country that is not enabled for your organization. Present only on COUNTRY_NOT_SUPPORTED.","example":"DK"}},"required":["type","title","status","detail","code","requestId"],"example":{"type":"https://developer.telgea.com/errors/http/FORBIDDEN","title":"Forbidden","status":403,"detail":"This API key is missing the users:create permission.","code":"FORBIDDEN","requestId":"req_123","missingPermission":"users:create"}},"TooManyRequestsError":{"type":"object","properties":{"type":{"type":"string","description":"URI naming the problem type. It opens the page on developer.telgea.com that explains this refusal.","example":"https://developer.telgea.com/errors/http/TOO_MANY_REQUESTS"},"title":{"type":"string","description":"Short, stable summary of the problem type. It does not change from one occurrence to the next.","example":"Too many requests"},"status":{"type":"integer","description":"The HTTP status of this response.","example":429},"detail":{"type":"string","description":"What went wrong on this request, in one sentence.","example":"This request was rate limited because too many requests were made in a short period."},"code":{"type":"string","enum":["TOO_MANY_REQUESTS","RATE_LIMIT_EXCEEDED"],"description":"Stable machine-readable code. Branch on this, never on the detail text.","example":"TOO_MANY_REQUESTS"},"requestId":{"type":"string","description":"Identifier for this request. Quote it to support and we can find the exact call.","example":"req_123"}},"required":["type","title","status","detail","code","requestId"]},"InternalError":{"type":"object","properties":{"type":{"type":"string","description":"URI naming the problem type. It opens the page on developer.telgea.com that explains this refusal.","example":"https://developer.telgea.com/errors/http/INTERNAL_ERROR"},"title":{"type":"string","description":"Short, stable summary of the problem type. It does not change from one occurrence to the next.","example":"Internal error"},"status":{"type":"integer","description":"The HTTP status of this response.","example":500},"detail":{"type":"string","description":"What went wrong on this request, in one sentence.","example":"This request could not be completed."},"code":{"type":"string","enum":["INTERNAL_ERROR"],"description":"Stable machine-readable code. Branch on this, never on the detail text.","example":"INTERNAL_ERROR"},"requestId":{"type":"string","description":"Identifier for this request. Quote it to support and we can find the exact call.","example":"req_123"}},"required":["type","title","status","detail","code","requestId"]},"CreateUserResponse":{"type":"object","properties":{"id":{"type":"string","description":"UUID of the created user. Use it to provision a plan, submit a port-in, or update the user.","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01"},"email":{"type":"string","format":"email","description":"Email address as stored.","example":"anna.holm@acme.example"},"firstName":{"type":"string","description":"First name as stored.","example":"Anna"},"lastName":{"type":"string","description":"Last name as stored.","example":"Holm"}},"required":["id","email","firstName","lastName"]},"NotFoundError":{"type":"object","properties":{"type":{"type":"string","description":"URI naming the problem type. It opens the page on developer.telgea.com that explains this refusal.","example":"https://developer.telgea.com/errors/http/NOT_FOUND"},"title":{"type":"string","description":"Short, stable summary of the problem type. It does not change from one occurrence to the next.","example":"Not found"},"status":{"type":"integer","description":"The HTTP status of this response.","example":404},"detail":{"type":"string","description":"What went wrong on this request, in one sentence.","example":"No resource matching this request exists in your organization."},"code":{"type":"string","enum":["NOT_FOUND"],"description":"Stable machine-readable code. Branch on this, never on the detail text.","example":"NOT_FOUND"},"requestId":{"type":"string","description":"Identifier for this request. Quote it to support and we can find the exact call.","example":"req_123"}},"required":["type","title","status","detail","code","requestId"]},"ConflictError":{"type":"object","properties":{"type":{"type":"string","description":"URI naming the problem type. It opens the page on developer.telgea.com that explains this refusal.","example":"https://developer.telgea.com/errors/http/CONFLICT"},"title":{"type":"string","description":"Short, stable summary of the problem type. It does not change from one occurrence to the next.","example":"Conflict"},"status":{"type":"integer","description":"The HTTP status of this response.","example":409},"detail":{"type":"string","description":"What went wrong on this request, in one sentence.","example":"This request conflicts with an existing resource, so nothing was created or changed."},"code":{"type":"string","enum":["CONFLICT"],"description":"Stable machine-readable code. Branch on this, never on the detail text.","example":"CONFLICT"},"requestId":{"type":"string","description":"Identifier for this request. Quote it to support and we can find the exact call.","example":"req_123"}},"required":["type","title","status","detail","code","requestId"]},"CreateUserBody":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"Email address of the new user. Unique within your organization.","example":"anna.holm@acme.example"},"firstName":{"type":"string","minLength":1,"description":"First name","example":"Anna"},"lastName":{"type":"string","minLength":1,"description":"Last name","example":"Holm"},"teamId":{"type":"string","format":"uuid","example":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70","description":"Team to assign the user to. Omitted, the user joins the default team, Unassigned."},"costCode":{"type":"string","description":"Cost center code for billing purposes","example":"CC-4100"},"employeeId":{"type":"string","description":"External employee identifier","example":"EMP-0142"}},"required":["email","firstName","lastName"],"additionalProperties":false},"UpdateUserBody":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"Email address","example":"anna.holm@acme.example"},"firstName":{"type":"string","minLength":1,"description":"First name","example":"Anna"},"lastName":{"type":"string","minLength":1,"description":"Last name","example":"Holm"},"teamId":{"type":"string","nullable":true,"format":"uuid","example":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70","description":"Team to assign the user to. null moves the user to the default team, Unassigned."},"costCode":{"type":"string","nullable":true,"description":"Cost center code for billing purposes (null to remove)","example":"CC-4100"},"employeeId":{"type":"string","nullable":true,"description":"External employee identifier (null to remove)","example":"EMP-0142"}},"additionalProperties":false},"UserCostThresholdResponse":{"type":"object","properties":{"threshold":{"anyOf":[{"$ref":"#/components/schemas/CostThreshold"},{"nullable":true}],"description":"The threshold in force for the user: their own, else their team's, else the organization's. Null when none is set."},"spend":{"anyOf":[{"$ref":"#/components/schemas/CostSpend"},{"nullable":true}],"description":"Their spend this month against it. Null when no threshold is in force, or the spend could not be converted."},"pausedUntil":{"type":"string","nullable":true,"description":"While the usage is paused on their lines for crossing the threshold: when the pause lifts (ISO 8601). Null otherwise.","example":null}},"required":["threshold","spend","pausedUntil"]},"CostThreshold":{"type":"object","properties":{"id":{"type":"string","description":"UUID of the threshold.","example":"5d0b2c1e-7f3a-4b6c-9e8d-2a1f0c3b4d5e"},"usageType":{"type":"string","enum":["DATA","VOICE","SMS","MMS"],"description":"The usage type the threshold is on. `VOICE` is international calling: reaching it pauses international calls and SMS on the person's lines, where their market offers the pause. Other types answer `422` until the platform can enforce them.","example":"VOICE"},"scope":{"type":"string","enum":["organization","team","user"],"description":"Whose threshold this is: the organization's default, a team's, or one user's own.","example":"team"},"teamId":{"type":"string","nullable":true,"description":"The team, for a team threshold.","example":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70"},"userId":{"type":"string","nullable":true,"description":"The user, for a user threshold.","example":null},"maxAmount":{"type":"number","description":"What one person may spend on the usage type per month, in `currency`.","example":50},"currency":{"type":"string","description":"ISO 4217 code of the threshold's money: the team's cost-center currency, else the organization's primary.","example":"EUR"},"period":{"type":"string","enum":["monthly"],"description":"The period the spend is counted in. Always the calendar month.","example":"monthly"},"validFrom":{"type":"string","description":"When the threshold opens (ISO 8601). A threshold lowered below someone's spend opens next month.","example":"2026-10-01T00:00:00.000Z"},"validTo":{"type":"string","nullable":true,"description":"When the threshold closes (ISO 8601), or null while it stands.","example":null}},"required":["id","usageType","scope","teamId","userId","maxAmount","currency","period","validFrom","validTo"]},"CostSpend":{"type":"object","properties":{"amount":{"type":"number","description":"The user's spend on the usage type this month, in `currency`.","example":12.4},"currency":{"type":"string","description":"ISO 4217 code: the threshold's money.","example":"EUR"},"periodStart":{"type":"string","description":"Start of the month the spend is counted in (ISO 8601).","example":"2026-10-01T00:00:00.000Z"}},"required":["amount","currency","periodStart"]},"UnprocessableEntityError":{"type":"object","properties":{"type":{"type":"string","description":"URI naming the problem type. It opens the page on developer.telgea.com that explains this refusal.","example":"https://developer.telgea.com/errors/http/UNPROCESSABLE_ENTITY"},"title":{"type":"string","description":"Short, stable summary of the problem type. It does not change from one occurrence to the next.","example":"Unprocessable entity"},"status":{"type":"integer","description":"The HTTP status of this response.","example":422},"detail":{"type":"string","description":"What went wrong on this request, in one sentence.","example":"This request was understood but could not be processed with the values it contains."},"code":{"type":"string","enum":["UNPROCESSABLE_ENTITY"],"description":"Stable machine-readable code. Branch on this, never on the detail text.","example":"UNPROCESSABLE_ENTITY"},"requestId":{"type":"string","description":"Identifier for this request. Quote it to support and we can find the exact call.","example":"req_123"}},"required":["type","title","status","detail","code","requestId"]},"ListTeamsResponse":{"type":"object","properties":{"page":{"type":"integer","description":"The page these items came from.","example":1},"pageSize":{"type":"integer","description":"Items per page, as requested.","example":50},"itemsCount":{"type":"integer","description":"Total items across all pages. Divide by pageSize to get the number of pages.","example":142},"items":{"type":"array","items":{"$ref":"#/components/schemas/TeamListItem"},"description":"Teams on this page."}},"required":["page","pageSize","itemsCount","items"]},"TeamListItem":{"type":"object","properties":{"id":{"type":"string","description":"UUID of the team.","example":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70"},"name":{"type":"string","description":"Team name.","example":"Field Sales"},"emoji":{"type":"string","nullable":true,"description":"Emoji shown next to the team name, or null.","example":"🚀"},"costCode":{"type":"string","nullable":true,"description":"Cost center code applied to all users in this team","example":"CC-4100"},"memberCount":{"type":"integer","minimum":0,"description":"Number of users currently in the team.","example":12},"isDefault":{"type":"boolean","description":"Whether this is your organization's default team, Unassigned. Every user in no other team is in it, and it cannot be updated.","example":false}},"required":["id","name","emoji","costCode","memberCount","isDefault"]},"CreateTeamResponse":{"type":"object","properties":{"id":{"type":"string","description":"UUID of the created team.","example":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70"}},"required":["id"]},"CreateTeamBody":{"type":"object","properties":{"name":{"type":"string","description":"Team name","example":"Field Sales"},"emoji":{"type":"string","description":"Emoji representing the team","example":"🚀"},"costCode":{"type":"string","description":"Cost center code applied to all users in this team","example":"IT 5000"},"userIds":{"type":"array","items":{"type":"string","format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000"},"description":"Existing user IDs to add to the team on creation"}},"required":["name"],"additionalProperties":false},"UpdateTeamBody":{"type":"object","properties":{"name":{"type":"string","description":"Team name","example":"Field Sales"},"emoji":{"type":"string","description":"Emoji representing the team","example":"🚀"},"costCode":{"type":"string","description":"Cost center code applied to all users in this team","example":"IT 5000"},"userIds":{"type":"array","items":{"type":"string","format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000"},"description":"Full desired member list. When provided, replaces the team's membership: users not in the list are removed, new user IDs are added."}},"additionalProperties":false},"ListUserPlansResponse":{"type":"object","properties":{"page":{"type":"integer","description":"The page these items came from.","example":1},"pageSize":{"type":"integer","description":"Items per page, as requested.","example":50},"itemsCount":{"type":"integer","description":"Total items across all pages. Divide by pageSize to get the number of pages.","example":142},"items":{"type":"array","items":{"$ref":"#/components/schemas/UserPlanItem"},"description":"User plans on this page."}},"required":["page","pageSize","itemsCount","items"]},"UserPlanItem":{"type":"object","properties":{"id":{"type":"string","description":"UUID of the user plan.","example":"f7a8b9c0-d1e2-3456-f789-012345678901"},"userId":{"type":"string","description":"UUID of the user who holds the plan.","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01"},"firstName":{"type":"string","description":"First name of the user.","example":"Anna"},"lastName":{"type":"string","description":"Last name of the user.","example":"Holm"},"email":{"type":"string","format":"email","description":"Email address of the user.","example":"anna.holm@acme.example"},"status":{"type":"string","enum":["INACTIVE","PROVISIONING","PORTING","PORTING_FAILED","ACTIVE","TERMINATING","TERMINATING_WITH_DELETION"],"description":"Current status of the user plan","example":"ACTIVE"},"localPhoneNumber":{"type":"string","nullable":true,"description":"The local number in E.164 format, or null until it has been provisioned.","example":"+4520123456"},"teamId":{"type":"string","nullable":true,"description":"UUID of the user's team, or null. Teams are an enterprise concept and stay null for partners.","example":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70"},"teamName":{"type":"string","nullable":true,"description":"Name of the user's team, or null. Teams are an enterprise concept and stay null for partners.","example":"Field Sales"}},"required":["id","userId","firstName","lastName","email","status","localPhoneNumber","teamId","teamName"]},"UserPlanDetails":{"type":"object","properties":{"userId":{"type":"string","description":"UUID of the user who holds the plan.","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01"},"email":{"type":"string","format":"email","description":"Email address of the user.","example":"anna.holm@acme.example"},"firstName":{"type":"string","description":"First name of the user.","example":"Anna"},"lastName":{"type":"string","description":"Last name of the user.","example":"Holm"},"status":{"type":"string","enum":["INACTIVE","PROVISIONING","PORTING","PORTING_FAILED","ACTIVE","TERMINATING","TERMINATING_WITH_DELETION"],"description":"Current status of the user plan","example":"ACTIVE"},"teamId":{"type":"string","nullable":true,"description":"UUID of the user's team, or null. Teams are an enterprise concept and stay null for partners.","example":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70"},"localNumber":{"$ref":"#/components/schemas/UserPlanNumber"},"travelNumber":{"$ref":"#/components/schemas/UserPlanTravelNumber"},"terminationScheduledAt":{"type":"string","nullable":true,"description":"The date this plan is scheduled to end, or null when no termination is scheduled. Set by POST /v1/user-plans/{userId}/termination.","example":"2026-10-01T00:00:00.000Z"}},"required":["userId","email","firstName","lastName","status","teamId","localNumber","travelNumber","terminationScheduledAt"]},"UserPlanNumber":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"UUID of the number. This is what SIM replacement and suspension act on.","example":"8238c1b9-c2c0-4455-9b03-4bd787052709"},"type":{"type":"string","enum":["local","travel"],"description":"Which line this is.","example":"local"},"countryCode":{"type":"string","description":"Market the number belongs to, ISO 3166-1 alpha-2.","example":"DK"},"phoneNumber":{"type":"string","nullable":true,"description":"The number in E.164 format, or null until it has been provisioned.","example":"+4520123456"},"state":{"type":"string","nullable":true,"enum":["PENDING","PORTING","PORTING_FAILED","PROVISIONING","READY","REPLACING","CHANGING","SUSPENDING","SUSPENDED","RESTORING","RECONFIGURING","DEACTIVATING","DEACTIVATED","PORTING_DISCARDED","PORTING_OUT","PORTED_OUT",null],"description":"Current state of the phone number in the provisioning lifecycle","example":"READY"},"sim":{"$ref":"#/components/schemas/UserPlanSimDetails"}},"required":["id","type","countryCode","phoneNumber","state","sim"],"description":"The local line: the number, where it is in provisioning, and its eSIM."},"UserPlanSimDetails":{"type":"object","nullable":true,"properties":{"iccid":{"type":"string","description":"ICCID of the eSIM profile.","example":"8945000000000000001"},"activationCode":{"type":"string","nullable":true,"description":"GSMA activation string for the eSIM. Render it as a QR code, or build an install link from it. Null until the profile has been issued.","example":"LPA:1$SMDP.TELGEA.COM$34682-73063-9140"},"pinOne":{"type":"string","nullable":true,"description":"PIN1 of the SIM, or null.","example":"1234"},"pinTwo":{"type":"string","nullable":true,"description":"PIN2 of the SIM, or null.","example":"5678"},"pukOne":{"type":"string","nullable":true,"description":"PUK1, needed after three wrong PIN1 entries, or null.","example":"12345678"},"pukTwo":{"type":"string","nullable":true,"description":"PUK2, needed after three wrong PIN2 entries, or null.","example":"87654321"}},"required":["iccid","activationCode","pinOne","pinTwo","pukOne","pukTwo"],"description":"SIM details, included only when the number state is READY"},"UserPlanTravelNumber":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"UUID of the travel number.","example":"81ec0bc5-b200-436d-bb70-d563ca2348d4"},"type":{"type":"string","enum":["local","travel"],"description":"Which line this is.","example":"travel"},"phoneNumber":{"type":"string","nullable":true,"description":"The travel number in E.164 format, or null when the profile carries data only.","example":"+4520123456"},"state":{"type":"string","nullable":true,"enum":["PENDING","PORTING","PORTING_FAILED","PROVISIONING","READY","REPLACING","CHANGING","SUSPENDING","SUSPENDED","RESTORING","RECONFIGURING","DEACTIVATING","DEACTIVATED","PORTING_DISCARDED","PORTING_OUT","PORTED_OUT",null],"description":"Current state of the phone number in the provisioning lifecycle","example":"READY"},"sim":{"$ref":"#/components/schemas/UserPlanSimDetails"}},"required":["id","type","phoneNumber","state","sim"],"description":"The travel line and its eSIM, when the organization has one. Null for a local-only plan."},"CreateUserPlanResponse":{"type":"object","properties":{"status":{"type":"string","enum":["INACTIVE","PROVISIONING","PORTING","PORTING_FAILED","ACTIVE","TERMINATING","TERMINATING_WITH_DELETION"],"description":"Current status of the user plan","example":"PROVISIONING"},"localNumberId":{"type":"string","nullable":true,"description":"UUID of the provisioned local number","example":"8238c1b9-c2c0-4455-9b03-4bd787052709"},"travelNumberId":{"type":"string","nullable":true,"deprecated":true,"description":"Always `null`. This call provisions the local line alone. A travel eSIM is added afterwards, and only for an organization whose contract includes one and which holds a data pool outside its home zone. Read `travelNumber` from GET /v1/user-plans/{userId} to see whether one exists.","example":null}},"required":["status","localNumberId","travelNumberId"]},"CreateUserPlanBody":{"type":"object","properties":{"userId":{"type":"string","format":"uuid","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","description":"UUID of an existing user to provision a plan for"},"countryCode":{"type":"string","example":"DK","description":"Two-character ISO country code for the user plan. Must be a valid ISO 3166-1 alpha-2 code (e.g., \"DK\", \"US\", \"GB\") and available in your organization's list of supported markets. Case-insensitive. Invalid codes are rejected immediately. Contact support to enable additional countries."}},"required":["userId","countryCode"],"additionalProperties":false},"ReplaceSimResponse":{"type":"object","properties":{"status":{"type":"string","description":"Status of the SIM replacement request","example":"accepted"}},"required":["status"]},"ReplaceSimBody":{"type":"object","properties":{"numberId":{"type":"string","format":"uuid","example":"8238c1b9-c2c0-4455-9b03-4bd787052709","description":"UUID of the number to replace the SIM for. Obtain from the user plan details endpoint (localNumber.id or travelNumber.id)."}},"required":["numberId"],"additionalProperties":false},"DataRestrictionResponse":{"type":"object","properties":{"numbers":{"type":"array","items":{"type":"string"},"description":"The phone numbers the request actually reached at the network.","example":["+4520123456"]},"effectiveAt":{"type":"string","description":"When the change took effect at the network.","example":"2026-09-14T09:30:00.000Z"}},"required":["numbers","effectiveAt"]},"DataRestrictionBody":{"type":"object","properties":{"reason":{"type":"string","maxLength":200,"description":"Free text kept with the change and shown to our support staff.","example":"Customer exceeded their agreed data allowance."}},"additionalProperties":false},"SuspensionResponse":{"type":"object","properties":{"numbers":{"type":"array","items":{"type":"string"},"description":"The phone numbers the request actually reached at the network.","example":["+4520123456"]}},"required":["numbers"]},"SuspensionBody":{"type":"object","properties":{"numberId":{"type":"string","format":"uuid","example":"8238c1b9-c2c0-4455-9b03-4bd787052709","description":"UUID of the number to suspend. Obtain it from the user plan details endpoint."}},"required":["numberId"],"additionalProperties":false},"TerminationResponse":{"type":"object","properties":{"terminationDate":{"type":"string","description":"The date the line stops, as accepted.","example":"2026-10-01"},"activeUntil":{"type":"string","nullable":true,"description":"The end of the period already paid for. Billing runs to this date even when the line stops earlier; null when the plan carried no billing period.","example":"2026-12-31T00:00:00.000Z"},"numberIds":{"type":"array","items":{"type":"string"},"description":"The lines this termination ends, by their number ids.","example":["9f1c6f3e-4f4a-4f2e-bb2a-2b9a1f0c8e11"]}},"required":["terminationDate","activeUntil","numberIds"]},"TerminationBody":{"type":"object","properties":{"terminationDate":{"type":"string","format":"date","description":"The date the customer agreed to stop, as YYYY-MM-DD. Today is allowed; a past date is rejected.","example":"2026-10-01"},"deleteUser":{"type":"boolean","description":"Delete the end-user once their line is gone. Defaults to false, in which case the user remains and can be deleted with DELETE /v1/users/{userId} once the line is suspended.","example":false}},"required":["terminationDate"],"additionalProperties":false},"ListNumbersResponse":{"type":"object","properties":{"page":{"type":"integer","description":"The page these items came from.","example":1},"pageSize":{"type":"integer","description":"Items per page, as requested.","example":50},"itemsCount":{"type":"integer","description":"Total items across all pages. Divide by pageSize to get the number of pages.","example":142},"items":{"type":"array","items":{"$ref":"#/components/schemas/NumberListItem"},"description":"Lines on this page."}},"required":["page","pageSize","itemsCount","items"]},"NumberListItem":{"type":"object","properties":{"id":{"type":"string","description":"UUID of the number. This is what SIM replacement and suspension act on.","example":"8238c1b9-c2c0-4455-9b03-4bd787052709"},"type":{"type":"string","enum":["local","travel"],"description":"Which line this is.","example":"local"},"countryCode":{"type":"string","description":"Market the number belongs to, ISO 3166-1 alpha-2.","example":"DK"},"phoneNumber":{"type":"string","nullable":true,"description":"The number in E.164 format, or null until it has been provisioned.","example":"+4520123456"},"state":{"type":"string","nullable":true,"enum":["PENDING","PORTING","PORTING_FAILED","PROVISIONING","READY","REPLACING","CHANGING","SUSPENDING","SUSPENDED","RESTORING","RECONFIGURING","DEACTIVATING","DEACTIVATED","PORTING_DISCARDED","PORTING_OUT","PORTED_OUT",null],"description":"Current state of the phone number in the provisioning lifecycle","example":"READY"},"sim":{"$ref":"#/components/schemas/UserPlanSimDetails"},"userId":{"type":"string","description":"UUID of the user who holds the line.","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01"},"createdAt":{"type":"string","description":"When the line was created, as an ISO 8601 UTC time.","example":"2026-09-17T08:15:00.000Z"}},"required":["id","type","countryCode","phoneNumber","state","sim","userId","createdAt"],"description":"One line in your organization."},"NumberDetails":{"type":"object","properties":{"id":{"type":"string","description":"UUID of the number. This is what SIM replacement and suspension act on.","example":"8238c1b9-c2c0-4455-9b03-4bd787052709"},"type":{"type":"string","enum":["local","travel"],"description":"Which line this is.","example":"local"},"countryCode":{"type":"string","description":"Market the number belongs to, ISO 3166-1 alpha-2.","example":"DK"},"phoneNumber":{"type":"string","nullable":true,"description":"The number in E.164 format, or null until it has been provisioned.","example":"+4520123456"},"state":{"type":"string","nullable":true,"enum":["PENDING","PORTING","PORTING_FAILED","PROVISIONING","READY","REPLACING","CHANGING","SUSPENDING","SUSPENDED","RESTORING","RECONFIGURING","DEACTIVATING","DEACTIVATED","PORTING_DISCARDED","PORTING_OUT","PORTED_OUT",null],"description":"Current state of the phone number in the provisioning lifecycle","example":"READY"},"sim":{"$ref":"#/components/schemas/UserPlanSimDetails"},"userId":{"type":"string","description":"UUID of the user who holds the line.","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01"},"createdAt":{"type":"string","description":"When the line was created, as an ISO 8601 UTC time.","example":"2026-09-17T08:15:00.000Z"},"stateUpdatedAt":{"type":"string","nullable":true,"description":"When the line last reached the state it is in, as an ISO 8601 UTC time. Null for a line with no state yet.","example":"2026-09-17T08:15:00.000Z"},"terminationScheduledAt":{"type":"string","nullable":true,"description":"The date this line is scheduled to end, or null when no termination is scheduled. Set by POST /v1/numbers/{numberId}/termination.","example":"2026-10-01T00:00:00.000Z"},"activatedAt":{"type":"string","nullable":true,"description":"When the line first went into service, as an ISO 8601 UTC time: when it was provisioned, or when its number was ported in. Null until then.","example":"2026-09-17T08:20:00.000Z"},"previousSims":{"type":"array","items":{"$ref":"#/components/schemas/PreviousSim"},"description":"The eSIMs the line carried before its current one, newest first. Each SIM replacement adds one. Empty for a line whose eSIM has never been replaced."}},"required":["id","type","countryCode","phoneNumber","state","sim","userId","createdAt","stateUpdatedAt","terminationScheduledAt","activatedAt","previousSims"],"description":"One line in full."},"PreviousSim":{"type":"object","properties":{"iccid":{"type":"string","description":"ICCID of the eSIM profile.","example":"89462000099812030017"},"inServiceFrom":{"type":"string","description":"When this eSIM was issued to the line, as an ISO 8601 UTC time.","example":"2026-03-02T09:00:00.000Z"},"inServiceTo":{"type":"string","description":"When the eSIM that replaced it was issued, as an ISO 8601 UTC time.","example":"2026-09-14T08:00:00.000Z"}},"required":["iccid","inServiceFrom","inServiceTo"],"description":"An eSIM the line carried before its current one."},"NumberConnection":{"type":"object","properties":{"available":{"type":"boolean","description":"Whether the line's network could be asked. False for a line in a market whose network does not report connection status, one with no phone number or eSIM yet, and one still being ported in or already ended; every other field is then null.","example":true},"status":{"type":"string","nullable":true,"enum":["active","suspended","inactive","unknown",null],"description":"How the network holds the line: `active`, `suspended` or `inactive`, or `unknown` when the network does not say.","example":"active"},"lastSeenAt":{"type":"string","nullable":true,"description":"When the network last saw activity on the line, as an ISO 8601 UTC time. Null when the network does not report it.","example":"2026-10-19T11:58:00.000Z"},"countryCode":{"type":"string","nullable":true,"description":"The country the line is attached in, ISO 3166-1 alpha-2. Null when the network does not report it.","example":"DK"},"servingNetwork":{"type":"string","nullable":true,"description":"The name of the network operator serving the line. Null when the network does not report it.","example":"TDC"},"accessTechnology":{"type":"string","nullable":true,"enum":["2G","3G","4G","5G","unknown",null],"description":"The network type the line is attached on, or `unknown` when the network does not say.","example":"4G"},"ipAddress":{"type":"string","nullable":true,"description":"The IP address the line holds for data. Null when the network does not report it.","example":"10.20.30.40"},"apn":{"type":"string","nullable":true,"description":"The access point name the line uses for data. Null when the network does not report it.","example":"internet"},"imei":{"type":"string","nullable":true,"description":"The IMEI of the device the line was last seen in. Null when the network does not report it.","example":"356938035643809"},"checkedAt":{"type":"string","nullable":true,"description":"When the network was asked, as an ISO 8601 UTC time. A read is shared for the rest of its 5-minute window, so this can be up to 5 minutes earlier than your request.","example":"2026-10-19T12:00:00.000Z"}},"required":["available","status","lastSeenAt","countryCode","servingNetwork","accessTechnology","ipAddress","apn","imei","checkedAt"],"description":"What the line's network reports about it."},"ServiceUnavailableError":{"type":"object","properties":{"type":{"type":"string","description":"URI naming the problem type. It opens the page on developer.telgea.com that explains this refusal.","example":"https://developer.telgea.com/errors/http/SERVICE_UNAVAILABLE"},"title":{"type":"string","description":"Short, stable summary of the problem type. It does not change from one occurrence to the next.","example":"Service unavailable"},"status":{"type":"integer","description":"The HTTP status of this response.","example":503},"detail":{"type":"string","description":"What went wrong on this request, in one sentence.","example":"This request could not be completed because a system it depends on is temporarily unavailable."},"code":{"type":"string","enum":["SERVICE_UNAVAILABLE"],"description":"Stable machine-readable code. Branch on this, never on the detail text.","example":"SERVICE_UNAVAILABLE"},"requestId":{"type":"string","description":"Identifier for this request. Quote it to support and we can find the exact call.","example":"req_123"}},"required":["type","title","status","detail","code","requestId"]},"CreateNumberResponse":{"type":"object","properties":{"numberId":{"type":"string","description":"UUID of the line being obtained.","example":"8238c1b9-c2c0-4455-9b03-4bd787052709"},"state":{"type":"string","enum":["PENDING","PORTING","PORTING_FAILED","PROVISIONING","READY","REPLACING","CHANGING","SUSPENDING","SUSPENDED","RESTORING","RECONFIGURING","DEACTIVATING","DEACTIVATED","PORTING_DISCARDED","PORTING_OUT","PORTED_OUT"],"description":"State the line starts in. Poll GET /v1/numbers/{numberId} until it reaches READY.","example":"PROVISIONING"}},"required":["numberId","state"]},"CreateNumberBody":{"type":"object","properties":{"userId":{"type":"string","format":"uuid","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","description":"UUID of an existing user to obtain the line for"},"countryCode":{"type":"string","example":"DK","description":"Two-character ISO country code of the market the line belongs to. Must be a valid ISO 3166-1 alpha-2 code (e.g., \"DK\", \"US\", \"GB\") and available in your organization's list of supported markets. Case-insensitive. Invalid codes are rejected immediately. Contact support to enable additional countries."}},"required":["userId","countryCode"],"additionalProperties":false},"GetPortInFieldsResponse":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/PortInFieldTypeConfig"}},"PortInFieldTypeConfig":{"type":"object","properties":{"label":{"type":"string","description":"Human-readable label for this port-in type","example":"Personal"},"typeLabel":{"type":"object","properties":{"id":{"type":"string","description":"Stable id of the text, to key a translation off.","example":"port-in.de.business.authorizationCode.howToGet"},"en":{"type":"string","description":"The text in English.","example":"On the current carrier's invoice."}},"required":["id","en"],"description":"The label over the choice of type, such as \"Who is the number registered to?\". The same in every type of the market. A market with a single type has none."},"explanation":{"type":"object","properties":{"id":{"type":"string","description":"Stable id of the text, to key a translation off.","example":"port-in.de.business.authorizationCode.howToGet"},"en":{"type":"string","description":"The text in English.","example":"On the current carrier's invoice."}},"required":["id","en"],"description":"Shown with the choice of type, to help pick it. A market with a single type has none."},"fields":{"type":"array","items":{"$ref":"#/components/schemas/PortInInputField"},"description":"Every field this port-in type requires."},"executionDate":{"allOf":[{"$ref":"#/components/schemas/PortInInputField"},{"description":"The transfer date, as a date field: `dates` holds every date a port-in can happen on, until `validUntil`. The same in every type of the market."}]},"timing":{"$ref":"#/components/schemas/PortInTiming"}},"required":["label","fields"]},"PortInInputField":{"type":"object","properties":{"name":{"type":"string","description":"Machine-readable field name","example":"authorizationCode"},"label":{"type":"string","description":"Human-readable label","example":"PAC code"},"type":{"type":"string","enum":["text","select","date","number","checkbox"],"description":"Input field type","example":"text"},"description":{"type":"string","description":"Help text for the field","example":"Porting Authorization Code from the current carrier."},"errorMessage":{"type":"string","description":"Custom error message for validation failures","example":"A PAC is 3 letters, then 6 digits (e.g. ABC123456). 6 digits then 3 letters is a STAC, not a PAC."},"help":{"type":"object","properties":{"id":{"type":"string","description":"Stable id of the text, to key a translation off.","example":"port-in.de.business.authorizationCode.howToGet"},"en":{"type":"string","description":"The text in English.","example":"On the current carrier's invoice."}},"required":["id","en"],"description":"What the value is, and whose details it is."},"howToGet":{"type":"object","properties":{"id":{"type":"string","description":"Stable id of the text, to key a translation off.","example":"port-in.de.business.authorizationCode.howToGet"},"en":{"type":"string","description":"The text in English.","example":"On the current carrier's invoice."}},"required":["id","en"],"description":"How to look the value up, for a value the customer has to go and find."},"example":{"type":"string","description":"A value in the format the field accepts. It shows the format only and is never a real value.","example":"ABC123456"},"minLength":{"type":"number","description":"Shortest accepted value, for a text field.","example":1},"maxLength":{"type":"number","description":"Longest accepted value, for a text field.","example":64},"regex":{"type":"string","description":"The pattern a text field must match, as a JavaScript regular expression literal: `/pattern/flags`. Compile the part between the slashes, with the flags after the last one.","example":"/^\\s*[A-Za-z]{3}\\s*\\d{3}\\s*\\d{3}\\s*$/"},"options":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","description":"What to show the customer.","example":"Congstar"},"value":{"type":"string","description":"What to send back in `fields`.","example":"CONG"}},"required":["label","value"]},"description":"Options for select fields"},"minDate":{"type":"string","description":"Earliest accepted date, for a date field, as YYYY-MM-DD.","example":"2027-03-01"},"maxDate":{"type":"string","description":"Latest accepted date, for a date field, as YYYY-MM-DD.","example":"2027-03-08"},"dates":{"type":"array","items":{"type":"string","format":"date"},"description":"For a date field, every date the value can take, ascending, as YYYY-MM-DD. Absent when any date is accepted.","example":["2027-03-01","2027-03-02","2027-03-03"]},"validUntil":{"type":"string","format":"date-time","description":"When `dates` stops holding, as ISO 8601: the market's next midnight. Fetch the fields again after it.","example":"2027-02-22T23:00:00.000Z"},"min":{"type":"number","description":"Smallest accepted value, for a number field.","example":1},"max":{"type":"number","description":"Largest accepted value, for a number field.","example":99},"decimalPlaces":{"type":"number","description":"Decimal places accepted, for a number field.","example":0},"requiredValue":{"type":"boolean","description":"For a checkbox, the value the donor requires. Present when only one answer is accepted.","example":true}},"required":["name","label","type"],"description":"One field the donor carrier requires for this port-in type."},"PortInTiming":{"type":"object","properties":{"submitted":{"type":"string","enum":["immediately","onTheDay","beforeTheDate"],"description":"When the port-in is submitted to the carrier: `immediately`, `onTheDay` of the transfer, or `beforeTheDate`.","example":"immediately"},"finalDateSetBy":{"type":"string","enum":["us","provider","oldCarrier"],"description":"Who sets the final transfer date: `us`, our `provider`, or the `oldCarrier` the number leaves.","example":"oldCarrier"},"dateMayMove":{"type":"boolean","description":"Whether the transfer date can still move after the port-in is submitted.","example":true},"cancel":{"type":"string","enum":["never","beforeSubmission","always"],"description":"When the port-in can be cancelled: `never`, `beforeSubmission`, or `always`.","example":"beforeSubmission"},"reschedule":{"type":"string","enum":["never","beforeSubmission"],"description":"When the transfer date can be changed: `never`, or `beforeSubmission`.","example":"beforeSubmission"}},"required":["submitted","finalDateSetBy","dateMayMove","cancel","reschedule"],"description":"How a port-in into this market runs. The same in every type of the market."},"GetPortInFieldsSchemaResponse":{"type":"object","additionalProperties":{"nullable":true}},"ValidatePortInResponse":{"type":"object","properties":{"valid":{"type":"boolean","description":"Whether the port-in data passed validation","example":true},"errors":{"type":"array","items":{"$ref":"#/components/schemas/PortInValidationError"},"description":"List of validation errors, empty if valid"}},"required":["valid","errors"]},"PortInValidationError":{"type":"object","properties":{"message":{"type":"string","description":"Validation error description","example":"A PAC is 3 letters, then 6 digits (e.g. ABC123456). 6 digits then 3 letters is a STAC, not a PAC."},"field":{"type":"string","description":"The field that caused the validation error","example":"authorizationCode"},"code":{"type":"string","enum":["REQUIRED","FORMAT_INVALID","LENGTH_INVALID","NOT_ALLOWED","DATE_NOT_ALLOWED","CHECK_DIGIT_INVALID","WRONG_CUSTOMER_TYPE"],"description":"Why the value was refused, as a stable code to branch on. A code is never renamed or removed, but new ones can be added: show the `message` for a code you do not recognise.","example":"FORMAT_INVALID"}},"required":["message","code"]},"ValidatePortInBody":{"type":"object","properties":{"countryCode":{"type":"string","example":"DE","description":"ISO 3166-1 alpha-2 country code"},"type":{"type":"string","description":"Port-in type as returned by the fields endpoint (e.g., \"personal\", \"business\")","example":"personal"},"msisdn":{"type":"string","description":"Phone number to port in, in E.164 format","example":"+4915112345678"},"executionDate":{"type":"string","format":"date","description":"Requested porting date in YYYY-MM-DD format. Must be one of the type's `executionDate.dates` from `GET /v1/port-ins/fields/{countryCode}`, which hold until its `validUntil`.","example":"2027-03-01"},"fields":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"boolean"},{"type":"number"}]},"description":"Port-in fields as defined by the fields endpoint. Must include authorizationCode.","example":{"currentCarrier":"CONG","authorizationCode":"1985-04-12","ownerFirstName":"Erika","ownerLastName":"Mustermann","isUnlocked":true}}},"required":["countryCode","type","msisdn","executionDate","fields"],"additionalProperties":false},"CreatePortInResponse":{"type":"object","properties":{"id":{"type":"string","description":"UUID of the created port-in","example":"c3d4e5f6-a7b8-9012-c345-678901234567"},"status":{"type":"string","enum":["CREATED","REJECTED"],"description":"Status of the port-in. CREATED means accepted for processing; REJECTED means validation failed.","example":"CREATED"},"msisdn":{"type":"string","description":"The phone number being ported","example":"+4915112345678"},"numberId":{"type":"string","description":"UUID of the associated number resource","example":"8238c1b9-c2c0-4455-9b03-4bd787052709"},"executionDate":{"type":"string","description":"Confirmed execution date","example":"2027-03-01"},"errors":{"type":"array","items":{"$ref":"#/components/schemas/PortInValidationError"},"description":"Validation errors when status is REJECTED"}},"required":["id","status"]},"CreatePortInBody":{"type":"object","properties":{"userId":{"type":"string","format":"uuid","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","description":"UUID of the user to port a number for. The user must have an INACTIVE or PORTING plan."},"countryCode":{"type":"string","example":"DE","description":"ISO 3166-1 alpha-2 country code"},"msisdn":{"type":"string","description":"Phone number to port in, in E.164 format","example":"+4915112345678"},"executionDate":{"type":"string","format":"date","description":"Requested porting date in YYYY-MM-DD format. Must be one of the type's `executionDate.dates` from `GET /v1/port-ins/fields/{countryCode}`, which hold until its `validUntil`.","example":"2027-03-01"},"type":{"type":"string","description":"Port-in type as returned by the fields endpoint (e.g., \"personal\", \"business\")","example":"personal"},"fields":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"boolean"},{"type":"number"}]},"description":"Port-in fields as defined by the fields endpoint. Must include authorizationCode.","example":{"currentCarrier":"CONG","authorizationCode":"1985-04-12","ownerFirstName":"Erika","ownerLastName":"Mustermann","isUnlocked":true}}},"required":["userId","countryCode","msisdn","executionDate","type","fields"],"additionalProperties":false},"GetPortInResponse":{"type":"object","properties":{"id":{"type":"string","description":"UUID of the port-in request.","example":"c3d4e5f6-a7b8-9012-c345-678901234567"},"countryCode":{"type":"string","description":"Market the number is being ported into.","example":"DE"},"msisdn":{"type":"string","description":"The number being ported, in E.164 format.","example":"+4915112345678"},"executionDate":{"type":"string","description":"The porting date, as YYYY-MM-DD.","example":"2027-03-01"},"type":{"type":"string","nullable":true,"description":"Port-in type this request was submitted under, or null when the donor needed none.","example":"personal"},"status":{"type":"string","enum":["PENDING","CREATED","SUBMITTED","ACCEPTED","REJECTED","SUCCEEDED","FAILED"],"description":"Current status of the port-in","example":"CREATED"},"numberId":{"type":"string","description":"UUID of the number this port-in creates. Use it to read the line once porting succeeds.","example":"8238c1b9-c2c0-4455-9b03-4bd787052709"},"failure":{"$ref":"#/components/schemas/PortInFailure"},"createdAt":{"type":"string","description":"When the port-in was submitted, ISO 8601.","example":"2027-02-22T10:00:00Z"},"updatedAt":{"type":"string","description":"When the port-in last changed status, ISO 8601.","example":"2027-02-22T10:00:00Z"}},"required":["id","countryCode","msisdn","executionDate","type","status","numberId","failure","createdAt","updatedAt"]},"PortInFailure":{"type":"object","nullable":true,"properties":{"reason":{"type":"string","nullable":true,"enum":["WRONG_CUSTOMER_TYPE","CONTRACT_LOCKED","NUMBER_OWNERSHIP_MISMATCH","NUMBER_ALREADY_PORTING","AUTHORIZATION_CODE_INVALID","PORTING_DATE_UNAVAILABLE","FIELD_MISSING","FIELD_INVALID","FIELD_MISMATCH","REJECTED_BY_DONOR","CANCELLED",null],"description":"Why the port-in ended this way, or null when we could not classify it.","example":"AUTHORIZATION_CODE_INVALID"},"field":{"type":"string","nullable":true,"description":"What the donor objected to, when it identified something. Either a key you sent in `fields` (e.g. `authorizationCode`) or a top-level property of the port-in (`msisdn`, `type`, `executionDate`).","example":"authorizationCode"},"text":{"type":"string","description":"What happened and what to do next, in English, for showing to your customer. The wording may change at any time: branch on `reason`, never on this.","example":"Your authorization code was refused or has expired."}},"required":["reason","field","text"],"description":"Why a REJECTED or FAILED port-in ended that way: values you can branch on, and a text you can show your customer. Null in every other status."},"ListPortInsResponse":{"type":"object","properties":{"page":{"type":"integer","description":"The page these items came from.","example":1},"pageSize":{"type":"integer","description":"Items per page, as requested.","example":50},"itemsCount":{"type":"integer","description":"Total items across all pages. Divide by pageSize to get the number of pages.","example":142},"items":{"type":"array","items":{"$ref":"#/components/schemas/GetPortInResponse"},"description":"Port-ins on this page, newest first."}},"required":["page","pageSize","itemsCount","items"]},"UsageFeedResponse":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/UsageRecord"},"description":"Usage records on this page, in the order they were stored or last corrected."},"nextCursor":{"type":"string","nullable":true,"description":"Pass as `cursor` to fetch the next page; null once the feed is exhausted. To pick up later changes, resend the cursor that fetched the last page.","example":"eyJjIjoiMjAyNi0wOS0xMVQwODozMDowMC4xMjM0NTZaIiwicyI6ImRhdGEiLCJpIjoiY2RyXzEifQ"},"hasMore":{"type":"boolean","description":"Whether another page follows. Equivalent to nextCursor being non-null.","example":true}},"required":["items","nextCursor","hasMore"]},"UsageRecord":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of this usage record. Stable, so you can deduplicate across pages.","example":"cdr_01j9v2k8f3m4n5p6q7r8s9t0u1"},"type":{"type":"string","enum":["VOICE","SMS","MMS","DATA","UNKNOWN"],"description":"What was metered. `UNKNOWN` is a record the network sent us that we could not classify.","example":"DATA"},"provider":{"type":"string","description":"The network that reported this usage.","example":"telia-denmark"},"msisdn":{"type":"string","description":"The number the usage was recorded against, in E.164 format.","example":"+4520123456"},"timeStarted":{"type":"string","description":"When the session or message started, ISO 8601 UTC.","example":"2026-09-11T08:30:00.000Z"},"timeEnded":{"type":"string","nullable":true,"description":"When it ended, ISO 8601 UTC. Null for records the network reports without a duration.","example":"2026-09-11T08:34:12.000Z"},"amount":{"type":"number","description":"Usage quantity, expressed in `unit`.","example":10485760},"unit":{"type":"string","enum":["seconds","count","bytes"],"description":"What `amount` counts: seconds for voice, count for messages, bytes for data.","example":"bytes"},"servingCountryCode":{"type":"string","nullable":true,"description":"ISO-2 country serving the subscriber.","example":"DK"},"usageClass":{"type":"string","nullable":true,"enum":["domestic","roaming","international",null],"description":"Where the usage sat relative to the home market.","example":"domestic"},"counterpartyMsisdn":{"type":"string","nullable":true,"description":"Communication records only.","example":"+4598765432"},"callDirection":{"type":"string","nullable":true,"enum":["inbound","outbound",null],"description":"Which way the call or message went. Null for data.","example":"outbound"},"counterpartyCountryCode":{"type":"string","nullable":true,"description":"ISO-2 country of the other party. Null for data.","example":"DK"},"networkType":{"type":"string","nullable":true,"description":"Data records only.","example":"5G"},"userId":{"type":"string","nullable":true,"description":"The end-user this usage belongs to, or null when the number is not attached to one.","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01"},"date":{"type":"string","description":"Calendar day the usage is billed under, YYYY-MM-DD.","example":"2026-09-11"},"totalPrice":{"type":"string","nullable":true,"description":"What this record costs, as a decimal string so no precision is lost. A connected voice call may also carry a one-off connection fee, which is included here and is not derivable from unitPrice. Null until the record is rated, and on usage covered by a pool.","example":"0.043200"},"unitPrice":{"type":"string","nullable":true,"description":"The rate applied, as a decimal string. Priced per minute for voice, per binary megabyte (1024²) for data, and per message for SMS and MMS — so for voice and data this is not the same unit `amount` is counted in. Null until the record is rated.","example":"0.004320"},"currency":{"type":"string","nullable":true,"description":"ISO 4217 currency of the prices. Null until rated.","example":"EUR"},"rateId":{"type":"string","nullable":true,"description":"The rate that priced this record, for reconciling a bill line by line. Null until rated.","example":"rate_01j9v2k8f3m4n5p6q7r8s9t0u1"}},"required":["id","type","provider","msisdn","timeStarted","timeEnded","amount","unit","servingCountryCode","usageClass","counterpartyMsisdn","callDirection","counterpartyCountryCode","networkType","userId","date","totalPrice","unitPrice","currency","rateId"]},"AnalyticsResponse":{"type":"object","properties":{"usage":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/RegionalIntervalUsage"},"description":"Data usage per interval, in bytes."},"voice":{"type":"array","items":{"$ref":"#/components/schemas/LocationIntervalUsage"},"description":"Voice usage per interval, in seconds."},"sms":{"type":"array","items":{"$ref":"#/components/schemas/LocationIntervalUsage"},"description":"SMS usage per interval, as a count."}},"required":["data","voice","sms"],"description":"One series per usage type, bucketed by the requested interval."},"metadata":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/RegionalUsageMetadata"},"voice":{"$ref":"#/components/schemas/LocationUsageMetadata"},"sms":{"$ref":"#/components/schemas/LocationUsageMetadata"}},"required":["data","voice","sms"],"description":"Highest, lowest and average interval for each series, so you need not compute them."}},"required":["usage","metadata"]},"RegionalIntervalUsage":{"type":"object","properties":{"interval":{"type":"string","description":"The bucket this usage falls in, as YYYY-MM-DD for a day or YYYY-MM for a month.","example":"2026-09-11"},"usage":{"$ref":"#/components/schemas/RegionalUsage"}},"required":["interval","usage"]},"RegionalUsage":{"type":"object","properties":{"total":{"type":"number","description":"Usage across every region, in bytes.","example":10485760}},"required":["total"],"additionalProperties":{"type":"number"},"description":"Data usage for one interval: `total`, plus one property per region the usage was served in, keyed by region name."},"LocationIntervalUsage":{"type":"object","properties":{"interval":{"type":"string","description":"The bucket this usage falls in, as YYYY-MM-DD for a day or YYYY-MM for a month.","example":"2026-09-11"},"usage":{"$ref":"#/components/schemas/LocationUsage"}},"required":["interval","usage"]},"LocationUsage":{"type":"object","properties":{"local":{"type":"number","description":"Usage inside the home market.","example":1240},"international":{"type":"number","description":"Usage to or from another country.","example":310},"total":{"type":"number","description":"Local and international added together.","example":1550}},"required":["local","international","total"],"description":"Voice or SMS usage for one interval, split by whether it stayed in the home market."},"RegionalUsageMetadata":{"type":"object","properties":{"highest":{"allOf":[{"$ref":"#/components/schemas/RegionalIntervalUsage"},{"description":"The interval with the most usage in the window."}]},"lowest":{"allOf":[{"$ref":"#/components/schemas/RegionalIntervalUsage"},{"description":"The interval with the least usage in the window."}]},"average":{"allOf":[{"$ref":"#/components/schemas/RegionalUsage"},{"description":"Mean usage per interval across the window."}]}},"required":["highest","lowest","average"],"description":"Summary of the data series over the whole window."},"LocationUsageMetadata":{"type":"object","properties":{"highest":{"allOf":[{"$ref":"#/components/schemas/LocationIntervalUsage"},{"description":"The interval with the most usage in the window."}]},"lowest":{"allOf":[{"$ref":"#/components/schemas/LocationIntervalUsage"},{"description":"The interval with the least usage in the window."}]},"average":{"allOf":[{"$ref":"#/components/schemas/LocationUsage"},{"description":"Mean usage per interval across the window."}]}},"required":["highest","lowest","average"],"description":"Summary of the voice or SMS series over the whole window."},"ListDataPoolsResponse":{"type":"object","properties":{"pools":{"type":"array","items":{"$ref":"#/components/schemas/DataPool"},"description":"Every pool your organization holds."}},"required":["pools"]},"DataPool":{"type":"object","properties":{"poolId":{"type":"string","description":"UUID of the data pool","example":"6b9a0c74-51d2-4e83-9f16-2a7c8d0e5b34"},"regionId":{"type":"string","description":"Identifier of the region this pool covers","example":"eu-zone-1"},"regionName":{"type":"string","description":"Display name of the region this pool covers","example":"Europe"},"totalAmountGB":{"type":"number","description":"Total size of the pool in GB","example":500},"consumedGB":{"type":"number","description":"Data consumed from the pool so far, in GB","example":312.4},"remainingGB":{"type":"number","description":"Data still available in the pool, in GB","example":187.6},"expirationDate":{"type":"string","description":"Date the pool expires, as an ISO date (YYYY-MM-DD)","example":"2026-12-31"},"hasActiveRestrictions":{"type":"boolean","description":"Whether any number drawing on this pool is currently restricted","example":false}},"required":["poolId","regionId","regionName","totalAmountGB","consumedGB","remainingGB","expirationDate","hasActiveRestrictions"]},"ListPoolMembersResponse":{"type":"object","properties":{"poolId":{"type":"string","description":"UUID of the pool these members draw on.","example":"6b9a0c74-51d2-4e83-9f16-2a7c8d0e5b34"},"members":{"type":"array","items":{"$ref":"#/components/schemas/PoolMember"},"description":"Every line drawing on this pool."}},"required":["poolId","members"]},"PoolMember":{"type":"object","properties":{"userId":{"type":"string","description":"UUID of the user drawing on the pool","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01"},"msisdn":{"type":"string","nullable":true,"description":"Phone number in E.164 format","example":"+4520123456"},"numberType":{"type":"string","nullable":true,"enum":["local","travel",null],"description":"Which line draws on the pool","example":"local"},"firstName":{"type":"string","nullable":true,"description":"First name of the user holding the line, or null.","example":"Anna"},"lastName":{"type":"string","nullable":true,"description":"Last name of the user holding the line, or null.","example":"Holm"},"email":{"type":"string","nullable":true,"description":"Email address of the user holding the line, or null.","example":"anna.holm@acme.example"},"activationDate":{"type":"string","description":"Date the member joined the pool (YYYY-MM-DD)","example":"2026-09-01"},"terminationDate":{"type":"string","nullable":true,"description":"Date the member left the pool (YYYY-MM-DD). Null while the line is still drawing on it.","example":"2026-12-31"},"usageBytes":{"type":"number","description":"Bytes the member has drawn from the pool across all their lines. A member with several lines is listed once per line, each row carrying the same total, so add it once per userId.","example":10485760}},"required":["userId","msisdn","numberType","firstName","lastName","email","activationDate","terminationDate","usageBytes"]},"RatesResponse":{"type":"object","properties":{"market":{"type":"string","description":"The market that was priced.","example":"DE"},"servingCountry":{"type":"string","nullable":true,"description":"The country the calls were priced from — the requested one, or the market when none was sent. Null for ROAMING_DATA, which prices each visited country in `rates`.","example":"DE"},"direction":{"type":"string","nullable":true,"enum":["outbound","inbound",null],"description":"The direction the list was priced for — the requested one, or outbound when none was sent. Null for ROAMING_DATA, which has no direction.","example":"outbound"},"asOfDate":{"type":"string","format":"date","description":"The day the list was priced for — the requested one, or today when none was sent.","example":"2026-09-18"},"rates":{"type":"array","items":{"$ref":"#/components/schemas/Rate"},"description":"One entry per country — every destination but the serving country for calling, every visited country for data. A country that costs nothing is listed at 0."}},"required":["market","servingCountry","direction","asOfDate","rates"]},"Rate":{"type":"object","properties":{"country":{"type":"string","description":"ISO 3166-1 alpha-2 country the price applies to — the destination for calling/SMS, the visited country for data.","example":"DE"},"ratePerUnit":{"type":"number","description":"Price per unit in `currency`, to six decimal places. `0` means the country costs nothing — either a route priced free (calls inside the EU/EEA, under roam-like-at-home) or one we publish no pay-as-you-go price for, such as a roaming-data country included in the plan.","example":0.12},"unit":{"type":"string","description":"minutes (voice), count (SMS/MMS), or mb (data). Set even when the country costs nothing.","example":"minutes"},"currency":{"type":"string","nullable":true,"description":"The market's ISO 4217 currency — the provider's native one, the same for every country in the list. Null only when nothing in the market is priced, leaving no currency to quote.","example":"EUR"},"validFrom":{"type":"string","nullable":true,"description":"When this rate took effect (ISO-8601), or null if unknown.","example":"2026-01-01"}},"required":["country","ratePerUnit","unit","currency","validFrom"]},"ListCostThresholdsResponse":{"type":"object","properties":{"thresholds":{"type":"array","items":{"$ref":"#/components/schemas/CostThreshold"},"description":"The organization's thresholds in force or opening next month, and the named team's or user's own."},"currency":{"type":"string","description":"ISO 4217 code a threshold written for the named team or user would carry. Absent when neither is named.","example":"EUR"}},"required":["thresholds"]},"SetCostThresholdResponse":{"type":"object","properties":{"threshold":{"allOf":[{"$ref":"#/components/schemas/CostThreshold"},{"description":"The threshold as written."}]},"appliesFromNextMonth":{"type":"boolean","description":"True when someone in scope has already spent more than the new amount this month, so it opens next month rather than now.","example":false},"releasedNumberCount":{"type":"integer","description":"Lines whose pause was lifted because the raised amount put their user back under it.","example":0}},"required":["threshold","appliesFromNextMonth","releasedNumberCount"]}},"parameters":{}},"paths":{"/v1/users":{"get":{"operationId":"listUsers","summary":"List users","description":"Lists all users in your organization with pagination and optional filtering.\n\nYou can filter the results by exact email address or employee ID. Use pagination parameters to control the number of results returned per page.","security":[{"ApiKeyAuth":["users:read"]}],"x-telgea-audience":"both","tags":["Users"],"x-telgea-problem-types":[],"parameters":[{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"default":1,"description":"Page to return, starting at 1.","example":1},"required":false,"description":"Page to return, starting at 1.","name":"page","in":"query"},{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":50,"default":10,"description":"Items per page, at most 50. Defaults to 10.","example":10},"required":false,"description":"Items per page, at most 50. Defaults to 10.","name":"pageSize","in":"query"},{"schema":{"type":"string","format":"email","description":"Filter by exact email address","example":"anna.holm@acme.example"},"required":false,"description":"Filter by exact email address","name":"email","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Filter by exact employee ID","example":"EMP-0142"},"required":false,"description":"Filter by exact employee ID","name":"employeeId","in":"query"}],"responses":{"200":{"description":"Successfully retrieved list of users","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListUsersResponse"},"example":{"page":1,"pageSize":10,"itemsCount":2,"items":[{"id":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","email":"anna.holm@acme.example","firstName":"Anna","lastName":"Holm","teamId":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70","employeeId":"EMP-0142","costCode":"CC-4100"},{"id":"3e5d1b42-7c90-4a18-b6f3-0d9e2a4c7f85","email":"jonas.berg@acme.example","firstName":"Jonas","lastName":"Berg","teamId":null,"employeeId":null,"costCode":null}]}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to list users","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}},"post":{"operationId":"createUser","summary":"Create a new user","description":"Creates a new user in your organization. Use this endpoint to onboard employees or contractors who need mobile numbers or telecommunications resources.\n\nOnce created, the user can be assigned to teams, associated with billing entities, and provisioned with SIM cards through the user-plans endpoint.","security":[{"ApiKeyAuth":["users:create"]}],"x-telgea-audience":"both","tags":["Users"],"x-telgea-problem-types":["https://developer.telgea.com/errors/hub/USER_ALREADY_EXISTS_WITH_EMAIL"],"parameters":[{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUserBody"},"examples":{"full":{"summary":"Every field","value":{"email":"anna.holm@acme.example","firstName":"Anna","lastName":"Holm","teamId":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70","costCode":"CC-4100","employeeId":"EMP-0142"}},"minimal":{"summary":"Required fields only","value":{"email":"anna.holm@acme.example","firstName":"Anna","lastName":"Holm"}}}}}},"responses":{"200":{"description":"User created successfully. Returns the created user object including the auto-generated user ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUserResponse"},"example":{"id":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","email":"anna.holm@acme.example","firstName":"Anna","lastName":"Holm"}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to create users","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"`teamId` names no team in your organization","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"409":{"description":"No user was created: another user already holds this email address.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/users/{userId}":{"patch":{"operationId":"updateUser","summary":"Update a user","description":"Updates an existing user's information. All fields are optional - only provide the fields you want to update.\n\nYou can update basic information like name, as well as organizational assignments like team membership, cost center codes, and employee IDs.","security":[{"ApiKeyAuth":["users:update"]}],"x-telgea-audience":"both","tags":["Users"],"x-telgea-problem-types":["https://developer.telgea.com/errors/hub/USER_ALREADY_EXISTS_WITH_EMAIL","https://developer.telgea.com/errors/hub/USER_NOT_FOUND"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","description":"UUID of the user."},"required":true,"description":"UUID of the user.","name":"userId","in":"path"},{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUserBody"},"examples":{"full":{"summary":"Every field","value":{"email":"anna.holm@acme.example","firstName":"Anna","lastName":"Holm-Jensen","teamId":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70","costCode":"CC-4100","employeeId":"EMP-0142"}},"minimal":{"summary":"Change one field","value":{"lastName":"Holm-Jensen"}}}}}},"responses":{"204":{"description":"User updated successfully. No content returned."},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to update users","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"User not found, or `teamId` names no team in your organization","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"409":{"description":"No change was made: another user already holds this email address.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}},"delete":{"operationId":"deleteUser","summary":"Delete a user","description":"Permanently deletes a user from your organization.\n\n**Important Restrictions:**\n- Cannot delete users with active phone numbers (must terminate user plan first)\n- Cannot delete admin users\n- Cannot delete yourself\n\nBefore deleting, ensure the user's local number is in SUSPENDED, DEACTIVATED state, or doesn't exist.","security":[{"ApiKeyAuth":["users:delete"]}],"x-telgea-audience":"both","tags":["Users"],"x-telgea-problem-types":["https://developer.telgea.com/errors/hub/USER_NOT_FOUND"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","description":"UUID of the user."},"required":true,"description":"UUID of the user.","name":"userId","in":"path"},{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"responses":{"204":{"description":"User deleted successfully. No content returned."},"400":{"description":"Cannot delete user with active phone numbers","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions, or attempting to delete self or admin user","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"User not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/users/{userId}/cost-thresholds/{usageType}":{"get":{"operationId":"getUserCostThreshold","summary":"Get a user's cost threshold and spend","description":"Where a user stands against their cost threshold on one usage type: the threshold in force for them (their own, else their team's, else the organization's), their spend this month against it, and whether the usage is paused for crossing it.\n\nThe spend is converted into the threshold's currency at the day's exchange rate, so it is approximate; usage already under way may take it past the threshold before it ends.\n\nThresholds are set with `PUT /v1/cost-thresholds`. A usage type with no threshold support yet answers `422`.\n\n**Scope:** `users:read`.","security":[{"ApiKeyAuth":["users:read"]}],"x-telgea-audience":"both","tags":["Users"],"x-telgea-problem-types":["https://developer.telgea.com/errors/order/USAGE_THRESHOLD_USER_OUTSIDE_ORGANIZATION","https://developer.telgea.com/errors/order/USAGE_THRESHOLD_TYPE_NOT_SUPPORTED"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","description":"UUID of the user."},"required":true,"description":"UUID of the user.","name":"userId","in":"path"},{"schema":{"type":"string","enum":["DATA","VOICE","SMS","MMS"],"description":"The usage type the threshold is on. `VOICE` is international calling: reaching it pauses international calls and SMS on the person's lines, where their market offers the pause. Other types answer `422` until the platform can enforce them.","example":"VOICE"},"required":true,"description":"The usage type the threshold is on. `VOICE` is international calling: reaching it pauses international calls and SMS on the person's lines, where their market offers the pause. Other types answer `422` until the platform can enforce them.","name":"usageType","in":"path"}],"responses":{"200":{"description":"The user's threshold, spend and pause on the usage type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserCostThresholdResponse"},"example":{"threshold":{"id":"5d0b2c1e-7f3a-4b6c-9e8d-2a1f0c3b4d5e","usageType":"VOICE","scope":"team","teamId":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70","userId":null,"maxAmount":50,"currency":"EUR","period":"monthly","validFrom":"2026-10-01T00:00:00.000Z","validTo":null},"spend":{"amount":12.4,"currency":"EUR","periodStart":"2026-10-01T00:00:00.000Z"},"pausedUntil":null}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to view users","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"No user in your organization has this id, so nothing was read or changed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"422":{"description":"No threshold can stand on this usage type yet, so nothing was read or changed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnprocessableEntityError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/teams":{"get":{"operationId":"listTeams","summary":"List all teams","description":"Retrieves a paginated list of all teams in your organization. Teams are organizational units used to group users for billing, access control, and reporting purposes.\n\nUse the `page` and `pageSize` query parameters to navigate through large result sets.","security":[{"ApiKeyAuth":["teams:read"]}],"x-telgea-audience":"enterprise","tags":["Teams"],"x-telgea-problem-types":[],"parameters":[{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"default":1,"description":"Page to return, starting at 1.","example":1},"required":false,"description":"Page to return, starting at 1.","name":"page","in":"query"},{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":50,"default":50,"description":"Items per page, at most 50. Defaults to 50.","example":50},"required":false,"description":"Items per page, at most 50. Defaults to 50.","name":"pageSize","in":"query"}],"responses":{"200":{"description":"Successfully retrieved teams. Returns a paginated list with total count.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTeamsResponse"},"example":{"page":1,"pageSize":50,"itemsCount":3,"items":[{"id":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70","name":"Field Sales","emoji":"🚀","costCode":"CC-4100","memberCount":12,"isDefault":false},{"id":"7c2e9f10-4b83-4d55-a0e6-1f8b3d6c2a94","name":"Support","emoji":null,"costCode":null,"memberCount":4,"isDefault":false},{"id":"2b8d4e61-9c37-4f02-b5a8-6e1d0c7f3a59","name":"Unassigned","emoji":"▫️","costCode":null,"memberCount":7,"isDefault":true}]}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to list teams","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}},"post":{"operationId":"createTeam","summary":"Create a new team","description":"Creates a new team in your organization. Teams help organize users into logical groups for billing, access control, and reporting.\n\nAfter creating a team, you can assign users to it and associate it with billing entities for billing allocation.","security":[{"ApiKeyAuth":["teams:create"]}],"x-telgea-audience":"enterprise","tags":["Teams"],"x-telgea-problem-types":["https://developer.telgea.com/errors/hub/USER_NOT_FOUND"],"parameters":[{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTeamBody"},"examples":{"full":{"summary":"Every field","value":{"name":"Field Sales","emoji":"🚀","costCode":"IT 5000","userIds":["9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01"]}},"minimal":{"summary":"Required fields only","value":{"name":"Field Sales"}}}}}},"responses":{"200":{"description":"Team created successfully. Returns the created team object including the auto-generated team ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTeamResponse"},"example":{"id":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70"}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to create teams","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"A user id in `userIds` is not in your organization","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/teams/{teamId}":{"patch":{"operationId":"updateTeam","summary":"Update a team","description":"Updates an existing team's information. All fields are optional - only provide the fields you want to update.\n\nYou can update basic information like name, emoji, and cost center code. Providing `userIds` replaces the team's full membership: users in the list are added, and users not in the list move to the default team, Unassigned.\n\nThe default team (`isDefault: true` in GET /v1/teams) cannot be updated.","security":[{"ApiKeyAuth":["teams:update"]}],"x-telgea-audience":"enterprise","tags":["Teams"],"x-telgea-problem-types":["https://developer.telgea.com/errors/hub/USER_NOT_FOUND","https://developer.telgea.com/errors/hub/DEFAULT_TEAM_IMMUTABLE"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70","description":"UUID of the team."},"required":true,"description":"UUID of the team.","name":"teamId","in":"path"},{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTeamBody"},"examples":{"full":{"summary":"Every field","value":{"name":"Field Sales EMEA","emoji":"🌍","costCode":"IT 5001","userIds":["9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01"]}},"minimal":{"summary":"Rename the team","value":{"name":"Field Sales EMEA"}}}}}},"responses":{"204":{"description":"Team updated successfully. No content returned."},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to update teams","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"Team not found, or a user id in `userIds` is not in your organization","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"409":{"description":"This is your organization's default team, Unassigned, so it cannot be changed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/user-plans":{"get":{"operationId":"listUserPlans","summary":"List all user plans","description":"Retrieves a paginated list of user plans in your organization. A user plan represents the association between a user and their telecommunications resources (SIM cards, phone numbers, data plans).\n\nUse filters to narrow results by user, team, or plan status. Supports pagination for large datasets.","security":[{"ApiKeyAuth":["user-plans:read"]}],"x-telgea-audience":"enterprise","tags":["User Plans"],"x-telgea-problem-types":[],"parameters":[{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"default":1,"description":"Page to return, starting at 1.","example":1},"required":false,"description":"Page to return, starting at 1.","name":"page","in":"query"},{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":100,"default":50,"description":"Items per page, at most 100. Defaults to 50.","example":50},"required":false,"description":"Items per page, at most 100. Defaults to 50.","name":"pageSize","in":"query"},{"schema":{"type":"string","enum":["firstName","localPhoneNumber","status","teamName"],"description":"Field to sort by. Defaults to the order the plans were created in.","example":"firstName"},"required":false,"description":"Field to sort by. Defaults to the order the plans were created in.","name":"orderBy","in":"query"},{"schema":{"type":"string","enum":["asc","desc"],"description":"Sort direction. Only meaningful together with orderBy.","example":"asc"},"required":false,"description":"Sort direction. Only meaningful together with orderBy.","name":"orderDirection","in":"query"}],"responses":{"200":{"description":"Successfully retrieved user plans. Returns a paginated list with total count and plan details.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListUserPlansResponse"},"example":{"page":1,"pageSize":50,"itemsCount":2,"items":[{"id":"f7a8b9c0-d1e2-3456-f789-012345678901","userId":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","firstName":"Anna","lastName":"Holm","email":"anna.holm@acme.example","status":"ACTIVE","localPhoneNumber":"+4520123456","teamId":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70","teamName":"Field Sales"},{"id":"5a1c8e37-2d64-4b90-8fa2-6c0e9d4b7132","userId":"3e5d1b42-7c90-4a18-b6f3-0d9e2a4c7f85","firstName":"Jonas","lastName":"Berg","email":"jonas.berg@acme.example","status":"PROVISIONING","localPhoneNumber":null,"teamId":null,"teamName":null}]}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to list user plans","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}},"post":{"operationId":"createUserPlan","summary":"Create a new user plan","description":"Provisions a local line for an existing user: a market-bound phone number and the eSIM that carries it.\n\nThe user must exist in your organization before creating a plan. Use the users endpoint to create users first if needed.\n\n**Provisioning flow:**\n1. The user plan is created and returns `PROVISIONING` — a local number id, and `travelNumberId: null`\n2. A SIM is assigned from available inventory and the number allocated with the local market's operator\n3. The plan reaches `ACTIVE`, and GET /v1/user-plans/{userId} carries the local number's `sim.activationCode`\n\nA travel eSIM is **not** part of this call. One is added afterwards, on its own, and only for an organization whose contract includes one and which holds a data pool outside its home zone — poll GET /v1/user-plans/{userId} to see whether a `travelNumber` appeared.\n\nTo install the eSIM yourself, take `sim.activationCode` — a GSMA `LPA:1$…` string — from GET /v1/user-plans/{userId} and encode it as a QR code; any QR library will do.\n\nOrganizations with Telgea's end-user communications enabled also send the user installation instructions by email. White-label integrations have them switched off, so that activation code is the only delivery and presenting it is yours to do.","security":[{"ApiKeyAuth":["user-plans:create"]}],"x-telgea-audience":"enterprise","tags":["User Plans"],"x-telgea-problem-types":["https://developer.telgea.com/errors/hub/USER_NOT_FOUND","https://developer.telgea.com/errors/order/CATALOGUE_ENTRY_UNAVAILABLE","https://developer.telgea.com/errors/order/HOME_PLAN_ALREADY_ACTIVE","https://developer.telgea.com/errors/hub/ORGANIZATION_VERIFICATION_REQUIRED"],"parameters":[{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUserPlanBody"},"example":{"userId":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","countryCode":"DK"}}}},"responses":{"200":{"description":"User plan created successfully. Returns the complete plan details including assigned phone numbers and SIM information.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUserPlanResponse"},"example":{"status":"PROVISIONING","localNumberId":"8238c1b9-c2c0-4455-9b03-4bd787052709","travelNumberId":null}}}},"400":{"description":"Request failed schema validation, or the country code is not a supported ISO 3166-1 alpha-2 code","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions, or the requested country is not available for your organization: nothing it can buy covers the country, or the country requires business verification your organization has not passed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"User not found in your organization, or no local plan is available for the requested market.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"409":{"description":"The user already has an active plan, so nothing was created.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/user-plans/search":{"get":{"operationId":"searchUserPlans","x-telgea-sample-query":{"email":"anna.holm@acme.example"},"summary":"Search for a user plan","description":"Search for a user plan by email address, phone number (MSISDN), or ICCID (SIM card identifier). This endpoint is useful for looking up user plans when you only have contact identifiers.\n\nExactly one search parameter (email, msisdn, or iccid) must be provided.\n\nThe phone number must be in E.164 format (e.g., +4520123456).","security":[{"ApiKeyAuth":["user-plans:read"]}],"x-telgea-audience":"enterprise","tags":["User Plans"],"x-telgea-problem-types":[],"parameters":[{"schema":{"type":"string","format":"email","description":"Email address of the user to search for","example":"user@example.com"},"required":false,"description":"Email address of the user to search for","name":"email","in":"query"},{"schema":{"type":"string","description":"Phone number in E.164 format to search for","example":"+4520123456"},"required":false,"description":"Phone number in E.164 format to search for","name":"msisdn","in":"query"},{"schema":{"type":"string","minLength":1,"description":"ICCID (SIM card identifier) to search for","example":"8944500102198304826"},"required":false,"description":"ICCID (SIM card identifier) to search for","name":"iccid","in":"query"}],"responses":{"200":{"description":"Successfully found the user plan. Returns the same detailed information as the get user plan details endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPlanDetails"},"example":{"userId":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","email":"anna.holm@acme.example","firstName":"Anna","lastName":"Holm","status":"ACTIVE","teamId":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70","terminationScheduledAt":null,"localNumber":{"id":"8238c1b9-c2c0-4455-9b03-4bd787052709","type":"local","countryCode":"DK","phoneNumber":"+4520123456","state":"READY","sim":{"iccid":"8945000000000000001","activationCode":"LPA:1$SMDP.TELGEA.COM$34682-73063-9140","pinOne":"1234","pinTwo":"5678","pukOne":"12345678","pukTwo":"87654321"}},"travelNumber":null}}}},"400":{"description":"Exactly one of email, msisdn or iccid must be provided, and it must be well formed. Sending none, or more than one, is refused here.","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to search user plans","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"No user plan found matching the provided search criteria","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/user-plans/{userId}":{"get":{"operationId":"getUserPlan","summary":"Get user plan details","description":"Retrieves detailed information about a specific user's telecommunications plan, including assigned phone numbers, SIM card details, data allowances, and usage statistics.\n\nUse this endpoint to view the complete telecommunications setup for a particular user.","security":[{"ApiKeyAuth":["user-plans:read"]}],"x-telgea-audience":"enterprise","tags":["User Plans"],"x-telgea-problem-types":["https://developer.telgea.com/errors/hub/USER_NOT_FOUND"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","description":"UUID of the user whose plan this is."},"required":true,"description":"UUID of the user whose plan this is.","name":"userId","in":"path"}],"responses":{"200":{"description":"Successfully retrieved user plan details. Includes phone numbers, SIM information, and plan configuration.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPlanDetails"},"example":{"userId":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","email":"anna.holm@acme.example","firstName":"Anna","lastName":"Holm","status":"ACTIVE","teamId":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70","terminationScheduledAt":null,"localNumber":{"id":"8238c1b9-c2c0-4455-9b03-4bd787052709","type":"local","countryCode":"DK","phoneNumber":"+4520123456","state":"READY","sim":{"iccid":"8945000000000000001","activationCode":"LPA:1$SMDP.TELGEA.COM$34682-73063-9140","pinOne":"1234","pinTwo":"5678","pukOne":"12345678","pukTwo":"87654321"}},"travelNumber":null}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to view user plan details","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"User not found. The specified user ID does not belong to a user in your organization.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/user-plans/{userId}/sim-replacement":{"post":{"operationId":"replaceUserPlanSim","summary":"Replace a SIM card","description":"Initiates a SIM card replacement (eSIM swap) for a specific number within a user's plan. This provisions a new eSIM and deactivates the previous one.\n\n> **Important:** This endpoint should **only** be used when the end-user changes devices and the existing eSIM activation QR code (LPA string) has been confirmed to be expired or no longer working. Do **not** use this endpoint to troubleshoot connectivity issues — contact support instead.\n\n**Rate limit:** one replacement per number inside the cooldown your organization's SIM-swap offering sets, counted from when the number's last replacement finished — and once per calendar day for a German number. A request inside the window gets a `429` naming when to retry.\n\n**Flow:**\n1. A new eSIM profile is provisioned and the old SIM is deactivated\n2. Until the new profile is ready, GET /v1/user-plans/{userId} reports the number with `sim: null` — its state is `REPLACING`, and SIM details are published only in `READY`\n3. Back in `READY`, the number's `sim.activationCode` is the new one to render as a QR code\n\nOrganizations with Telgea's end-user communications enabled also email the user the new activation code. White-label integrations have them switched off and present it themselves.\n\n**Scopes:** `numbers:replace-sim` and `user-plans:read` — the number is checked against the addressed user's plan before any replacement is started.","security":[{"ApiKeyAuth":["numbers:replace-sim","user-plans:read"]}],"x-telgea-audience":"enterprise","tags":["User Plans"],"x-telgea-problem-types":["https://developer.telgea.com/errors/hub/USER_NOT_FOUND","https://developer.telgea.com/errors/order/ORDER_COOLDOWN_ACTIVE"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","description":"UUID of the user whose plan this is."},"required":true,"description":"UUID of the user whose plan this is.","name":"userId","in":"path"},{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplaceSimBody"},"example":{"numberId":"8238c1b9-c2c0-4455-9b03-4bd787052709"}}}},"responses":{"202":{"description":"SIM replacement request accepted and processed asynchronously. Poll GET /v1/user-plans/{userId} until the number is READY again with its new SIM.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplaceSimResponse"},"example":{"status":"accepted"}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to replace SIM cards","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"User plan or number not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"The number's last SIM replacement finished too recently for another: your organization's SIM-swap offering sets the cooldown (a German number is replaced once per calendar day), and `Retry-After` says when to retry. The same status also answers a key that has used its request quota.","headers":{"Retry-After":{"schema":{"type":"string","example":"Fri, 18 Sep 2026 12:00:00 GMT"},"required":true,"description":"When to retry. An HTTP-date — the earliest moment a replacement is accepted again — for the cooldown; the seconds until the window resets for a key that has used its request quota."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"},"example":{"type":"https://developer.telgea.com/errors/order/ORDER_COOLDOWN_ACTIVE","title":"Too soon after the last one","status":429,"detail":"The last one of these for this number finished too recently for another, so nothing was placed.","code":"TOO_MANY_REQUESTS","requestId":"req_123"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/user-plans/{userId}/data-restriction":{"post":{"operationId":"restrictUserPlanData","summary":"Stop a customer's mobile data","description":"Stops mobile data for one of your customers — for someone who has used up what they paid for. Calls and texts keep working; use the suspension endpoint to stop the whole line.\n\nThe call returns once the change has taken effect at the network, so a `200` means the data is genuinely off. Nothing here is queued for later.\n\nStopping data that is already stopped returns `409` and changes nothing. Our own automated processes never undo a stop you made — only `DELETE` on this path does.\n\nNot every market offers stopping data on its own. Where it does not, this returns `422` and nothing changes — the Markets page in the documentation lists which is which.","security":[{"ApiKeyAuth":["numbers:suspend"]}],"x-telgea-audience":"enterprise","tags":["User Plans"],"x-telgea-problem-types":["https://developer.telgea.com/errors/consumption/DATA_ALREADY_STOPPED","https://developer.telgea.com/errors/consumption/SUBSCRIBER_HAS_NO_DATA_POOL","https://developer.telgea.com/errors/consumption/DATA_STOP_NOT_SUPPORTED","https://developer.telgea.com/errors/consumption/DATA_STOP_NOT_APPLIED","https://developer.telgea.com/errors/hub/USER_NOT_FOUND"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","description":"UUID of the user whose plan this is."},"required":true,"description":"UUID of the user whose plan this is.","name":"userId","in":"path"},{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataRestrictionBody"},"examples":{"full":{"summary":"With a reason","value":{"reason":"Customer exceeded their agreed data allowance."}},"minimal":{"summary":"No reason given","value":{}}}}}},"responses":{"200":{"description":"Data stopped. Lists the numbers the stop reached and when it took effect.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataRestrictionResponse"},"example":{"numbers":["+4520123456"],"effectiveAt":"2026-09-14T09:30:00.000Z"}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions for this action","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"User not found. The specified user ID does not belong to a user in your organization.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"409":{"description":"Already in the state you asked for, so nothing was changed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}}},"422":{"description":"Nothing was changed: the subscriber belongs to no data pool, so there is no data to stop, or their market does not offer stopping data on its own.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnprocessableEntityError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}},"delete":{"operationId":"liftUserPlanDataRestriction","summary":"Restore a customer's mobile data","description":"Undoes a stop made with `POST /v1/user-plans/{userId}/data-restriction`, and returns once data is live again at the network.\n\nRestoring data that is not stopped returns `409`. Data stays off if the customer is also over an allowance you set — clear that first.","security":[{"ApiKeyAuth":["numbers:unsuspend"]}],"x-telgea-audience":"enterprise","tags":["User Plans"],"x-telgea-problem-types":["https://developer.telgea.com/errors/consumption/DATA_NOT_STOPPED","https://developer.telgea.com/errors/consumption/DATA_RESTORE_NOT_APPLIED","https://developer.telgea.com/errors/hub/USER_NOT_FOUND"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","description":"UUID of the user whose plan this is."},"required":true,"description":"UUID of the user whose plan this is.","name":"userId","in":"path"},{"schema":{"type":"string","maxLength":200,"description":"Free text kept with the change.","example":"Customer settled their account."},"required":false,"description":"Free text kept with the change.","name":"reason","in":"query"},{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"responses":{"200":{"description":"Data restored. Lists the numbers the restore reached and when it took effect.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataRestrictionResponse"},"example":{"numbers":["+4520123456"],"effectiveAt":"2026-09-14T09:30:00.000Z"}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions for this action","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"User not found. The specified user ID does not belong to a user in your organization.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"409":{"description":"Already in the state you asked for, so nothing was changed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/user-plans/{userId}/suspension":{"post":{"operationId":"suspendUserPlanNumber","summary":"Suspend a customer's number","description":"Stops all traffic on one of a customer's numbers, domestic and international — for a phone that has been lost or stolen. To stop only mobile data and leave the line usable, use the data-restriction endpoint.\n\nThe call returns once the line is down at the network, so a `200` means the service is genuinely stopped.\n\nSuspending a number that is already suspended returns `409` and changes nothing.\n\nNot every market offers suspension. Where it does not, this returns `400` and the line stays live — the Markets page in the documentation lists which is which.","security":[{"ApiKeyAuth":["numbers:suspend"]}],"x-telgea-audience":"enterprise","tags":["User Plans"],"x-telgea-problem-types":["https://developer.telgea.com/errors/number-service/NUMBER_ALREADY_IN_STATE","https://developer.telgea.com/errors/number-service/NUMBER_MISSING_MSISDN","https://developer.telgea.com/errors/number-service/NUMBER_OPERATION_NOT_SUPPORTED","https://developer.telgea.com/errors/number-service/NUMBER_NOT_FOUND","https://developer.telgea.com/errors/hub/USER_NOT_FOUND"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","description":"UUID of the user whose plan this is."},"required":true,"description":"UUID of the user whose plan this is.","name":"userId","in":"path"},{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuspensionBody"},"example":{"numberId":"8238c1b9-c2c0-4455-9b03-4bd787052709"}}}},"responses":{"200":{"description":"Number suspended. Lists the number the suspension reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuspensionResponse"},"example":{"numbers":["+4520123456"]}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions for this action","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"User plan or number not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"409":{"description":"Already in the state you asked for, so nothing was changed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}},"delete":{"operationId":"unsuspendUserPlanNumber","summary":"Restore a customer's number","description":"Undoes a suspension made with `POST /v1/user-plans/{userId}/suspension`, and returns once the line is live again at the network.\n\nRestoring a number that is not suspended returns `409`.","security":[{"ApiKeyAuth":["numbers:unsuspend"]}],"x-telgea-audience":"enterprise","tags":["User Plans"],"x-telgea-problem-types":["https://developer.telgea.com/errors/number-service/NUMBER_ALREADY_IN_STATE","https://developer.telgea.com/errors/number-service/NUMBER_MISSING_MSISDN","https://developer.telgea.com/errors/number-service/NUMBER_OPERATION_NOT_SUPPORTED","https://developer.telgea.com/errors/number-service/NUMBER_NOT_FOUND","https://developer.telgea.com/errors/hub/USER_NOT_FOUND"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","description":"UUID of the user whose plan this is."},"required":true,"description":"UUID of the user whose plan this is.","name":"userId","in":"path"},{"schema":{"type":"string","format":"uuid","description":"UUID of the number to restore.","example":"8238c1b9-c2c0-4455-9b03-4bd787052709"},"required":true,"description":"UUID of the number to restore.","name":"numberId","in":"query"},{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"responses":{"200":{"description":"Number restored. Lists the number the restore reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuspensionResponse"},"example":{"numbers":["+4520123456"]}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions for this action","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"User plan or number not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"409":{"description":"Already in the state you asked for, so nothing was changed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/user-plans/{userId}/termination":{"post":{"operationId":"terminateUserPlan","summary":"End a customer's plan","description":"Ends the customer's line on the date you name — the date they agreed to stop.\n\nThe line is suspended on that date and deactivated at the network 14 days later. The call returns as soon as the termination is scheduled, so a `202` means it is booked, not that the line is already down. Read it back on `GET /v1/user-plans/{userId}` as `terminationScheduledAt`.\n\n**Billing is not prorated.** The customer keeps the period they already bought: the line stops on your date, and billing runs to `activeUntil` in the response. The plan does not renew afterwards.\n\nSend `deleteUser: true` to delete the end-user along with the line. Otherwise the user remains, and `DELETE /v1/users/{userId}` succeeds once the line is suspended — you do not have to wait out the grace period.","security":[{"ApiKeyAuth":["orders:cancel"]}],"x-telgea-audience":"enterprise","tags":["User Plans"],"x-telgea-problem-types":["https://developer.telgea.com/errors/order/TERMINATION_DATE_IN_PAST","https://developer.telgea.com/errors/order/USER_SUBSCRIPTION_NOT_FOUND"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","description":"UUID of the user whose plan this is."},"required":true,"description":"UUID of the user whose plan this is.","name":"userId","in":"path"},{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TerminationBody"},"examples":{"full":{"summary":"Every field","value":{"terminationDate":"2026-10-01","deleteUser":true}},"minimal":{"summary":"Required fields only","value":{"terminationDate":"2026-10-01"}}}}}},"responses":{"202":{"description":"Termination scheduled. States the date, when billing stops, and the lines ending.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TerminationResponse"},"example":{"terminationDate":"2026-10-01","activeUntil":"2026-12-31T00:00:00.000Z","numberIds":["8238c1b9-c2c0-4455-9b03-4bd787052709"]}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions for this action","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"No plan to end exists for this user in your organization","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/numbers":{"get":{"operationId":"listNumbers","summary":"List lines","description":"Retrieves a paginated list of the lines in your organization — the numbers you sell and the eSIMs that carry them.\n\nEvery filter is optional and they combine, so this one endpoint answers both \"the next page of my roster\" and \"the line on this number\". Narrow by `msisdn` or `iccid` to look one up, by `userId` for the lines one customer holds, and by `type` or `state` for a slice of the roster.\n\nA line that was just ordered appears here with `state: null` until its first lifecycle event, and its SIM details are published only once it reaches `READY`.","security":[{"ApiKeyAuth":["numbers:read"]}],"x-telgea-audience":"partner","tags":["Numbers"],"x-telgea-problem-types":[],"parameters":[{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"default":1,"description":"Page to return, starting at 1.","example":1},"required":false,"description":"Page to return, starting at 1.","name":"page","in":"query"},{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":100,"default":50,"description":"Items per page, at most 100. Defaults to 50.","example":50},"required":false,"description":"Items per page, at most 100. Defaults to 50.","name":"pageSize","in":"query"},{"schema":{"type":"string","enum":["createdAt","phoneNumber","type"],"description":"Field to sort by. Defaults to the order the lines were created in. `state` is not sortable: it is derived per line, so sorting by it would resolve the state of every line in your organization before a page could be picked. Narrow by it instead.","example":"createdAt"},"required":false,"description":"Field to sort by. Defaults to the order the lines were created in. `state` is not sortable: it is derived per line, so sorting by it would resolve the state of every line in your organization before a page could be picked. Narrow by it instead.","name":"orderBy","in":"query"},{"schema":{"type":"string","enum":["asc","desc"],"description":"Sort direction. Only meaningful together with orderBy.","example":"asc"},"required":false,"description":"Sort direction. Only meaningful together with orderBy.","name":"orderDirection","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Only the line on this number, in E.164 format. Matched exactly.","example":"+4520123456"},"required":false,"description":"Only the line on this number, in E.164 format. Matched exactly.","name":"msisdn","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Only the line whose eSIM has this ICCID. Matched exactly; a line with no SIM never matches.","example":"8945000000000000001"},"required":false,"description":"Only the line whose eSIM has this ICCID. Matched exactly; a line with no SIM never matches.","name":"iccid","in":"query"},{"schema":{"type":"string","format":"uuid","description":"Only the lines this user holds.","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01"},"required":false,"description":"Only the lines this user holds.","name":"userId","in":"query"},{"schema":{"type":"string","enum":["local","travel"],"description":"Only lines of this kind.","example":"local"},"required":false,"description":"Only lines of this kind.","name":"type","in":"query"},{"schema":{"type":"string","enum":["PENDING","PORTING","PORTING_FAILED","PROVISIONING","READY","REPLACING","CHANGING","SUSPENDING","SUSPENDED","RESTORING","RECONFIGURING","DEACTIVATING","DEACTIVATED","PORTING_DISCARDED","PORTING_OUT","PORTED_OUT"],"description":"Only lines in this state. Costs more than the other filters, since the state of each of your lines is resolved to answer it.","example":"READY"},"required":false,"description":"Only lines in this state. Costs more than the other filters, since the state of each of your lines is resolved to answer it.","name":"state","in":"query"}],"responses":{"200":{"description":"Successfully retrieved lines. Returns a paginated list with the total count.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListNumbersResponse"},"example":{"page":1,"pageSize":50,"itemsCount":2,"items":[{"id":"8238c1b9-c2c0-4455-9b03-4bd787052709","userId":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","type":"local","countryCode":"DK","phoneNumber":"+4520123456","state":"READY","sim":{"iccid":"8945000000000000001","activationCode":"LPA:1$SMDP.TELGEA.COM$34682-73063-9140","pinOne":"1234","pinTwo":"5678","pukOne":"12345678","pukTwo":"87654321"},"createdAt":"2026-09-17T08:15:00.000Z"},{"id":"5a1c8e37-2d64-4b90-8fa2-6c0e9d4b7132","userId":"3e5d1b42-7c90-4a18-b6f3-0d9e2a4c7f85","type":"local","countryCode":"SE","phoneNumber":null,"state":"PROVISIONING","sim":null,"createdAt":"2026-09-18T11:02:00.000Z"}]}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to list lines","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}},"post":{"operationId":"createNumber","summary":"Obtain a line","description":"Obtains a local line for one of your customers: a market-bound phone number and the eSIM that carries it.\n\nThe user must exist in your organization first — create one with POST /v1/users.\n\n**Provisioning flow:**\n1. This call returns the line's id and `state: PROVISIONING`\n2. A SIM is assigned from available inventory and the number allocated with the local market's operator\n3. The line reaches `READY`, and GET /v1/numbers/{numberId} carries its `sim.activationCode`\n\nOrganizations with Telgea's end-user communications enabled also send the user installation instructions by email. White-label integrations have them switched off, so that activation code is the only delivery and presenting it is yours to do.","security":[{"ApiKeyAuth":["numbers:create-local"]}],"x-telgea-audience":"partner","tags":["Numbers"],"x-telgea-problem-types":["https://developer.telgea.com/errors/hub/USER_NOT_FOUND","https://developer.telgea.com/errors/order/CATALOGUE_ENTRY_UNAVAILABLE","https://developer.telgea.com/errors/order/HOME_PLAN_ALREADY_ACTIVE","https://developer.telgea.com/errors/hub/ORGANIZATION_VERIFICATION_REQUIRED"],"parameters":[{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateNumberBody"},"example":{"userId":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","countryCode":"DK"}}}},"responses":{"202":{"description":"Line accepted and being provisioned. Poll GET /v1/numbers/{numberId} until it reaches READY with its SIM.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateNumberResponse"},"example":{"numberId":"8238c1b9-c2c0-4455-9b03-4bd787052709","state":"PROVISIONING"}}}},"400":{"description":"Request failed schema validation, or the country code is not a supported ISO 3166-1 alpha-2 code","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions, or the requested country is not available for your organization: nothing it can buy covers the country, or the country requires business verification your organization has not passed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"User not found in your organization, or no plan is available for the requested market.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"409":{"description":"The user already holds an active line, so nothing was created.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/numbers/{numberId}":{"get":{"operationId":"getNumber","summary":"Get a line","description":"Retrieves one line in full: the number, where it is in the provisioning lifecycle, its eSIM, when it last changed state, when it first went into service, the eSIMs it carried before its current one, and the date it is due to end if a termination is scheduled.\n\nTake `sim.activationCode` — a GSMA `LPA:1$…` string — and encode it as a QR code to install the eSIM; any QR library will do. SIM details are published only while the line is `READY`, so during a replacement `sim` reads `null` rather than handing out a code that has been revoked.\n\nA line in another organization answers exactly as one that does not exist.","security":[{"ApiKeyAuth":["numbers:read"]}],"x-telgea-audience":"partner","tags":["Numbers"],"x-telgea-problem-types":["https://developer.telgea.com/errors/number-service/NUMBER_NOT_FOUND"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8238c1b9-c2c0-4455-9b03-4bd787052709","description":"UUID of the line."},"required":true,"description":"UUID of the line.","name":"numberId","in":"path"}],"responses":{"200":{"description":"Successfully retrieved the line.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NumberDetails"},"example":{"id":"8238c1b9-c2c0-4455-9b03-4bd787052709","userId":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","type":"local","countryCode":"DK","phoneNumber":"+4520123456","state":"READY","sim":{"iccid":"8945000000000000001","activationCode":"LPA:1$SMDP.TELGEA.COM$34682-73063-9140","pinOne":"1234","pinTwo":"5678","pukOne":"12345678","pukTwo":"87654321"},"createdAt":"2026-09-17T08:15:00.000Z","stateUpdatedAt":"2026-10-01T10:00:00.000Z","terminationScheduledAt":null,"activatedAt":"2026-09-17T08:20:00.000Z","previousSims":[{"iccid":"89462000099812030017","inServiceFrom":"2026-09-17T08:20:00.000Z","inServiceTo":"2026-10-01T10:00:00.000Z"}]}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to read lines","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"No line in your organization has this id.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/numbers/{numberId}/connection":{"get":{"operationId":"getNumberConnection","summary":"Get a line's connection status","description":"Reads what the network reports about one line: its status there (active, suspended or inactive), when it last saw activity on the line, the country and operator the line is attached to, the network type, and the IP address, APN and device IMEI in use.\n\n**A line is read at most once per 5-minute window.** The windows are fixed, starting on the clock's 5-minute marks rather than at a request. A request inside a window gets the answer the network gave at `checkedAt`, whoever asked first, without the network being asked again — so polling more often returns the same answer. The first request in the next window reads the line again, however recent the last read. A failed read is answered again the same way until its window ends. Reads of many lines are answered a few at a time per network, so a loop over a large roster takes a while.\n\nSome lines cannot be read: those in a market whose network does not report connection status, those with no phone number or eSIM yet, and those still being ported in or already ended. They answer `200` with `available: false` and every other field null.\n\nA line in another organization answers exactly as one that does not exist.","security":[{"ApiKeyAuth":["numbers:read"]}],"x-telgea-audience":"partner","tags":["Numbers"],"x-telgea-problem-types":["https://developer.telgea.com/errors/number-service/NUMBER_NOT_FOUND","https://developer.telgea.com/errors/number-service/CONNECTION_STATUS_FAILED"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8238c1b9-c2c0-4455-9b03-4bd787052709","description":"UUID of the line."},"required":true,"description":"UUID of the line.","name":"numberId","in":"path"}],"responses":{"200":{"description":"The line's connection status, or `available: false` for a line that cannot be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NumberConnection"},"example":{"available":true,"status":"active","lastSeenAt":"2026-10-19T11:58:00.000Z","countryCode":"DK","servingNetwork":"TDC","accessTechnology":"4G","ipAddress":"10.20.30.40","apn":"internet","imei":"356938035643809","checkedAt":"2026-10-19T12:00:00.000Z"}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to read lines","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"No line in your organization has this id.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"The network serving this line did not answer, so its connection status could not be read.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/numbers/{numberId}/sim-replacement":{"post":{"operationId":"replaceNumberSim","summary":"Replace a SIM card","description":"Initiates a SIM card replacement (eSIM swap) on one line. This provisions a new eSIM and deactivates the previous one.\n\n> **Important:** This endpoint should **only** be used when the end-user changes devices and the existing eSIM activation QR code (LPA string) has been confirmed to be expired or no longer working. Do **not** use this endpoint to troubleshoot connectivity issues — contact support instead.\n\n**Rate limit:** one replacement per line inside the cooldown your organization's SIM-swap offering sets, counted from when the line's last replacement finished — and once per calendar day for a German number. A request inside the window gets a `429` naming when to retry.\n\n**Flow:**\n1. A new eSIM profile is provisioned and the old SIM is deactivated\n2. Until the new profile is ready, GET /v1/numbers/{numberId} reports the line with `sim: null` — its state is `REPLACING`, and SIM details are published only in `READY`\n3. Back in `READY`, the line's `sim.activationCode` is the new one to render as a QR code\n\nOrganizations with Telgea's end-user communications enabled also email the user the new activation code. White-label integrations have them switched off and present it themselves.","security":[{"ApiKeyAuth":["numbers:replace-sim"]}],"x-telgea-audience":"partner","tags":["Numbers"],"x-telgea-problem-types":["https://developer.telgea.com/errors/order/ORDER_COOLDOWN_ACTIVE"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8238c1b9-c2c0-4455-9b03-4bd787052709","description":"UUID of the line."},"required":true,"description":"UUID of the line.","name":"numberId","in":"path"},{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"responses":{"202":{"description":"SIM replacement request accepted and processed asynchronously. Poll GET /v1/numbers/{numberId} until the line is READY again with its new SIM.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplaceSimResponse"},"example":{"status":"accepted"}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to replace SIM cards","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"No line in your organization has this id.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"The line's last SIM replacement finished too recently for another: your organization's SIM-swap offering sets the cooldown (a German number is replaced once per calendar day), and `Retry-After` says when to retry. The same status also answers a key that has used its request quota.","headers":{"Retry-After":{"schema":{"type":"string","example":"Fri, 18 Sep 2026 12:00:00 GMT"},"required":true,"description":"When to retry. An HTTP-date — the earliest moment a replacement is accepted again — for the cooldown; the seconds until the window resets for a key that has used its request quota."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"},"example":{"type":"https://developer.telgea.com/errors/order/ORDER_COOLDOWN_ACTIVE","title":"Too soon after the last one","status":429,"detail":"The last one of these for this number finished too recently for another, so nothing was placed.","code":"TOO_MANY_REQUESTS","requestId":"req_123"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/numbers/{numberId}/suspension":{"post":{"operationId":"suspendNumber","summary":"Suspend a line","description":"Stops all traffic on one line, domestic and international — for a phone that has been lost or stolen. To stop only mobile data and leave the line usable, use the data-restriction endpoint.\n\nThe call returns once the line is down at the network, so a `204` means the service is genuinely stopped.\n\nSuspending a line that is already suspended returns `409` and changes nothing.\n\nNot every market offers suspension. Where it does not, this returns `400` and the line stays live — the Markets page in the documentation lists which is which.","security":[{"ApiKeyAuth":["numbers:suspend"]}],"x-telgea-audience":"partner","tags":["Numbers"],"x-telgea-problem-types":["https://developer.telgea.com/errors/number-service/NUMBER_ALREADY_IN_STATE","https://developer.telgea.com/errors/number-service/NUMBER_MISSING_MSISDN","https://developer.telgea.com/errors/number-service/NUMBER_OPERATION_NOT_SUPPORTED","https://developer.telgea.com/errors/number-service/NUMBER_NOT_FOUND"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8238c1b9-c2c0-4455-9b03-4bd787052709","description":"UUID of the line."},"required":true,"description":"UUID of the line.","name":"numberId","in":"path"},{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"responses":{"204":{"description":"Line suspended. No content returned."},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions for this action","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"No line in your organization has this id.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"409":{"description":"Already in the state you asked for, so nothing was changed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}},"delete":{"operationId":"unsuspendNumber","summary":"Restore a suspended line","description":"Undoes a suspension made with `POST /v1/numbers/{numberId}/suspension`, and returns once the line is live again at the network.\n\nRestoring a line that is not suspended returns `409`.","security":[{"ApiKeyAuth":["numbers:unsuspend"]}],"x-telgea-audience":"partner","tags":["Numbers"],"x-telgea-problem-types":["https://developer.telgea.com/errors/number-service/NUMBER_ALREADY_IN_STATE","https://developer.telgea.com/errors/number-service/NUMBER_MISSING_MSISDN","https://developer.telgea.com/errors/number-service/NUMBER_OPERATION_NOT_SUPPORTED","https://developer.telgea.com/errors/number-service/NUMBER_NOT_FOUND"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8238c1b9-c2c0-4455-9b03-4bd787052709","description":"UUID of the line."},"required":true,"description":"UUID of the line.","name":"numberId","in":"path"},{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"responses":{"204":{"description":"Line restored. No content returned."},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions for this action","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"No line in your organization has this id.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"409":{"description":"Already in the state you asked for, so nothing was changed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/numbers/{numberId}/data-restriction":{"post":{"operationId":"restrictNumberData","summary":"Stop a line's mobile data","description":"Stops mobile data on one line — for a customer who has used up what they paid for. Calls and texts keep working; use the suspension endpoint to stop the whole line.\n\nThe call returns once the change has taken effect at the network, so a `200` means the data is genuinely off. Nothing here is queued for later.\n\nStopping data that is already stopped returns `409` and changes nothing. Our own automated processes never undo a stop you made — only `DELETE` on this path does.\n\nData is stopped against the data pool the line draws on, so a line in none of your pools returns `422`. Not every market offers stopping data on its own either; where it does not, this returns `422` and nothing changes — the Markets page in the documentation lists which is which.","security":[{"ApiKeyAuth":["numbers:suspend"]}],"x-telgea-audience":"partner","tags":["Numbers"],"x-telgea-problem-types":["https://developer.telgea.com/errors/consumption/DATA_ALREADY_STOPPED","https://developer.telgea.com/errors/consumption/SUBSCRIBER_HAS_NO_DATA_POOL","https://developer.telgea.com/errors/consumption/DATA_STOP_NOT_SUPPORTED","https://developer.telgea.com/errors/consumption/DATA_STOP_NOT_APPLIED","https://developer.telgea.com/errors/number-service/NUMBER_NOT_FOUND","https://developer.telgea.com/errors/hub/USER_NOT_FOUND"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8238c1b9-c2c0-4455-9b03-4bd787052709","description":"UUID of the line."},"required":true,"description":"UUID of the line.","name":"numberId","in":"path"},{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataRestrictionBody"},"examples":{"full":{"summary":"With a reason","value":{"reason":"Customer exceeded their agreed data allowance."}},"minimal":{"summary":"No reason given","value":{}}}}}},"responses":{"200":{"description":"Data stopped. Lists the numbers the stop reached and when it took effect.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataRestrictionResponse"},"example":{"numbers":["+4520123456"],"effectiveAt":"2026-09-14T09:30:00.000Z"}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions for this action","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"No line in your organization has this id.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"409":{"description":"Already in the state you asked for, so nothing was changed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}}},"422":{"description":"Nothing was changed: the line draws on none of your data pools, so there is no data to stop, or its market does not offer stopping data on its own.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnprocessableEntityError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}},"delete":{"operationId":"liftNumberDataRestriction","summary":"Restore a line's mobile data","description":"Undoes a stop made with `POST /v1/numbers/{numberId}/data-restriction`, and returns once data is live again at the network.\n\nRestoring data that is not stopped returns `409`. Data stays off if the customer is also over an allowance you set — clear that first.","security":[{"ApiKeyAuth":["numbers:unsuspend"]}],"x-telgea-audience":"partner","tags":["Numbers"],"x-telgea-problem-types":["https://developer.telgea.com/errors/consumption/DATA_NOT_STOPPED","https://developer.telgea.com/errors/consumption/DATA_RESTORE_NOT_APPLIED","https://developer.telgea.com/errors/number-service/NUMBER_NOT_FOUND","https://developer.telgea.com/errors/hub/USER_NOT_FOUND"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8238c1b9-c2c0-4455-9b03-4bd787052709","description":"UUID of the line."},"required":true,"description":"UUID of the line.","name":"numberId","in":"path"},{"schema":{"type":"string","maxLength":200,"description":"Free text kept with the change.","example":"Customer settled their account."},"required":false,"description":"Free text kept with the change.","name":"reason","in":"query"},{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"responses":{"200":{"description":"Data restored. Lists the numbers the restore reached and when it took effect.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataRestrictionResponse"},"example":{"numbers":["+4520123456"],"effectiveAt":"2026-09-14T09:30:00.000Z"}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions for this action","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"No line in your organization has this id.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"409":{"description":"Already in the state you asked for, so nothing was changed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/numbers/{numberId}/termination":{"post":{"operationId":"terminateNumber","summary":"End a line","description":"Ends the line on the date you name — the date the customer agreed to stop.\n\nThe line is suspended on that date and deactivated at the network 14 days later. The call returns as soon as the termination is scheduled, so a `202` means it is booked, not that the line is already down. Read it back on `GET /v1/numbers/{numberId}` as `terminationScheduledAt`.\n\n**Billing is not prorated.** The customer keeps the period they already bought: the line stops on your date, and billing runs to `activeUntil` in the response. The plan does not renew afterwards.\n\nSend `deleteUser: true` to delete the end-user along with the line. Otherwise the user remains, and `DELETE /v1/users/{userId}` succeeds once the line is suspended — you do not have to wait out the grace period.\n\nThe response lists every line the termination ends, which can be more than the one you named: a travel eSIM raised against this line's plan ends with it.","security":[{"ApiKeyAuth":["orders:cancel"]}],"x-telgea-audience":"partner","tags":["Numbers"],"x-telgea-problem-types":["https://developer.telgea.com/errors/order/TERMINATION_DATE_IN_PAST"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8238c1b9-c2c0-4455-9b03-4bd787052709","description":"UUID of the line."},"required":true,"description":"UUID of the line.","name":"numberId","in":"path"},{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TerminationBody"},"examples":{"full":{"summary":"Every field","value":{"terminationDate":"2026-10-01","deleteUser":true}},"minimal":{"summary":"Required fields only","value":{"terminationDate":"2026-10-01"}}}}}},"responses":{"202":{"description":"Termination scheduled. States the date, when billing stops, and the lines ending.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TerminationResponse"},"example":{"terminationDate":"2026-10-01","activeUntil":"2026-12-31T00:00:00.000Z","numberIds":["8238c1b9-c2c0-4455-9b03-4bd787052709"]}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions for this action","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"No plan to end stands against this line in your organization","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/port-ins/fields/{countryCode}":{"get":{"operationId":"getPortInFields","summary":"Get port-in fields for a country","description":"Retrieves the dynamic form fields required to submit a number port-in for a given country. Different countries and providers require different information (e.g., authorization codes, account numbers, personal details).\n\nThe response is keyed by port-in type (e.g., \"personal\", \"business\"). Each type contains a human-readable label and an array of input field definitions with validation rules.\n\nEach type also carries the market's transfer date as `executionDate` and how a port-in into the market runs as `timing`. Both hold for the whole market, and repeat in every type because the response is keyed by type.\n\nUse this endpoint to build dynamic forms that collect the right data before submitting a port-in.","security":[{"ApiKeyAuth":["port-ins:read"]}],"x-telgea-audience":"both","tags":["Port-Ins"],"x-telgea-problem-types":[],"parameters":[{"schema":{"type":"string","example":"DE","description":"ISO 3166-1 alpha-2 country code (e.g., \"DK\", \"US\", \"GB\")"},"required":true,"description":"ISO 3166-1 alpha-2 country code (e.g., \"DK\", \"US\", \"GB\")","name":"countryCode","in":"path"}],"responses":{"200":{"description":"Successfully retrieved port-in field definitions for the specified country. The response is keyed by port-in type (e.g., `personal`, `business`). Each type contains a human-readable label and an array of field definitions describing the inputs required for that port-in type.\n\nField types are `text`, `select`, `date`, `number` and `checkbox`. Each carries only the constraints that apply to it: `minLength`, `maxLength` and `regex` on text; `options` on select; `minDate`, `maxDate`, `dates` and `validUntil` on date; `min`, `max` and `decimalPlaces` on number; `requiredValue` on checkbox. Any field can carry `help`, `howToGet` and an `example` of its format.\n\n`executionDate` is a date field whose `dates` are every date a port-in can happen on, as of today in the market's time zone. They hold until `validUntil`, the market's next midnight; fetch the fields again after it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetPortInFieldsResponse"},"example":{"personal":{"label":"Personal","typeLabel":{"id":"port-in.de.typeLabel","en":"Who is the number registered to?"},"explanation":{"id":"port-in.de.personal.explanation","en":"The contract is in a person's name."},"fields":[{"name":"currentCarrier","label":"Current carrier","description":"Your current mobile carrier","type":"select","help":{"id":"port-in.de.currentCarrier.help","en":"The brand on your bill or SIM."},"options":[{"label":"Congstar","value":"CONG"},{"label":"O2 Deutschland GmbH","value":"O2DE"},{"label":"Vodafone GmbH","value":"VODA"}]},{"name":"authorizationCode","label":"Date of birth","description":"Owner date of birth (YYYY-MM-DD)","type":"date","help":{"id":"port-in.de.personal.authorizationCode.help","en":"Date of birth of the contract holder."}},{"name":"ownerFirstName","label":"First name","description":"Account owner first name","type":"text","minLength":1,"help":{"id":"port-in.de.asOnTheContract","en":"As on the contract."}},{"name":"ownerLastName","label":"Last name","description":"Account owner last name","type":"text","minLength":1,"help":{"id":"port-in.de.asOnTheContract","en":"As on the contract."}},{"name":"isUnlocked","label":"Number released for porting","description":"Please confirm that the current carrier has been contacted and unlocked the number for port-out","type":"checkbox","help":{"id":"port-in.de.isUnlocked.help","en":"Ask your current carrier to release the number before you start."},"requiredValue":true}],"executionDate":{"name":"executionDate","label":"Transfer date","type":"date","help":{"id":"port-in.executionDate.help.a-weekday-from-7-days-to-14-days-from-today","en":"A weekday, from 7 days to 14 days from today."},"errorMessage":"That date isn't possible. Choose a weekday from 7 days to 14 days from today.","minDate":"2027-03-01","maxDate":"2027-03-08","dates":["2027-03-01","2027-03-02","2027-03-03","2027-03-04","2027-03-05","2027-03-08"],"validUntil":"2027-02-22T23:00:00.000Z"},"timing":{"submitted":"beforeTheDate","finalDateSetBy":"oldCarrier","dateMayMove":true,"cancel":"beforeSubmission","reschedule":"beforeSubmission"}},"business":{"label":"Business","typeLabel":{"id":"port-in.de.typeLabel","en":"Who is the number registered to?"},"explanation":{"id":"port-in.de.business.explanation","en":"The contract is in a company's name."},"fields":[{"name":"currentCarrier","label":"Current carrier","description":"Your current mobile carrier","type":"select","help":{"id":"port-in.de.currentCarrier.help","en":"The brand on your bill or SIM."},"options":[{"label":"Congstar","value":"CONG"},{"label":"O2 Deutschland GmbH","value":"O2DE"},{"label":"Vodafone GmbH","value":"VODA"}]},{"name":"authorizationCode","label":"Customer number","description":"Your customer number with the current carrier. Can be found on a recent bill from them or by contacting the carrier directly.","type":"text","minLength":1,"help":{"id":"port-in.de.business.authorizationCode.help","en":"On the current carrier's invoice."},"howToGet":{"id":"port-in.de.business.authorizationCode.howToGet","en":"On the current carrier's invoice."}},{"name":"companyName","label":"Company name","description":"Registered company name of company that owns the number","type":"text","minLength":1,"help":{"id":"port-in.de.asOnTheContract","en":"As on the contract."}},{"name":"isUnlocked","label":"Number released for porting","description":"Please confirm that the current carrier has been contacted and unlocked the number for port-out","type":"checkbox","help":{"id":"port-in.de.isUnlocked.help","en":"Ask your current carrier to release the number before you start."},"requiredValue":true}],"executionDate":{"name":"executionDate","label":"Transfer date","type":"date","help":{"id":"port-in.executionDate.help.a-weekday-from-7-days-to-14-days-from-today","en":"A weekday, from 7 days to 14 days from today."},"errorMessage":"That date isn't possible. Choose a weekday from 7 days to 14 days from today.","minDate":"2027-03-01","maxDate":"2027-03-08","dates":["2027-03-01","2027-03-02","2027-03-03","2027-03-04","2027-03-05","2027-03-08"],"validUntil":"2027-02-22T23:00:00.000Z"},"timing":{"submitted":"beforeTheDate","finalDateSetBy":"oldCarrier","dateMayMove":true,"cancel":"beforeSubmission","reschedule":"beforeSubmission"}}}}}},"400":{"description":"The countryCode is not a valid ISO 3166-1 alpha-2 code. Valid codes look like DK, US, GB or FR.","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to read port-in data","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/port-ins/fields/{countryCode}/schema":{"get":{"operationId":"getPortInFieldsSchema","summary":"Get port-in fields JSON Schema","description":"Retrieves JSON Schema definitions for port-in fields, keyed by port-in type. Use these schemas for client-side validation of port-in form data before submission.\n\nEach key in the response corresponds to a port-in type (e.g., \"personal\", \"business\"), and the value is a standard JSON Schema object that can be used with any JSON Schema validator.\n\nA type whose market declares transfer dates also carries `$defs.executionDate`: check the port-in's `executionDate` against it. Its dates hold until the `executionDate.validUntil` the fields endpoint returns; fetch the schema again after it. Nothing in the schema's `properties` refers to it, so the schema validates `fields` alone.","security":[{"ApiKeyAuth":["port-ins:read"]}],"x-telgea-audience":"both","tags":["Port-Ins"],"x-telgea-problem-types":[],"parameters":[{"schema":{"type":"string","example":"DE","description":"ISO 3166-1 alpha-2 country code (e.g., \"DK\", \"US\", \"GB\")"},"required":true,"description":"ISO 3166-1 alpha-2 country code (e.g., \"DK\", \"US\", \"GB\")","name":"countryCode","in":"path"}],"responses":{"200":{"description":"Successfully retrieved JSON Schema definitions for port-in fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetPortInFieldsSchemaResponse"},"example":{"personal":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"currentCarrier":{"type":"string","enum":["CONG","O2DE","VODA"],"errorMessage":"Value must be one of the allowed options"},"authorizationCode":{"type":"string","format":"date","errorMessage":"Value must be a valid date"},"ownerFirstName":{"type":"string","minLength":1},"ownerLastName":{"type":"string","minLength":1},"isUnlocked":{"type":"boolean","const":true,"errorMessage":"Value must be true"}},"required":["currentCarrier","authorizationCode","ownerFirstName","ownerLastName","isUnlocked"],"additionalProperties":false,"$defs":{"executionDate":{"type":"string","enum":["2027-03-01","2027-03-02","2027-03-03","2027-03-04","2027-03-05","2027-03-08"],"format":"date","errorMessage":"That date isn't possible. Choose a weekday from 7 days to 14 days from today."}}}}}}},"400":{"description":"The countryCode is not a valid ISO 3166-1 alpha-2 code. Valid codes look like DK, US, GB or FR.","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to read port-in data","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/port-ins/validate":{"post":{"operationId":"validatePortIn","summary":"Validate port-in data","description":"Validates port-in data against provider requirements without creating a port-in. Use this endpoint to check whether the submitted fields, phone number, and execution date would pass provider validation before committing to a port-in submission.\n\nThe `executionDate` must be one of the type's `executionDate.dates` from `GET /v1/port-ins/fields/{countryCode}`, which hold until its `validUntil`. The date is checked once everything else passes: a date outside them is then refused with 400 BAD_REQUEST, not `valid: false`.\n\nThis is a dry-run operation — no resources are created or modified.","security":[{"ApiKeyAuth":["port-ins:validate"]}],"x-telgea-audience":"both","tags":["Port-Ins"],"x-telgea-problem-types":["https://developer.telgea.com/errors/number-service/MSISDN_HELD_BY_TELGEA","https://developer.telgea.com/errors/number-service/MSISDN_IN_TERMINATION_GRACE_PERIOD","https://developer.telgea.com/errors/hub/PORT_IN_ALREADY_IN_PROGRESS","https://developer.telgea.com/errors/provider-platform/EXECUTION_DATE_NOT_OFFERED"],"parameters":[{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidatePortInBody"},"example":{"countryCode":"DE","type":"personal","msisdn":"+4915112345678","executionDate":"2027-03-01","fields":{"currentCarrier":"CONG","authorizationCode":"1985-04-12","ownerFirstName":"Erika","ownerLastName":"Mustermann","isUnlocked":true}}}}},"responses":{"200":{"description":"Validation completed. Check the `valid` field to determine if the data passed. If `valid` is false, the `errors` array contains details: each error names its `field` and carries a stable `code` to branch on.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidatePortInResponse"},"example":{"valid":true,"errors":[]}}}},"400":{"description":"Request body failed schema validation, or everything else passed and the `executionDate` is not one the market offers","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to validate port-ins","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"409":{"description":"The number cannot be ported in: Telgea already holds it, or a port-in for it is already in flight. Creating the port-in would be refused the same way.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/port-ins":{"post":{"operationId":"createPortIn","summary":"Submit a port-in request","description":"Submits a number porting request to bring a phone number from another carrier into Telgea. The user must have an existing plan in INACTIVE or PORTING status.\n\n**Important constraints:**\n- The `executionDate` must be one of the type's `executionDate.dates` from `GET /v1/port-ins/fields/{countryCode}`, which hold until its `validUntil`. The date is checked once everything else passes: a date outside them is then refused with 400 BAD_REQUEST, and no port-in is created.\n- Only **one port-in can be in progress** per phone number at a time. Submitting a port-in for an MSISDN that already has an active (non-completed, non-failed, non-rejected) port-in will be rejected.\n- A number **already with Telgea** cannot be ported in: one on a Telgea line, or one whose plan ended within the last 14 days and can still be restored. It is refused with 409 CONFLICT.\n\n**Recommended flow:**\n1. Call `GET /v1/port-ins/fields/{countryCode}` to discover required fields for the country\n2. Call `POST /v1/port-ins/validate` to verify the data before submission\n3. Call this endpoint to submit the port-in\n\nIf provider-side validation fails, the response will have `status: \"REJECTED\"` with an `errors` array describing the issues. A successful submission returns `status: \"CREATED\"`.\n\nThe port-in will progress through states: CREATED → SUBMITTED → ACCEPTED → SUCCEEDED. Check the status with `GET /v1/port-ins/{portInId}`.\n\n**Retrying a port-in that ended in REJECTED or FAILED:** read `failure.reason` and `failure.field` on the port-in, correct what they point at (`failure.text` explains it in words you can show your customer), then call this endpoint again with the same `msisdn`. The failed attempt is kept as history and stays readable at its own id — `GET /v1/port-ins/number/{numberId}` lists every attempt for the number, newest first. A retry sent while a port-in for that number is still in flight is refused with 409 CONFLICT — a number can only be ported once at a time anywhere. Wait for it to finish, then read `failure.reason` and submit again.","security":[{"ApiKeyAuth":["port-ins:create"]}],"x-telgea-audience":"both","tags":["Port-Ins"],"x-telgea-problem-types":["https://developer.telgea.com/errors/number-service/PORT_IN_PLAN_STATE_INVALID","https://developer.telgea.com/errors/number-service/MSISDN_HELD_BY_TELGEA","https://developer.telgea.com/errors/number-service/MSISDN_IN_TERMINATION_GRACE_PERIOD","https://developer.telgea.com/errors/hub/PORT_IN_ALREADY_IN_PROGRESS","https://developer.telgea.com/errors/hub/USER_NOT_FOUND","https://developer.telgea.com/errors/provider-platform/EXECUTION_DATE_NOT_OFFERED","https://developer.telgea.com/errors/hub/ORGANIZATION_VERIFICATION_REQUIRED","https://developer.telgea.com/errors/order/CATALOGUE_ENTRY_UNAVAILABLE","https://developer.telgea.com/errors/order/HOME_PLAN_ALREADY_ACTIVE"],"parameters":[{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePortInBody"},"example":{"userId":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","countryCode":"DE","type":"personal","msisdn":"+4915112345678","executionDate":"2027-03-01","fields":{"currentCarrier":"CONG","authorizationCode":"1985-04-12","ownerFirstName":"Erika","ownerLastName":"Mustermann","isUnlocked":true}}}}},"responses":{"200":{"description":"Port-in request processed. Check the `status` field: \"CREATED\" means the port-in was accepted for processing; \"REJECTED\" means validation failed — see the `errors` array.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePortInResponse"},"example":{"id":"c3d4e5f6-a7b8-9012-c345-678901234567","status":"CREATED","msisdn":"+4915112345678","numberId":"8238c1b9-c2c0-4455-9b03-4bd787052709","executionDate":"2027-03-01","errors":[]}}}},"400":{"description":"Request body failed schema validation, or business rule violation (e.g., user plan not in correct state, or, once everything else passes, an `executionDate` the market does not offer)","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to create port-ins, or the country is not available for your organization: it is not enabled, or it requires business verification your organization has not passed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"No user with the given `userId` exists in your organization, so no port-in was created.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"409":{"description":"No port-in was created: Telgea already holds this number, or a port-in for it is already in flight.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/port-ins/{portInId}":{"get":{"operationId":"getPortIn","summary":"Get port-in status","description":"Retrieves the current status and details of a port-in request. Use this endpoint to track the progress of a submitted port-in through its lifecycle.","security":[{"ApiKeyAuth":["port-ins:read"]}],"x-telgea-audience":"both","tags":["Port-Ins"],"x-telgea-problem-types":["https://developer.telgea.com/errors/number-service/PORT_IN_NOT_FOUND"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"c3d4e5f6-a7b8-9012-c345-678901234567","description":"UUID of the port-in request."},"required":true,"description":"UUID of the port-in request.","name":"portInId","in":"path"}],"responses":{"200":{"description":"Successfully retrieved port-in details.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetPortInResponse"},"example":{"id":"c3d4e5f6-a7b8-9012-c345-678901234567","countryCode":"DE","msisdn":"+4915112345678","executionDate":"2027-03-01","type":"personal","status":"SUBMITTED","numberId":"8238c1b9-c2c0-4455-9b03-4bd787052709","failure":null,"createdAt":"2027-02-22T10:00:00Z","updatedAt":"2027-02-22T10:00:00Z"}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to read port-in data","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"Port-in not found. The specified ID does not match any existing port-in.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/port-ins/{portInId}/discard":{"post":{"operationId":"discardPortIn","summary":"Discard a failed port-in","description":"Gives up on a port-in that ended in REJECTED or FAILED, when you will not submit it again. The number leaves the plan and stays with the losing carrier. Unless the user has another number, the plan reads `INACTIVE`, so you can create a user plan with a new number or port in a different one.\n\nThe port-in stays readable at its own id and keeps its `REJECTED` or `FAILED` status. A discard shows as the number leaving the plan it was being ported onto, and the number's port-ins also leave `GET /v1/port-ins/number/{numberId}`.\n\nOnly a port-in that ended in REJECTED or FAILED can be discarded, and not while a newer port-in for the same number is in flight or once one has succeeded. Either is refused with 400 BAD_REQUEST. Discarding a port-in that is already discarded succeeds and changes nothing.","security":[{"ApiKeyAuth":["port-ins:discard"]}],"x-telgea-audience":"both","tags":["Port-Ins"],"x-telgea-problem-types":["https://developer.telgea.com/errors/number-service/PORT_IN_NOT_FOUND","https://developer.telgea.com/errors/number-service/PORT_IN_NOT_DISCARDABLE"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"c3d4e5f6-a7b8-9012-c345-678901234567","description":"UUID of the port-in request."},"required":true,"description":"UUID of the port-in request.","name":"portInId","in":"path"},{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"responses":{"204":{"description":"Port-in discarded. No content returned."},"400":{"description":"Request failed schema validation, or the port-in cannot be discarded: it has not failed, or a newer port-in has taken over its number","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to discard port-ins","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"Port-in not found. The specified ID does not match any existing port-in.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/port-ins/number/{numberId}":{"get":{"operationId":"listPortInsByNumber","summary":"List port-ins for a number","description":"Retrieves a paginated list of all port-in requests associated with a specific number. Use this to see the full porting history for a phone number, including completed, failed, and in-progress port-ins.","security":[{"ApiKeyAuth":["port-ins:read"]}],"x-telgea-audience":"both","tags":["Port-Ins"],"x-telgea-problem-types":[],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8238c1b9-c2c0-4455-9b03-4bd787052709","description":"UUID of the number resource"},"required":true,"description":"UUID of the number resource","name":"numberId","in":"path"},{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"default":1,"description":"Page to return, starting at 1.","example":1},"required":false,"description":"Page to return, starting at 1.","name":"page","in":"query"},{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":100,"default":50,"description":"Items per page, at most 100. Defaults to 50.","example":50},"required":false,"description":"Items per page, at most 100. Defaults to 50.","name":"pageSize","in":"query"}],"responses":{"200":{"description":"Successfully retrieved port-ins for the specified number.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPortInsResponse"},"example":{"page":1,"pageSize":50,"itemsCount":2,"items":[{"id":"c3d4e5f6-a7b8-9012-c345-678901234567","countryCode":"DE","msisdn":"+4915112345678","executionDate":"2027-03-01","type":"personal","status":"SUBMITTED","numberId":"8238c1b9-c2c0-4455-9b03-4bd787052709","failure":null,"createdAt":"2027-02-22T10:00:00Z","updatedAt":"2027-02-22T10:00:00Z"},{"id":"b1d2c3e4-f5a6-7890-b123-456789012345","countryCode":"DE","msisdn":"+4915112345678","executionDate":"2027-03-01","type":"personal","status":"FAILED","numberId":"8238c1b9-c2c0-4455-9b03-4bd787052709","failure":{"reason":"CONTRACT_LOCKED","field":null,"text":"The current contract doesn't allow the transfer yet. Ask your current carrier to release the number for porting."},"createdAt":"2027-02-22T10:00:00Z","updatedAt":"2027-02-22T10:00:00Z"}]}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to read port-in data","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/usage":{"get":{"operationId":"listUsage","summary":"List usage records","description":"Returns raw voice, SMS, and data usage records for your organization whose `timeStarted` falls between `startDate` and `endDate`, as one feed — you do not need to know that we store calls and data separately. Records come in the order we stored or last corrected them, not by `timeStarted`.\n\nWalk a period with the opaque `cursor`: send the first request with a `startDate`/`endDate`, then keep passing the `nextCursor` from each response until `hasMore` is `false`. Filter to one subscriber with `userId`.\n\nRecords are granular enough to bill on. Each arrives once the network reports it, from minutes to days after the usage depending on the market, and keeps its original `timeStarted`; a record we correct later comes round again with the same `id`. To poll incrementally, keep the `cursor` you sent for the last page and send it again, with the same window, on the next poll: you receive everything stored or corrected since, including records whose `timeStarted` is earlier than any you have seen. De-duplicate on `id`, keeping the latest copy. Records written in the last few minutes are held back until they settle. Expect usage from the last 24–48 hours to keep changing as late records arrive and are rated; the cursor delivers those updates.\n\n**Polling budget.** Each API key allows 1000 requests per 24 hours, shared across every endpoint. Walk a whole organisation with the default page size rather than polling per subscriber — a request over the budget returns `429`.","security":[{"ApiKeyAuth":["consumption:read"]}],"x-telgea-audience":"both","tags":["Usage"],"x-telgea-problem-types":["https://developer.telgea.com/errors/consumption/INVALID_USAGE_CURSOR"],"parameters":[{"schema":{"type":"string","format":"date","description":"Inclusive start of the usage window (YYYY-MM-DD, UTC).","example":"2026-09-01"},"required":true,"description":"Inclusive start of the usage window (YYYY-MM-DD, UTC).","name":"startDate","in":"query"},{"schema":{"type":"string","format":"date","description":"Inclusive end of the usage window (YYYY-MM-DD, UTC). The window may span at most 31 days.","example":"2026-09-30"},"required":true,"description":"Inclusive end of the usage window (YYYY-MM-DD, UTC). The window may span at most 31 days.","name":"endDate","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50,"description":"Records per page (max 100)","example":50},"required":false,"description":"Records per page (max 100)","name":"pageSize","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from a previous response's nextCursor. Omit for the first page.","example":"eyJjIjoiMjAyNi0wOS0xMVQwODozMDowMC4xMjM0NTZaIiwicyI6ImRhdGEiLCJpIjoiY2RyXzEifQ"},"required":false,"description":"Opaque cursor from a previous response's nextCursor. Omit for the first page.","name":"cursor","in":"query"},{"schema":{"type":"string","format":"uuid","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","description":"Restrict to one end-user your organization owns. Omit for every user."},"required":false,"description":"Restrict to one end-user your organization owns. Omit for every user.","name":"userId","in":"query"}],"responses":{"200":{"description":"A page of usage records with a forward cursor.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageFeedResponse"},"example":{"items":[{"id":"cdr_01j9v2k8f3m4n5p6q7r8s9t0u1","type":"DATA","provider":"telia-denmark","msisdn":"+4520123456","timeStarted":"2026-09-11T08:30:00.000Z","timeEnded":"2026-09-11T08:34:12.000Z","amount":10485760,"unit":"bytes","servingCountryCode":"DK","usageClass":"domestic","counterpartyMsisdn":null,"callDirection":null,"counterpartyCountryCode":null,"networkType":"5G","userId":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","date":"2026-09-11","totalPrice":"0.043200","unitPrice":"0.004320","currency":"EUR","rateId":"rate_01j9v2k8f3m4n5p6q7r8s9t0u1"}],"nextCursor":"eyJjIjoiMjAyNi0wOS0xMVQwODozMDowMC4xMjM0NTZaIiwicyI6ImRhdGEiLCJpIjoiY2RyXzEifQ","hasMore":true}}}},"400":{"description":"Invalid cursor, a query window wider than the published maximum, or schema validation","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"The API key lacks the consumption:read scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/analytics":{"get":{"operationId":"getUsageAnalytics","summary":"Get aggregated usage analytics","description":"Returns voice, SMS, and data consumption for your organization, aggregated into per-`interval` totals with highest / lowest / average metadata across the window.\n\nUse this for reporting and dashboards. When you need individual events — to bill on or to act on one customer's usage — use `GET /v1/usage` instead. Totals lag the network by the same delay as the usage feed.","security":[{"ApiKeyAuth":["analytics:read"]}],"x-telgea-audience":"both","tags":["Analytics"],"x-telgea-problem-types":[],"parameters":[{"schema":{"type":"string","format":"date","description":"Inclusive start of the reporting window (YYYY-MM-DD).","example":"2026-09-01"},"required":true,"description":"Inclusive start of the reporting window (YYYY-MM-DD).","name":"startDate","in":"query"},{"schema":{"type":"string","format":"date","description":"Inclusive end of the reporting window (YYYY-MM-DD).","example":"2026-09-30"},"required":true,"description":"Inclusive end of the reporting window (YYYY-MM-DD).","name":"endDate","in":"query"},{"schema":{"type":"string","enum":["month","day"],"description":"Aggregation bucket size","example":"day"},"required":true,"description":"Aggregation bucket size","name":"interval","in":"query"},{"schema":{"type":"string","format":"uuid","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","description":"Restrict to one end-user your organization owns."},"required":false,"description":"Restrict to one end-user your organization owns.","name":"userId","in":"query"},{"schema":{"type":"string","minLength":1,"description":"Restrict to a single number.","example":"+4520123456"},"required":false,"description":"Restrict to a single number.","name":"msisdn","in":"query"},{"schema":{"type":"string","example":"DK","description":"Restrict to usage served in one country."},"required":false,"description":"Restrict to usage served in one country.","name":"countryIsoCode","in":"query"},{"schema":{"type":"string","enum":["asc","desc"],"description":"Order the returned intervals ascending or descending by time","example":"asc"},"required":false,"description":"Order the returned intervals ascending or descending by time","name":"orderBy","in":"query"}],"responses":{"200":{"description":"Aggregated usage grouped by interval, with per-channel metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsResponse"},"example":{"usage":{"data":[{"interval":"2026-09-11","usage":{"total":10485760,"Europe":9437184,"North America":1048576}},{"interval":"2026-09-12","usage":{"total":524288,"Europe":524288}}],"voice":[{"interval":"2026-09-11","usage":{"local":1240,"international":310,"total":1550}},{"interval":"2026-09-12","usage":{"local":90,"international":0,"total":90}}],"sms":[{"interval":"2026-09-11","usage":{"local":12,"international":3,"total":15}},{"interval":"2026-09-12","usage":{"local":1,"international":0,"total":1}}]},"metadata":{"data":{"highest":{"interval":"2026-09-11","usage":{"total":10485760,"Europe":9437184,"North America":1048576}},"lowest":{"interval":"2026-09-12","usage":{"total":524288,"Europe":524288}},"average":{"total":5505024}},"voice":{"highest":{"interval":"2026-09-11","usage":{"local":1240,"international":310,"total":1550}},"lowest":{"interval":"2026-09-12","usage":{"local":90,"international":0,"total":90}},"average":{"local":665,"international":155,"total":820}},"sms":{"highest":{"interval":"2026-09-11","usage":{"local":12,"international":3,"total":15}},"lowest":{"interval":"2026-09-12","usage":{"local":1,"international":0,"total":1}},"average":{"local":6.5,"international":1.5,"total":8}}}}}}},"400":{"description":"Request failed schema validation","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"The API key lacks the analytics:read scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/data-pools":{"get":{"operationId":"listDataPools","summary":"List data pools","description":"Retrieves every active data pool in your organization, with how much of each is left.\n\nA pool covers one region. Numbers in that region draw on the pool as they use data, and stop when it is exhausted — so `remainingGB` is the figure to watch if you resell the pool and decide when to top up or throttle a customer.\n\nConsumption figures lag the network by the same delay as the usage feed, up to about 16 hours in some markets, so `remainingGB` does not yet count usage the network has not reported.\n\n**Scope:** `pools:read`.","security":[{"ApiKeyAuth":["pools:read"]}],"x-telgea-audience":"both","tags":["Data Pools"],"x-telgea-problem-types":[],"responses":{"200":{"description":"Successfully retrieved the active data pools and their balances.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListDataPoolsResponse"},"example":{"pools":[{"poolId":"6b9a0c74-51d2-4e83-9f16-2a7c8d0e5b34","regionId":"eu-zone-1","regionName":"Europe","totalAmountGB":500,"consumedGB":312.4,"remainingGB":187.6,"expirationDate":"2026-12-31","hasActiveRestrictions":false}]}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to view data pools","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/data-pools/{poolId}/members":{"get":{"operationId":"listDataPoolMembers","summary":"List the members of a data pool","description":"Retrieves every user drawing on a data pool, with the data each has taken from it.\n\nUse this to attribute a pool's consumption to individual customers. `usageBytes` is the member's usage across all their lines, repeated on each of their rows, so count it once per `userId` rather than summing the rows.\n\nA pool belonging to another organization answers `404`, not `403`.\n\n**Scope:** `pools:read`.","security":[{"ApiKeyAuth":["pools:read"]}],"x-telgea-audience":"both","tags":["Data Pools"],"x-telgea-problem-types":["https://developer.telgea.com/errors/consumption/POOL_NOT_FOUND"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"6b9a0c74-51d2-4e83-9f16-2a7c8d0e5b34","description":"UUID of the data pool"},"required":true,"description":"UUID of the data pool","name":"poolId","in":"path"}],"responses":{"200":{"description":"Successfully retrieved the pool members and their usage.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPoolMembersResponse"},"example":{"poolId":"6b9a0c74-51d2-4e83-9f16-2a7c8d0e5b34","members":[{"userId":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","msisdn":"+4520123456","numberType":"local","firstName":"Anna","lastName":"Holm","email":"anna.holm@acme.example","activationDate":"2026-09-01","terminationDate":null,"usageBytes":10485760}]}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to view data pools","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"No data pool in your organization has this id","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/rates":{"get":{"operationId":"listRates","summary":"List PAYG retail rates for a market","description":"Retrieves the pay-as-you-go retail price list for a market — international calling and messaging per destination, or roaming data per visited country.\n\nPass a `market` (an ISO 3166-1 alpha-2 country code — the home-plan market) and a rate `type`. The provider that prices the market is resolved internally, so the response is provider-agnostic: it carries only the country, the per-unit price, its unit, the currency and when it took effect. Prices are your organization's: any rate negotiated for it replaces the list price. They are in the provider's native currency; convert as needed.\n\nCalling and messaging are priced from the country the subscriber is in. That is the market by default — a subscriber at home. Add `servingCountry` to price the same market's plan while roaming: `market=DE&servingCountry=DK` is a German plan used in Denmark, and the response echoes the `servingCountry` it priced from. `ROAMING_DATA` has no single serving country — it returns a per-MB price for every visited country — so it ignores the parameter and answers with `servingCountry: null`.\n\nCalls and messages are priced outbound by default — what the subscriber pays to reach each destination. Add `direction=inbound` for the other leg: what the subscriber pays when someone in each country reaches them, which is chargeable while roaming. The response echoes the `direction` it priced; `ROAMING_DATA` has none and answers with `direction: null`.\n\nEvery country is listed, and a country that costs the subscriber nothing carries `ratePerUnit: 0` rather than being left out. That covers both a route priced free — calls inside the EU/EEA, under roam-like-at-home — and one we publish no pay-as-you-go price for, such as a roaming-data country included in the plan. For calling and messaging the serving country itself is not listed, since a call that stays inside it is not an international one.\n\nPrices are those in effect today. Add `asOfDate` (YYYY-MM-DD) to read the list for another day — for instance, a price change scheduled to take effect next month. The response echoes the `asOfDate` it priced. The provider is always the one serving the market today.\n\nA market no provider serves answers `403` `COUNTRY_NOT_SUPPORTED`.\n\n**Scope:** `rates:read`.","security":[{"ApiKeyAuth":["rates:read"]}],"x-telgea-audience":"both","tags":["Rates"],"x-telgea-problem-types":["https://developer.telgea.com/errors/hub/MARKET_NOT_SERVICEABLE"],"parameters":[{"schema":{"type":"string","example":"DK","description":"The home-plan market to price, as an ISO 3166-1 alpha-2 country code. The provider is resolved internally."},"required":true,"description":"The home-plan market to price, as an ISO 3166-1 alpha-2 country code. The provider is resolved internally.","name":"market","in":"query"},{"schema":{"type":"string","enum":["INTL_VOICE","INTL_SMS","INTL_MMS","ROAMING_DATA"],"description":"The rate type to price: INTL_VOICE (per minute), INTL_SMS / INTL_MMS (per message), or ROAMING_DATA (per MB)","example":"INTL_VOICE"},"required":true,"description":"The rate type to price: INTL_VOICE (per minute), INTL_SMS / INTL_MMS (per message), or ROAMING_DATA (per MB)","name":"type","in":"query"},{"schema":{"type":"string","example":"DK","description":"The country the subscriber is calling from, when it differs from the market (roaming). Defaults to the market, which prices calls placed at home. Ignored for ROAMING_DATA, which prices every visited country in one list."},"required":false,"description":"The country the subscriber is calling from, when it differs from the market (roaming). Defaults to the market, which prices calls placed at home. Ignored for ROAMING_DATA, which prices every visited country in one list.","name":"servingCountry","in":"query"},{"schema":{"type":"string","enum":["outbound","inbound"],"description":"Which leg of a call or message to price: outbound — the subscriber calls or texts the destination — or inbound — someone in that country reaches the subscriber, which is chargeable while roaming. Defaults to outbound. Ignored for ROAMING_DATA.","example":"outbound"},"required":false,"description":"Which leg of a call or message to price: outbound — the subscriber calls or texts the destination — or inbound — someone in that country reaches the subscriber, which is chargeable while roaming. Defaults to outbound. Ignored for ROAMING_DATA.","name":"direction","in":"query"},{"schema":{"type":"string","format":"date","description":"The day to price (YYYY-MM-DD): the rates in effect then. Defaults to today, so a price scheduled to take effect later is never quoted early. The provider is the one serving the market today.","example":"2026-10-01"},"required":false,"description":"The day to price (YYYY-MM-DD): the rates in effect then. Defaults to today, so a price scheduled to take effect later is never quoted early. The provider is the one serving the market today.","name":"asOfDate","in":"query"}],"responses":{"200":{"description":"Successfully retrieved the retail rates for the market.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RatesResponse"},"example":{"market":"DE","servingCountry":"DE","direction":"outbound","asOfDate":"2026-09-18","rates":[{"country":"US","ratePerUnit":0.12,"unit":"minutes","currency":"EUR","validFrom":"2026-01-01"},{"country":"FR","ratePerUnit":0,"unit":"minutes","currency":"EUR","validFrom":null}]}}}},"400":{"description":"Request failed schema validation, or was refused by a business rule","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"The API key lacks the rates:read scope, or no provider serves the requested market","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/cost-thresholds":{"get":{"operationId":"listCostThresholds","summary":"List cost thresholds","description":"Lists what people in your organization may spend per month on a usage type: the organization's own threshold; with `teamId`, that team's own and the own thresholds of the people in it; with `userId`, that user's own. A threshold that opens next month is listed with its `validFrom` in the future. Omit `usageType` for every type.\n\nA team or user of another organization answers `404`; a usage type nothing can enforce yet answers `422`. A user falls under their own threshold, else their team's, else the organization's. To see which one a user is under, with their spend this month, use `GET /v1/users/{userId}/cost-thresholds/{usageType}`.\n\n`currency` is the money a threshold written for the named team or user would carry: their cost-center currency, else the organization's primary.\n\n**Scope:** `policies:read`, and `teams:read` when a team is named.","security":[{"ApiKeyAuth":["policies:read"]}],"x-telgea-audience":"both","tags":["Cost Thresholds"],"x-telgea-problem-types":["https://developer.telgea.com/errors/order/USAGE_THRESHOLD_TEAM_OUTSIDE_ORGANIZATION","https://developer.telgea.com/errors/order/USAGE_THRESHOLD_USER_OUTSIDE_ORGANIZATION","https://developer.telgea.com/errors/order/USAGE_THRESHOLD_TYPE_NOT_SUPPORTED"],"parameters":[{"schema":{"type":"string","enum":["DATA","VOICE","SMS","MMS"],"description":"The usage type the threshold is on. `VOICE` is international calling: reaching it pauses international calls and SMS on the person's lines, where their market offers the pause. Other types answer `422` until the platform can enforce them.","example":"VOICE"},"required":false,"description":"The usage type the threshold is on. `VOICE` is international calling: reaching it pauses international calls and SMS on the person's lines, where their market offers the pause. Other types answer `422` until the platform can enforce them.","name":"usageType","in":"query"},{"schema":{"type":"string","format":"uuid","example":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70","description":"UUID of the team the threshold is for. Omit with `userId` for the organization's own."},"required":false,"description":"UUID of the team the threshold is for. Omit with `userId` for the organization's own.","name":"teamId","in":"query"},{"schema":{"type":"string","format":"uuid","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","description":"UUID of the user the threshold is for. Omit with `teamId` for the organization's own."},"required":false,"description":"UUID of the user the threshold is for. Omit with `teamId` for the organization's own.","name":"userId","in":"query"}],"responses":{"200":{"description":"The thresholds in force or opening next month.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListCostThresholdsResponse"},"example":{"thresholds":[{"id":"5d0b2c1e-7f3a-4b6c-9e8d-2a1f0c3b4d5e","usageType":"VOICE","scope":"team","teamId":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70","userId":null,"maxAmount":50,"currency":"EUR","period":"monthly","validFrom":"2026-10-01T00:00:00.000Z","validTo":null}],"currency":"EUR"}}}},"400":{"description":"Request failed schema validation, or named both a team and a user","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to view policies","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"No team in your organization has this id, so nothing was read or changed. No user in your organization has this id, so nothing was read or changed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"422":{"description":"No threshold can stand on this usage type yet, so nothing was read or changed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnprocessableEntityError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}},"put":{"operationId":"setCostThreshold","summary":"Set a cost threshold","description":"Sets what one person may spend per month on a usage type: for the organization, for a team (`teamId`), or for one user (`userId`). A new amount replaces the scope's current one on that usage type.\n\n`VOICE` is international calling: once a user's spend reaches the threshold, international calls and SMS on their lines are paused until the next month, where their market offers the pause; elsewhere the threshold warns only. Other usage types answer `422` until the platform can enforce them.\n\nThe amount is in the team's cost-center currency, else the organization's primary; read it back from the response. The threshold opens now, so this month's spend counts against it at once, unless someone in scope has already spent more than the new amount: then it opens next month and `appliesFromNextMonth` says so. Raising it above a paused user's spend lifts their pause in the same call.\n\n**Scope:** `policies:write`, and `teams:read` when a team is named.","security":[{"ApiKeyAuth":["policies:write"]}],"x-telgea-audience":"both","tags":["Cost Thresholds"],"x-telgea-problem-types":["https://developer.telgea.com/errors/order/USAGE_THRESHOLD_TEAM_OUTSIDE_ORGANIZATION","https://developer.telgea.com/errors/order/USAGE_THRESHOLD_USER_OUTSIDE_ORGANIZATION","https://developer.telgea.com/errors/order/USAGE_THRESHOLD_COST_CENTER_MISSING","https://developer.telgea.com/errors/order/USAGE_THRESHOLD_CURRENCY_NOT_QUOTED","https://developer.telgea.com/errors/order/USAGE_THRESHOLD_WRITE_CONFLICT","https://developer.telgea.com/errors/order/USAGE_THRESHOLD_TYPE_NOT_SUPPORTED"],"parameters":[{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"usageType":{"type":"string","enum":["DATA","VOICE","SMS","MMS"],"description":"The usage type the threshold is on. `VOICE` is international calling: reaching it pauses international calls and SMS on the person's lines, where their market offers the pause. Other types answer `422` until the platform can enforce them.","example":"VOICE"},"teamId":{"type":"string","format":"uuid","example":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70","description":"UUID of the team the threshold is for. Omit with `userId` for the organization's own."},"userId":{"type":"string","format":"uuid","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","description":"UUID of the user the threshold is for. Omit with `teamId` for the organization's own."},"maxAmount":{"type":"number","minimum":0,"exclusiveMinimum":true,"description":"What one person may spend on the usage type per month, at most two decimals.","example":50}},"required":["usageType","maxAmount"],"additionalProperties":false},"examples":{"full":{"summary":"A team's threshold on international calling","value":{"usageType":"VOICE","teamId":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70","maxAmount":50}},"minimal":{"summary":"The organization's own threshold","value":{"usageType":"VOICE","maxAmount":50}}}}}},"responses":{"200":{"description":"The threshold as written, and what it did on the way in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetCostThresholdResponse"},"example":{"threshold":{"id":"5d0b2c1e-7f3a-4b6c-9e8d-2a1f0c3b4d5e","usageType":"VOICE","scope":"team","teamId":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70","userId":null,"maxAmount":50,"currency":"EUR","period":"monthly","validFrom":"2026-10-01T00:00:00.000Z","validTo":null},"appliesFromNextMonth":false,"releasedNumberCount":0}}}},"400":{"description":"Request failed schema validation, or named both a team and a user","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to manage policies","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"No team in your organization has this id, so nothing was read or changed. No user in your organization has this id, so nothing was read or changed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"409":{"description":"Another write of the same threshold landed at the same moment, so this one was refused and nothing was changed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}}},"422":{"description":"No cost center names a currency for this scope, so the threshold has no money to be written in. The cost-center currency is one no exchange rate covers, so spend could never be compared with a threshold in it. No threshold can stand on this usage type yet, so nothing was read or changed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnprocessableEntityError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}},"delete":{"operationId":"removeCostThreshold","summary":"Remove a cost threshold","description":"Ends the scope's threshold on a usage type now: the organization's (no team or user), a team's (`teamId`) or a user's own (`userId`). A user then falls under their team's threshold, a team under the organization's; with none left, the usage is unlimited.\n\nRemoving a threshold that is not set changes nothing and still answers `204`.\n\n**Scope:** `policies:write`, and `teams:read` when a team is named.","security":[{"ApiKeyAuth":["policies:write"]}],"x-telgea-audience":"both","tags":["Cost Thresholds"],"x-telgea-problem-types":["https://developer.telgea.com/errors/order/USAGE_THRESHOLD_TEAM_OUTSIDE_ORGANIZATION","https://developer.telgea.com/errors/order/USAGE_THRESHOLD_USER_OUTSIDE_ORGANIZATION","https://developer.telgea.com/errors/order/USAGE_THRESHOLD_TYPE_NOT_SUPPORTED"],"parameters":[{"schema":{"type":"string","enum":["DATA","VOICE","SMS","MMS"],"description":"The usage type the threshold is on. `VOICE` is international calling: reaching it pauses international calls and SMS on the person's lines, where their market offers the pause. Other types answer `422` until the platform can enforce them.","example":"VOICE"},"required":true,"description":"The usage type the threshold is on. `VOICE` is international calling: reaching it pauses international calls and SMS on the person's lines, where their market offers the pause. Other types answer `422` until the platform can enforce them.","name":"usageType","in":"query"},{"schema":{"type":"string","format":"uuid","example":"2f6b0d3a-8c1e-4a7f-9b2d-1e3c4d5f6a70","description":"UUID of the team the threshold is for. Omit with `userId` for the organization's own."},"required":false,"description":"UUID of the team the threshold is for. Omit with `userId` for the organization's own.","name":"teamId","in":"query"},{"schema":{"type":"string","format":"uuid","example":"9c1f2a6e-3b7d-4e0a-8f21-5d6c7b8a9e01","description":"UUID of the user the threshold is for. Omit with `teamId` for the organization's own."},"required":false,"description":"UUID of the user the threshold is for. Omit with `teamId` for the organization's own.","name":"userId","in":"query"},{"schema":{"type":"string","pattern":"^[!-~]{1,255}$","description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","example":"0b7e4f1c-6a2d-4c9e-8f35-d1a7b2c93e60"},"required":false,"description":"A value unique to this request, of 1 to 255 printable ASCII characters — a UUID is the usual choice. Retry with the same key within 24 hours and you get the original response back, even if it was a failure, and nothing is done twice. Send a new key whenever you change the request. Keys are private to your API key and organisation.","name":"idempotency-key","in":"header"}],"responses":{"204":{"description":"The threshold is ended, or none was set."},"400":{"description":"Request failed schema validation, or named both a team and a user","content":{"application/problem+json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BadRequestError"},{"$ref":"#/components/schemas/ValidationError"}]}}}},"401":{"description":"Missing or invalid API key in the X-API-Key header","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}}},"403":{"description":"Insufficient permissions to manage policies","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}}},"404":{"description":"No team in your organization has this id, so nothing was read or changed. No user in your organization has this id, so nothing was read or changed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"422":{"description":"No threshold can stand on this usage type yet, so nothing was read or changed.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/UnprocessableEntityError"}}}},"429":{"description":"The API key has used its request quota for the current window. `Retry-After` says how many seconds until it resets.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":3600},"required":true,"description":"Seconds to wait before retrying, counted to the moment this key’s window resets."}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/TooManyRequestsError"}}}},"500":{"description":"Internal server error. Contact support if this persists.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}}}}