{"openapi":"3.0.0","paths":{"/account":{"get":{"operationId":"getAccount","parameters":[{"name":"Api-Version","in":"header","description":"API version","required":false,"schema":{"type":"string","default":"1"}},{"name":"Correlation-Id","required":false,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountSummaryDto"}}}},"401":{"description":"The access token is missing, invalid or expired: refresh it, or sign the user in again.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"ACCOUNT_NOT_FOUND: the caller has no account yet. Create one with POST /account, collecting first_name/last_name only when the token has no given_name/family_name.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"ACCOUNT_LINK_BROKEN: the caller is linked to an account that no longer exists. Contact support.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"oauth2":["openid","profile","email"]},{"bearer":[]}],"summary":"Get the caller's account","tags":["Account"]},"post":{"description":"Creates the account and links it to the Keycloak user; the account id is carried on tokens issued after this call. first_name/last_name are only required when the token has no given_name/family_name. If the caller already has an account, nothing is changed and 409 ACCOUNT_ALREADY_EXISTS is returned.","operationId":"createAccount","parameters":[{"name":"Api-Version","in":"header","description":"API version","required":false,"schema":{"type":"string","default":"1"}},{"name":"Correlation-Id","required":false,"in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAccountRequestDto"}}}},"responses":{"201":{"description":"Account created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountSummaryDto"}}}},"400":{"description":"VALIDATION_FAILED, including first_name/last_name when missing from both the body and the token","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"The access token is missing, invalid or expired: refresh it, or sign the user in again.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"ACCOUNT_ALREADY_EXISTS: the caller already has an account, which is left unchanged; read it with GET /account","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"The request failed on our side. Quote `trace_id` to aisim.now support.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"oauth2":["openid","profile","email"]},{"bearer":[]}],"summary":"Create the caller's account","tags":["Account"]}},"/product-offerings":{"get":{"description":"Callable by a signed-in user, or by a backend service with a client-credentials token whose service account holds the `product-offerings:read` role.","operationId":"searchProductOfferings","parameters":[{"name":"Api-Version","in":"header","description":"API version","required":false,"schema":{"type":"string","default":"1"}},{"name":"country","required":true,"in":"query","description":"ISO 3166-1 alpha-2 country code to search product offerings for","schema":{"example":"US","type":"string"}},{"name":"cursor","required":false,"in":"query","description":"Opaque cursor from a previous page's `paging.next_cursor`","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":40,"default":20,"type":"number"}},{"name":"Correlation-Id","required":false,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListProductOfferingsResponseDto"}}}},"401":{"description":"The access token is missing, invalid or expired: refresh it, or sign the user in again.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"The request failed on our side. Quote `trace_id` to aisim.now support.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"oauth2":["openid","profile","email"]},{"bearer":[]}],"summary":"Search product offerings available for a country","tags":["Product Offerings"]}},"/purchases":{"post":{"operationId":"createPurchase","parameters":[{"name":"Api-Version","in":"header","description":"API version","required":false,"schema":{"type":"string","default":"1"}},{"name":"Correlation-Id","required":false,"in":"header","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePurchaseRequestDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseResponseDto"}}}},"401":{"description":"The access token is missing, invalid or expired: refresh it, or sign the user in again.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"422":{"description":"Account is not fully set up","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"The request failed on our side. Quote `trace_id` to aisim.now support.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"oauth2":["openid","profile","email"]},{"bearer":[]}],"summary":"Trigger the purchase experience for a product offering","tags":["Purchases"]}},"/products":{"get":{"operationId":"listProducts","parameters":[{"name":"Api-Version","in":"header","description":"API version","required":false,"schema":{"type":"string","default":"1"}},{"name":"cursor","required":false,"in":"query","description":"Opaque cursor from a previous page's `paging.next_cursor`","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"Correlation-Id","required":false,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListProductsResponseDto"}}}},"401":{"description":"The access token is missing, invalid or expired: refresh it, or sign the user in again.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"The request failed on our side. Quote `trace_id` to aisim.now support.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"oauth2":["openid","profile","email"]},{"bearer":[]}],"summary":"List the caller's purchased products, newest first, one page at a time","tags":["Products"]}},"/products/{product_id}":{"get":{"operationId":"getProduct","parameters":[{"name":"Api-Version","in":"header","description":"API version","required":false,"schema":{"type":"string","default":"1"}},{"name":"product_id","required":true,"in":"path","schema":{"type":"string"}},{"name":"Correlation-Id","required":false,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductDto"}}}},"401":{"description":"The access token is missing, invalid or expired: refresh it, or sign the user in again.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"The request failed on our side. Quote `trace_id` to aisim.now support.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"oauth2":["openid","profile","email"]},{"bearer":[]}],"summary":"Get a purchased product's details","tags":["Products"]}},"/esims":{"get":{"operationId":"listEsims","parameters":[{"name":"Api-Version","in":"header","description":"API version","required":false,"schema":{"type":"string","default":"1"}},{"name":"Correlation-Id","required":false,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListEsimsResponseDto"}}}},"401":{"description":"The access token is missing, invalid or expired: refresh it, or sign the user in again.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"The request failed on our side. Quote `trace_id` to aisim.now support.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"oauth2":["openid","profile","email"]},{"bearer":[]}],"summary":"List the caller's eSIMs, with the plans on each and whether a plan can be added","tags":["eSIMs"]}},"/esims/{esim_id}":{"delete":{"description":"Can not be undone: the eSIM stops working. Always confirm with the user first. The eSIM leaves GET /esims once removed, usually within a few minutes.","operationId":"removeEsim","parameters":[{"name":"Api-Version","in":"header","description":"API version","required":false,"schema":{"type":"string","default":"1"}},{"name":"esim_id","required":true,"in":"path","schema":{"type":"string"}},{"name":"Correlation-Id","required":false,"in":"header","schema":{"type":"string"}}],"responses":{"202":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveEsimResponseDto"}}}},"401":{"description":"The access token is missing, invalid or expired: refresh it, or sign the user in again.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"NOT_FOUND: no such eSIM for the caller","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"ESIM_IN_USE: a plan on it is awaiting payment or in use; it can be removed once its plans have ended. ESIM_CANCEL_IN_PROGRESS: it is being changed right now; try again in a few minutes.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"The request failed on our side. Quote `trace_id` to aisim.now support.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"oauth2":["openid","profile","email"]},{"bearer":[]}],"summary":"Remove an eSIM the user no longer uses","tags":["eSIMs"]}}},"info":{"title":"aisim.now API","description":"Browse data plans, buy eSIMs and check their usage on behalf of a signed-in aisim.now user.\n\n**Errors.** Every error is an RFC 9457 problem details object (`application/problem+json`, the `ProblemDetails` schema). Branch on `status` and `code`, and quote `trace_id` to aisim.now support.\n\n**Versioning and deprecation.** Send `Api-Version: 1`; a request without it is treated as version 1. Breaking changes ship only as a new `Api-Version`, so calls that send version 1 keep working. An operation due to be removed is marked `deprecated` in this spec before it is removed.","version":"1.0","contact":{}},"tags":[],"servers":[{"url":"https://api.aisim.now"}],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"JWT","type":"http"},"oauth2":{"type":"oauth2","flows":{"authorizationCode":{"authorizationUrl":"https://api.1global.com/auth/realms/aisim-now/protocol/openid-connect/auth","tokenUrl":"https://api.1global.com/auth/realms/aisim-now/protocol/openid-connect/token","scopes":{"openid":"Sign in","profile":"Name","email":"Email address"}}}}},"schemas":{"AddressDto":{"type":"object","properties":{"line1":{"type":"string","example":"123 Main St","maxLength":200},"line2":{"type":"string","maxLength":200},"city":{"type":"string","example":"Dallas","maxLength":200},"postal_code":{"type":"string","example":"75201"},"country":{"type":"string","description":"ISO 3166-1 alpha-2 country code","example":"US"},"state":{"type":"string","description":"Required for US and CA addresses: a US state/territory or Canadian province/territory code. Ignored for other countries","example":"TX","enum":["AL","AK","AZ","AR","CA","CO","CT","DE","FL","GA","HI","ID","IL","IN","IA","KS","KY","LA","ME","MD","MA","MI","MN","MS","MO","MT","NE","NV","NH","NJ","NM","NY","NC","ND","OH","OK","OR","PA","RI","SC","SD","TN","TX","UT","VT","VA","WA","WV","WI","WY","AS","DC","GU","MP","PR","VI","AB","BC","MB","NB","NL","NS","NT","NU","ON","PE","QC","SK","YT"]}},"required":["country"]},"AccountSummaryDto":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"display_name":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"},"address":{"$ref":"#/components/schemas/AddressDto"}},"required":["id","email","first_name","last_name","address"]},"CreateAccountRequestDto":{"type":"object","properties":{"display_name":{"type":"string","maxLength":200},"first_name":{"type":"string","description":"Required when the token has no given_name","maxLength":100},"last_name":{"type":"string","description":"Required when the token has no family_name","maxLength":100},"locale":{"type":"string","enum":["ar","bg","cs","da","de","el","en","en-GB","es","es-419","et","fi","fil","fr","fr-CA","he","hr","hu","id","it","ja","ko","lt","lv","ms","mt","nb","nl","pl","pt","pt-BR","ro","ru","sk","sl","sv","th","tr","vi","zh","zh-HK"],"example":"pt-BR","description":"The language of the checkout pages. Leave it out to let the checkout pick it."},"address":{"$ref":"#/components/schemas/AddressDto"}},"required":["address"]},"ValidityPeriodDto":{"type":"object","properties":{"unit":{"type":"string","enum":["day","month","year"]},"unit_count":{"type":"number"},"is_recurrent":{"type":"boolean"}}},"AllowanceSummaryDto":{"type":"object","properties":{"type":{"type":"string","enum":["data","voice","sms"]},"is_unlimited":{"type":"boolean"},"unit":{"type":"string","enum":["bytes","megabytes","gigabytes","seconds","count"]},"unit_count":{"type":"number"}},"required":["type","is_unlimited"]},"FootprintDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["local","regional","global"]},"countries":{"description":"ISO 3166-1 alpha-2 country codes","type":"array","items":{"type":"string"}}},"required":["id","name","type","countries"]},"ProductOfferingDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"amount":{"type":"number","description":"The one-time price charged at checkout"},"currency":{"type":"string","description":"ISO 4217 currency of amount"},"validity":{"$ref":"#/components/schemas/ValidityPeriodDto"},"allowances":{"type":"array","items":{"$ref":"#/components/schemas/AllowanceSummaryDto"}},"footprint":{"type":"array","items":{"$ref":"#/components/schemas/FootprintDto"}}},"required":["id","name","amount","currency","allowances","footprint"]},"PagingDto":{"type":"object","properties":{"next_cursor":{"type":"string","nullable":true,"description":"Pass as `cursor` to fetch the next page; null when there isn't one."}}},"ListProductOfferingsResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ProductOfferingDto"}},"paging":{"$ref":"#/components/schemas/PagingDto"}},"required":["data","paging"]},"CreatePurchaseRequestDto":{"type":"object","properties":{"product_offering_id":{"type":"string","description":"The product offering id to purchase"},"esim_id":{"type":"string","description":"An eSIM of the user (from GET /esims, with `topup_available`) to add the plan to, instead of getting a new eSIM. Nothing to install. Leave it out for a new eSIM"}},"required":["product_offering_id"]},"PurchaseProductOfferingDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"PurchaseResponseDto":{"type":"object","properties":{"purchase_id":{"type":"string","description":"Id of the created product; use with GET /products/{product_id} to track progress"},"status":{"type":"string","enum":["pending_payment","processing","failed"]},"checkout_url":{"type":"string","description":"Hosted payment session URL to redirect the user to, when payment is required"},"product_offering":{"$ref":"#/components/schemas/PurchaseProductOfferingDto"},"created_at":{"type":"string"}},"required":["purchase_id","status"]},"ProductOfferingSummaryDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"}},"required":["id","name"]},"UsageBalanceDto":{"type":"object","properties":{"type":{"type":"string","enum":["data","voice","sms"]},"is_unlimited":{"type":"boolean"},"unit":{"type":"string","enum":["bytes","minutes","count"]},"initial":{"type":"number","description":"Absent when `is_unlimited` is true"},"spent":{"type":"number","description":"Absent when Connect does not report consumption, which it may omit for unlimited balances"},"remaining":{"type":"number","description":"Absent when `is_unlimited` is true"}},"required":["type","is_unlimited","unit"]},"ManualInstallationDto":{"type":"object","properties":{"smdp_address":{"type":"string","description":"SM-DP+ address","example":"rsp.truphone.com"},"activation_code":{"type":"string","description":"Activation code (matching id)","example":"5C-39YO3X-1IW7SC8"}},"required":["smdp_address","activation_code"]},"ProductLocationDto":{"type":"object","properties":{"current_country":{"type":"string","description":"ISO 3166-1 alpha-2 code of the country the eSIM last landed in","example":"PT"},"landed_at":{"type":"string","description":"When the eSIM landed in that country","format":"date-time"}}},"ProductDto":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["pending_payment","processing","active","suspended","terminated","failed"]},"checkout_url":{"type":"string","description":"The checkout page of a purchase still waiting to be paid: the same `checkout_url` POST /purchases returned. Only on GET /products/{product_id} while the status is `pending_payment`, and only when it can be read","format":"uri"},"product_offering":{"$ref":"#/components/schemas/ProductOfferingSummaryDto"},"esim_id":{"type":"string","description":"The eSIM this plan is on (see GET /esims). Absent for a new eSIM until it is created, shortly after payment"},"topup":{"type":"boolean","description":"True when the plan was added to an eSIM the user already has: there is nothing to install, so no install links are returned"},"footprint":{"type":"array","items":{"$ref":"#/components/schemas/FootprintDto"}},"usage":{"type":"array","items":{"$ref":"#/components/schemas/UsageBalanceDto"}},"iccid":{"type":"string"},"phone_number":{"type":"string"},"auto_renew":{"type":"boolean","description":"Present only while `status` is `active`"},"apple_activation_url":{"type":"string","description":"Apple eSIM universal install link, derived from the eSIM profile once assigned","format":"uri"},"android_activation_url":{"type":"string","description":"Android eSIM install link (Android 10+ with recent Google Play services), derived from the eSIM profile once assigned","format":"uri"},"qr_code_url":{"type":"string","description":"Image (PNG) of the eSIM QR code, derived from the eSIM profile once assigned. Show it to users who are not on the phone that will get the eSIM (e.g. on a laptop), to scan with that phone","format":"uri"},"manual_installation":{"description":"What to enter in the phone's eSIM settings when no install link or QR code can be used, once the eSIM profile is assigned","allOf":[{"$ref":"#/components/schemas/ManualInstallationDto"}]},"expires_at":{"type":"string","description":"When the plan ends. Absent until the plan starts, which happens on its first data use in a covered country","format":"date-time"},"validity_started_at":{"type":"string","description":"When the plan's validity started (its first data use in a covered country). Absent until then","format":"date-time"},"location":{"description":"Where the eSIM last landed. Absent until a landing is reported","allOf":[{"$ref":"#/components/schemas/ProductLocationDto"}]},"suspended_at":{"type":"string"},"terminated_at":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","status","product_offering","footprint","created_at"]},"ListProductsResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ProductDto"}},"paging":{"$ref":"#/components/schemas/PagingDto"}},"required":["data","paging"]},"EsimDto":{"type":"object","properties":{"id":{"type":"string","description":"The eSIM id. Send it as `esim_id` on POST /purchases to add a plan to this eSIM."},"iccid":{"type":"string","description":"The eSIM's serial number (ICCID), to help the user recognise it"},"status":{"type":"string","description":"The eSIM status: `active` for an eSIM that can be used; other values while it is set up or suspended","enum":["active","created","deactivated","grace","suspended"]},"profile_status":{"type":"string","description":"Whether the eSIM is on a phone, when known: `installed`, `deleted` or `ready_for_installation`"},"topup_available":{"type":"boolean","description":"Whether a plan can be added to this eSIM now (a top-up, with nothing to install)"},"topup_unavailable_reason":{"type":"string","description":"Why a plan cannot be added now: `not_active` (the eSIM is not active), `profile_deleted` (the eSIM was deleted from the phone) or `plan_limit_reached` (15 plans are already waiting or in use on it; one frees up when a plan ends)","enum":["not_active","profile_deleted","plan_limit_reached"]},"plans":{"description":"The plans bought for this eSIM, newest first","type":"array","items":{"$ref":"#/components/schemas/ProductDto"}},"created_at":{"type":"string","format":"date-time"}},"required":["id","topup_available","plans"]},"ListEsimsResponseDto":{"type":"object","properties":{"data":{"description":"The caller's eSIMs that haven't been removed, newest first","type":"array","items":{"$ref":"#/components/schemas/EsimDto"}}},"required":["data"]},"RemoveEsimResponseDto":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["removal_requested","removed"],"description":"`removal_requested`: the eSIM is being removed and leaves GET /esims shortly. `removed`: it was already removed."}},"required":["id","status"]},"ProblemDetails":{"type":"object","description":"RFC 9457 problem details, the body of every error. Branch on `status` and `code`, and quote `trace_id` to aisim.now support. Server errors carry no `detail`.","required":["title","status","trace_id"],"properties":{"title":{"type":"string","example":"Bad Request"},"status":{"type":"integer","example":400},"detail":{"type":"string","example":"Request validation failed"},"code":{"type":"string","description":"Machine-readable error code.","example":"VALIDATION_FAILED"},"errors":{"type":"array","description":"Present only when specific fields are at fault.","items":{"type":"object","required":["detail"],"properties":{"field":{"type":"string","description":"The field, by the request's own property path.","example":"address.state"},"detail":{"type":"string","example":"state is required for US addresses"},"code":{"type":"string"}}}},"reason":{"type":"string","description":"Why the request was refused, for codes with several causes (e.g. `TOPUP_TARGET_NOT_AVAILABLE`)."},"limit":{"type":"integer","description":"The limit that was reached (e.g. `ESIM_LIMIT_REACHED`)."},"trace_id":{"type":"string","description":"Identifies the request.","example":"4f7c1f0e-3b8a-4d57-9f5e-2f8f3a1c9b21"}}}}}}