What you're dealing with here is a non-technical problem, it's a human one.
There are technical solutions to be found here, but they don't cover the problem in its entirety. To repurpose an old saying, the universe will eventually come up with a bigger idiot that foils your clever technical hurdle.
I'm apprehensive of solving this using a technical hurdle because your attempts at protecting yourself from bigger idiots will take more and more effort and time, on top of likely detracting from the readability and simplicity of your codebase.
So this answer is going to offer some lateral solutions:
Option A - Since you say that the ID content might change in the future to be non-numeric, why not get ahead of the curve and already turn it into a non-numeric value? It stops anyone with numeric intentions dead in their tracks. Even just adding an otherwise ignored prefix (turning 123
into A123
) would suffice.
Option B - If you can't just use non-numerics in production right now (for whatever external reason), if you can control the testing layer you can still intentionally throw in some non-numeric values to test with and see if it breaks.
Option C - If your concern is that developers on your own codebase might make this mistake in the future, I'm worried about the team's trust in one another. If you know that this ID is non-numeric, so should the rest of the team. For trivial mistakes, there's the code review process to catch them. For endemic misconceptions, this seems like a team leadership or mentoring problem to solve - and if the issue is at this level, you're probably going to have more issues of a similar kind.
Option D - If your concern is that other dev teams working in other applications are going to misuse your identifier types, that's on them, not on you. You cannot control what others do, that's why they're a different team than you.
If you clearly document that this field can contain non-numeric characters, then they suffer the consequences of not reading your documentation when their numerical data type breaks once your ID values start changing.
Option E - I guess this is a somewhat technical one. People make bad calls because they're looking for the path of least resistance. If you make the correct path the path of least resistance, then you will find that people naturally gravitate towards doing things the way you want them done.
For example, you could provide a Nuget/npm/... package which provides all the data contracts and maybe even a neat and easy-to-use HTTP client. People will want to adopt it if it saves them the effort of having to do this work themselves, and you can sneakily make sure that they're using the contract the way you intended for it to be designed.
There's no guarantee that they will use your package (like I said before, you cannot control how others consume your service), but it will significantly mitigate the problem. The bigger the idiot, the more likely they will take the path of least resistance (blindly), which tends to mean that the worst offenders are the ones using your package.
Why? Because what might be a "number" now, may not be in the future
. Start using characters and future (idiot) proof your design now.013
gives the number 11, not 13!)