{"id":20442580,"url":"https://github.com/bifravst/sim-details","last_synced_at":"2026-01-17T23:31:03.950Z","repository":{"id":242261033,"uuid":"807501671","full_name":"bifravst/sim-details","owner":"bifravst","description":"Provide detailed information about SIM from known partners","archived":false,"fork":false,"pushed_at":"2026-01-16T19:07:48.000Z","size":3182,"stargazers_count":0,"open_issues_count":15,"forks_count":0,"subscribers_count":0,"default_branch":"saga","last_synced_at":"2026-01-17T05:30:47.149Z","etag":null,"topics":["onomondo","sim","wireless-logic"],"latest_commit_sha":null,"homepage":"http://sim-details.nordicsemi.cloud","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bifravst.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-05-29T08:15:16.000Z","updated_at":"2026-01-16T19:17:34.000Z","dependencies_parsed_at":"2024-07-28T06:21:27.303Z","dependency_job_id":"2a46c369-b426-490f-86f6-68806c3c5397","html_url":"https://github.com/bifravst/sim-details","commit_stats":null,"previous_names":["bifravst/sim-details"],"tags_count":248,"template":false,"template_full_name":null,"purl":"pkg:github/bifravst/sim-details","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bifravst%2Fsim-details","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bifravst%2Fsim-details/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bifravst%2Fsim-details/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bifravst%2Fsim-details/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bifravst","download_url":"https://codeload.github.com/bifravst/sim-details/tar.gz/refs/heads/saga","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bifravst%2Fsim-details/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28522306,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T22:11:28.393Z","status":"ssl_error","status_checked_at":"2026-01-17T22:11:27.841Z","response_time":85,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["onomondo","sim","wireless-logic"],"created_at":"2024-11-15T09:41:42.095Z","updated_at":"2026-01-17T23:31:03.921Z","avatar_url":"https://github.com/bifravst.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SIM Details\n\n[![Test and Release](https://github.com/bifravst/sim-details/actions/workflows/test-and-release.yaml/badge.svg?branch=saga)](https://github.com/bifravst/sim-details/actions/workflows/test-and-release.yaml)\n[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)\n[![Renovate](https://img.shields.io/badge/renovate-enabled-brightgreen.svg)](https://renovatebot.com)\n[![@commitlint/config-conventional](https://img.shields.io/badge/%40commitlint-config--conventional-brightgreen)](https://github.com/conventional-changelog/commitlint/tree/master/@commitlint/config-conventional)\n[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier/)\n[![ESLint: TypeScript](https://img.shields.io/badge/ESLint-TypeScript-blue.svg)](https://github.com/typescript-eslint/typescript-eslint)\n\nProvides usage information about SIM cards that have been shipped with Nordic\nSemiconductor development kits.\n\nDeveloped using [AWS CDK](https://aws.amazon.com/cdk) in\n[TypeScript](https://www.typescriptlang.org/).\n\n## Usage\n\n### Basic usage\n\nusing [HTTPie](https://httpie.io/):\n\n```bash\nhttp https://api.sim-details.nordicsemi.cloud/2024-07-01/sim/\u003cyour SIM's ICCID\u003e\n```\n\nReturns\n\n```json\n{\n  \"totalBytes\": 10000000,\n  \"usedBytes\": 0,\n  \"ts\": \"2024-07-01T12:11:43.066Z\"\n}\n```\n\nUsing\n\n```bash\nhttp https://api.sim-details.nordicsemi.cloud/2024-07-01/sim/\u003cyour SIM's ICCID\u003e/history?timespan=\u003ctimespan\u003e\n```\n\nwith one of the following timespans:\n\n```\nlastHour | lastDay | lastWeek  | lastMonth\n```\n\nReturns\n\n```json\n[\n  { \"ts\": \"2024-07-01T12:00:00.000Z\", \"usedBytes\": 50 },\n  { \"ts\": \"2024-07-01T12:05:00.000Z\", \"usedBytes\": 100 },\n  { \"ts\": \"2024-07-01T12:10:00.000Z\", \"usedBytes\": 0 },\n  { \"ts\": \"2024-07-01T12:15:00.000Z\", \"usedBytes\": 45 },\n  { \"ts\": \"2024-07-01T12:20:00.000Z\", \"usedBytes\": 344221 },\n  { \"ts\": \"2024-07-01T12:25:00.000Z\", \"usedBytes\": 854 },\n  { \"ts\": \"2024-07-01T12:30:00.000Z\", \"usedBytes\": 0 },\n  { \"ts\": \"2024-07-01T12:35:00.000Z\", \"usedBytes\": 30 },\n  { \"ts\": \"2024-07-01T12:40:00.000Z\", \"usedBytes\": 25 },\n  { \"ts\": \"2024-07-01T12:45:00.000Z\", \"usedBytes\": 0 },\n  { \"ts\": \"2024-07-01T12:50:00.000Z\", \"usedBytes\": 400 },\n  { \"ts\": \"2024-07-01T12:55:00.000Z\", \"usedBytes\": 50 }\n]\n```\n\nfor the last hour.\n\n### Caching of data\n\nEvery hour we cache usage information about **active** SIMs. For Onomondo a SIM\nis treated as **active** if it has been used that day. For Wireless Logic a SIM\nis treated as **active** if it is in the database, meaning it has been\nrequested/updated within the last 30 days.\n\nIf you send a request for a SIM that is cached you will first get the cached\nusage, and if the data is more than 5 minutes old we will fetch updated data in\nthe background. By sending the same request again you will get the updated data\nonce it is fetched from the issuers API.\n\nIf you have never used the SIM before there is no cached data. During the first\nrequest you will get a 409 status code and no data. In the background we will\ntry to fetch the updated data usage from the issuers API. By sending the same\nrequest again you will get the updated data once it is fetched from the issuers\nAPI. If the SIM is not existing you will get a 404 status code in the second\nrequest. If the SIM is not existing this will be cached for 30 days, and we will\nnot try to fetch new data from the issuer during this period.\n\nIf you send a request with a non valid ICCID you will get a 400 status code with\nan explanation of why it didn't validate in the response body.\n\n### Data history\n\nFor WL (Wireless Logic) we have a lambda\n[getAllSimUsageWirelessLogic.ts](./getAllSimUsageWirelessLogic.ts) that runs\nevery 5 minutes for updating the DynamoDB value for the usage per active SIM.\nFor WL an active SIM means that it is in DynamoDB.\n\n[getAllSimUsageWirelessLogic.ts](./getAllSimUsageWirelessLogic.ts) will fetch\nthe data usage from WL API every 5 minutes. This usage is then compared to the\nprevious value in DynamoDB (from our last fetch), and the difference between\nthose values is written to Timestream.\n\nAnother lambda where we fetch from WL API is\n[storeSimInformationWirelessLogic.ts](./storeSimInformationWirelessLogic.ts).\nThis lambda is doing the same as getAllSimUsageWirelessLogic, and the only\ndifference is that it fetches data for one specific SIM that is received from a\nqueue. By also writing to Timestream in this function we cover every usage\nupdate from WL and we can use the same logic as earlier where the data would be\nupdated every 5 minutes.\n\nFor Onomondo we have a lambda\n[getAllSimUsageOnomondo.ts](./getAllSimUsageOnomondo.ts) which runs every hour\nfor updating the DynamoDB value and Timestream history. The function will\nrequest all usage within the current day, and store the usage chunks in\nTimestream. This way we have all the history in Timestream. This function also\nupdates the total usage which is stored in DynamoDB.\n\nAnother lambda for fetching data from Onomondo is\n[storeSimInformationOnomondo.ts](./storeSimInformationOnomondo.ts). This lambda\nis also fetching data from Onomondo API, but this happens when a user requests\nthe history through our API. History from that specific SIM is then requested\nfrom Onomondo API, and then stored in Timestream. The usage in DynamoDB is also\nupdated.\n\n### API Response\n\nThe API will return different status codes based on different scenarios:\n\n| Status Code | Explanation                                                                                                                                   | Cache max-age |\n| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |\n| 200         | OK. The request was successful and you should get the most recent data from cache. If data is older than 5 minutes, new data will be fetched. | 300           |\n| 400         | Bad Request. The request parameters didn't validate.                                                                                          | 60            |\n| 404         | Not Found. The SIM doesn't exist in the issuers API. This response will be cached for 30 days.                                                | 2592000       |\n| 409         | Conflict. No information about SIM in cache. New data will be fetched from the issuers API.                                                   | 60            |\n| 500         | Internal Error.                                                                                                                               | 0             |\n\n## Installation in your AWS account\n\n### Setup\n\n[Provide your AWS credentials](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-authentication.html).\n\n### Install the dependencies\n\n```bash\nnpm ci\n```\n\n### Run once\n\nConfigure API credentials:\n\n```bash\naws ssm put-parameter --name /sim-details/onomondoKey --type String --value \u003cYour Onomondo API Key\u003e\naws ssm put-parameter --name /sim-details/wirelessLogicKey --type String --value \u003cYour Wireless Logic API Key\u003e\naws ssm put-parameter --name /sim-details/wirelessLogicClientId --type String --value \u003cYour Wireless Logic CLIENT ID\u003e\n```\n\n### Deploy\n\n```bash\nnpx cdk bootstrap # if this is the first time you use CDK in this account\nnpx cdk deploy --all\n```\n\n## Continuous Deployment using GitHub Actions\n\nAfter deploying the stack manually once,\n\n- configure a GitHub Actions environment named `production`\n- create the secret `AWS_ROLE` with the value\n  `arn:aws:iam::\u003caccount ID\u003e:role/\u003cstack name\u003e-cd` and a variable (use the\n  `cdRoleArn` stack output)\n- create the variable `AWS_REGION` with the value `\u003cregion\u003e` (your region)\n- create the variable `STACK_NAME` with the value `\u003cstack name\u003e` (your stack\n  name)\n\nto enable continuous deployment.\n\n```bash\ngh secret set AWS_ROLE --env production --body `arn:aws:iam::\u003caccount ID\u003e:role/\u003cstack name\u003e-cd`\ngh variable set AWS_REGION --env production --body \u003cregion\u003e\ngh variable set STACK_NAME --env production --body \u003cstack name\u003e\n```\n\n### Custom API domain\n\nOptionally, a custom API domain can be configured.\n\nFor this, create a certificate for the domain name in the Certificate Manager of\nthe production account in the region of the deployment.\n\nCreate a role in the account that manages the domain name, to allow the the\nproduction account to update the CNAME for the API domain with these permissions\n(make sure to replace `\u003cHosted Zone ID\u003e`, `\u003capi domain name\u003e`):\n\n```json\n{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": \"route53:ChangeResourceRecordSets\",\n      \"Resource\": \"arn:aws:route53:::hostedzone/\u003cHosted Zone ID\u003e\",\n      \"Condition\": {\n        \"ForAllValues:StringEquals\": {\n          \"route53:ChangeResourceRecordSetsNormalizedRecordNames\": [\n            \"\u003capi domain name\u003e\"\n          ],\n          \"route53:ChangeResourceRecordSetsRecordTypes\": [\"CNAME\"],\n          \"route53:ChangeResourceRecordSetsActions\": [\"UPSERT\"]\n        }\n      }\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": \"route53:ListHostedZonesByName\",\n      \"Resource\": \"*\"\n    }\n  ]\n}\n```\n\nThen, for continuous deployment:\n\n- create the variable `API_DOMAIN_NAME` with the name of the api domain, e.g.\n  `api.hello.nordicsemi.cloud`\n- create the secret `API_DOMAIN_ROUTE_53_ROLE_ARN` with the role ARN of the role\n  that allows the production account to update the CNAME for the API domain.\n\n```bash\ngh variable set API_DOMAIN_NAME --env production --body api.sim-details.nordicsemi.cloud\ngh secret set API_DOMAIN_ROUTE_53_ROLE_ARN --env production --body `arn:aws:iam::\u003caccount ID\u003e:role/\u003crole name\u003e`\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbifravst%2Fsim-details","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbifravst%2Fsim-details","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbifravst%2Fsim-details/lists"}