Can, May, and Permission in APIs
LESSON
Can, May, and Permission in APIs
By the end of this lesson, you will be able to...
Use
mayto express permission in short API and product-contract sentences.Separate permission from capability when
canwould be ambiguous.Compare optional, required, forbidden, and technically possible behavior in an API comment.
Idea in one sentence: In API language,
maysays "this is allowed";canoften says "this is possible."
Core Insight
Lesson 013 separated two negative meanings:
The service must not expose private tokens.
Clients do not have to send the legacy header.
Must not means forbidden.
Do not have to means not required.
This lesson adds a third meaning:
Clients may send one optional filter.
May means permitted. The client is allowed to send the filter. The client is not required to send it. The filter is not forbidden.
That sounds small, but it matters in API documentation. A single sentence can decide what a client is allowed to send, what the server promises to accept, and what support engineers can call a valid request.
The Small Situation
Imagine a customer export API:
POST /exports
The endpoint starts an export job. The client can request a narrower export by sending one optional date filter.
The team is writing a short contract comment for the endpoint:
Clients may send one optional filter.
This is the central practice line for this lesson.
It says the client has permission. A request with one filter is allowed. A request with no filter is also allowed, because the filter is optional.
Now compare it with a sentence from lesson 001:
The worker can process two queues at once.
There, can describes capability. The worker has the ability to process two queues. It is about what the system is able to do.
The API sentence is different. We are not mainly asking whether the server has enough CPU, code, or storage. We are asking what the client is allowed to send.
That is why may is useful in API language.
The Naive Sentence
A teammate writes this:
Clients can send one optional filter.
In everyday English, this is common. Many people use can for permission:
You can open the dashboard.
You can retry the request.
Clients can send one optional filter.
In a chat message, that may be fine.
In an API contract, it can become ambiguous.
Does can mean the client is allowed to send the filter?
Or does it mean the server is technically able to process the filter?
Those are close, but not identical.
The server might be able to parse two filters, but the contract may allow only one. The backend might support an internal debug field, but public clients must not send it. Capability is about what the system can do. Permission is about what the contract allows.
Better for the public contract:
Clients may send one optional filter.
Now the sentence points to permission.
Permission Is Not Capacity
Use this small model:
| Question | Better modal | Example |
|---|---|---|
| What is technically possible? | can |
The API can process one date filter efficiently. |
| What is allowed by the contract? | may |
Clients may send one optional date filter. |
| What is required? | must / have to |
Clients must include an idempotency key. |
| What is forbidden? | must not |
Clients must not send private tokens. |
| What is not required? | do not have to |
Clients do not have to send the legacy header. |
The same object can appear in more than one sentence.
The API can process one date filter efficiently.
Clients may send one date filter.
The first sentence tells us about the server's capability.
The second sentence tells us about the client's permission.
They often match, but they do not have to match.
For example:
The server can parse the old debug field, but clients must not send it.
The server has the technical ability. The client does not have permission.
This is one of the most useful contrasts in this track: English modals do not only describe grammar. They control commitment, permission, and responsibility.
A Worked API Trace
Here is the endpoint contract:
Endpoint: POST /exports
Required:
- idempotency_key
Optional:
- date_from
- date_to
Forbidden:
- private_token
Deprecated but still accepted:
- X-Export-Mode: async
We want to write contract sentences that match those buckets.
| Contract bucket | Sentence |
|---|---|
| required | Clients must include an idempotency key. |
| optional / permitted | Clients may send one optional date filter. |
| forbidden | Clients must not send private tokens. |
| not required | Clients do not have to send the legacy export-mode header. |
| capability | The API can process one date filter efficiently. |
Now trace four requests.
| Request | What the client sends | Contract result | Why |
|---|---|---|---|
| A | idempotency_key only |
valid | the required key is present; the optional filter is omitted |
| B | idempotency_key, date_from |
valid | clients may send one optional filter |
| C | idempotency_key, date_from, date_to, status |
invalid or rejected | the contract allows one optional filter, not several |
| D | idempotency_key, private_token |
invalid and unsafe | clients must not send private tokens |
The important part is request C.
A developer might say:
But the server can parse several filters.
That may be true. It is still not enough.
If the public contract says:
Clients may send one optional filter.
then a request with several filters is outside the contract. The server might reject it. The support team can say the request is invalid. The docs can stay precise.
So the path is:
input: a client sends fields
transition: the API checks the contract buckets
intermediate state: required, optional, forbidden, and deprecated fields are classified
decision: accept, reject, or warn
naive failure: treating "the server can parse it" as the same as "the client may send it"
That naive failure is common. It mixes implementation capacity with permission.
May for Permission and May for Uncertainty
Lesson 006 used may and might for uncertainty:
The spike might be related to the deploy.
The new timeout may reduce duplicate work.
In those sentences, may means "it is possible."
This lesson uses may in a different way:
Clients may send one optional filter.
Here, may means "allowed."
How do you know which meaning is active?
Look at the subject and the context.
If the subject is a client, user, caller, service owner, or team member doing an allowed action, may often means permission:
Clients may omit the legacy header.
Operators may retry the export after the timeout.
If the subject is a result, symptom, behavior, or risk, may often means uncertainty:
The queue spike may be related to the deploy.
The change may increase memory usage.
The grammar word is the same. The technical job is different.
Common Confusions
Confusion: can always means permission
Why it is tempting:
In everyday English, people often use can to ask for or give permission.
Can I restart the worker?
You can restart the worker after the deploy.
Better model:
In technical writing, can is very natural for capability. Use it when you mean "is able to."
The worker can restart without losing the job state.
Use may when the permission itself is the contract.
Operators may restart the worker after the deploy window opens.
Confusion: optional means unimportant
Why it is tempting:
The word optional can sound like the field does not matter.
Better model:
Optional means not required. It does not mean meaningless.
Clients may send one optional date filter.
The filter can still change the result. It limits which records are exported. It is optional because the client is allowed to omit it.
Confusion: not required means forbidden
Why it is tempting:
Negative phrases feel similar when you read quickly.
Better model:
Keep these three separate:
Clients do not have to send the legacy header.
Clients may send one optional filter.
Clients must not send private tokens.
The legacy header is not required.
The optional filter is permitted.
The private token is forbidden.
Trade-offs and Limits
The trade-off is tone versus precision.
May is precise in contracts and docs. It clearly says "allowed." It also sounds more formal than everyday chat.
In a Slack message, this may sound a little stiff:
You may retry the job now.
This is more natural in chat:
You can retry the job now.
But in API documentation, precision often matters more than casual tone:
Clients may retry the request with the same idempotency key.
That sentence tells the client what the contract allows.
This does not solve every contract problem. If the docs say may but the server rejects the request, the docs and implementation disagree. The modal verb makes the intended rule visible, but tests and behavior still have to match it.
You can see the boundary when a support ticket says:
The docs say clients may send this field, but the API returns 400.
At that point, the English sentence is doing its job. It exposes the mismatch.
A Documentation Before and After
Now look at a rough paragraph from the export API docs:
You can send filters. Do not send token. Header not needed.
The meaning is partly visible, but the contract is not stable enough.
First problem: filters is plural. Does that mean one filter, two filters, or any number of filters? The implementation may only support one efficient filter. The support team needs a sentence that gives a clear boundary.
Second problem: Do not send token sounds like a command, but it does not name the field. Is it a private token? An idempotency token? An access token used by the caller? The noun matters because security sentences should leave very little guessing.
Third problem: Header not needed is understandable, but it is too compressed for public docs. It does not say whether the header is still accepted during migration or forbidden after cleanup.
Here is a clearer version:
Clients may send one optional date filter. Clients must not send private tokens. Clients do not have to send the legacy export-mode header during the migration period.
This version is longer, but each sentence has one job.
The first sentence gives permission:
Clients may send one optional date filter.
The second sentence forbids a dangerous field:
Clients must not send private tokens.
The third sentence removes an old requirement:
Clients do not have to send the legacy export-mode header during the migration period.
Notice the discipline: do not make one modal verb carry three meanings. In technical English, short is useful only when the reader still knows the rule.
If you want to keep the docs compact, use a list:
Clients:
- must include an idempotency key;
- may send one optional date filter;
- must not send private tokens;
- do not have to send the legacy export-mode header during migration.
This list is easy to scan. It also keeps each modal close to the field it controls. That closeness helps reviewers notice contract mistakes early.
Check Your Understanding
Check: Which sentence is better for public API permission?
A. Clients can send one optional filter.
B. Clients may send one optional filter.
Think first, then reveal.
Answer: B is better for public API permission. Can is understandable, but it can also sound like capability. May makes the permission explicit.
Check: The server has code that can parse an internal field, but public clients are not allowed to send it. Which sentence matches the contract?
A. Clients may send the internal field.
B. Clients must not send the internal field.
C. The server cannot parse the internal field.
Think first, then reveal.
Answer: B matches the contract. The server's capability is separate from the client's permission. The server can parse the field, but clients must not send it.
Practice
Use the export API contract and choose the modal that fits each meaning.
| Meaning | Write a sentence |
|---|---|
| permitted | Clients ___ send one optional date filter. |
| capable | The API ___ process one date filter efficiently. |
| forbidden | Clients ___ send private tokens. |
| not required | Clients ___ send the legacy export-mode header. |
Model answer:
Clients may send one optional date filter.
The API can process one date filter efficiently.
Clients must not send private tokens.
Clients do not have to send the legacy export-mode header.
Now rewrite this rough comment:
Filter can be sent. Token no. Header no need.
A clearer version:
Clients may send one optional filter. Clients must not send private tokens. Clients do not have to send the legacy export-mode header.
Daily Practice Lines
Read these lines once or twice during the day:
Clients may send one optional filter.
The service must not expose private tokens.
We need to backfill the missing rows.
The first line is new.
The second line comes from lesson 013.
The third line comes from lesson 012.
This small reuse matters. You are not collecting isolated rules. You are building a short technical voice that can say what is allowed, what is forbidden, and what still needs work.
Resources
- [ARTICLE] Cambridge Dictionary Grammar: May - Use it to compare
mayfor permission and possibility. - [ARTICLE] Cambridge Dictionary Grammar: Can - Use it to review
canfor ability and permission. - [ARTICLE] Microsoft Writing Style Guide - Use it as a reference for clear, reader-friendly technical wording.
Key Takeaways
- Use
maywhen the sentence gives permission in an API or technical contract. - Use
canwhen the sentence describes capability: what a service, worker, or API is able to do. - Keep optional, required, forbidden, not required, and technically possible behavior in separate sentences when the contract matters.
← Back to Technical English: Modals and Engineering Judgment