---
name: sap-api-style
source: https://app.decimal.ai/s/sap-api-style@1/SKILL.md
source_sha256: 766aa583172f
---

# SAP API Style Guide conventions

## Contract

Enforces the SAP API Business Hub house style on OpenAPI documents — API naming, the
`x-sap-*` vendor extensions, operation/response wording, lifecycle metadata, and
character limits. Apply whenever you write or edit an `info` block, an operation, a
response, or deprecation metadata for a REST/OData API destined for SAP API Business Hub.
These are arbitrary SAP conventions; do not substitute generic OpenAPI habits.

## Rules

### 1. `info.title` (API name)
- REMOVE the word "API" — it is implied. `"Custom Forms API"` -> `"Custom Forms"`.
- REMOVE a leading `"SAP"` prefix. `"SAP Document Approval"` -> `"Document Approval"`.
- Use a NOUN PHRASE. No verb, gerund, or preposition lead: `"Configuring Portal"` ->
  `"Portal Configuration"`; `"Manage Invoices"` -> `"Invoice Management"`.
- Do NOT embed the protocol (`REST`, `OData`, `SOAP`, `GraphQL`) in the name.
- Do NOT embed a version (`v2`, `OData v4`) in the name — version lives in metadata.
- Use Title Case (capitalize each significant word).
- `info.title` must be at most **80 characters**.

### 2. Short text (catalog tile description)
- Put the one-line tile description in the vendor extension **`x-sap-shortText`**.
- NEVER use `summary`, `shortDescription`, `tagline`, or `info.description` for the
  tile text — those are ignored by the Business Hub tile renderer.
- `x-sap-shortText` must be at most **180 characters**.
- It is distinct from `info.description` (the long description), which may run to ~2
  sentences / 1024 chars.

### 3. Operation `summary` and `description`
- `summary`: action-oriented, starts with a verb (`Creates`, `Retrieves`, `Updates`,
  `Deletes`, `Searches`), no trailing period (preferred), at most **255 characters**.
- `description`: begins with a third-person singular present-tense verb — `Creates`,
  `Retrieves`, `Updates`, `Deletes`, `Returns`, `Replaces`, `Cancels`.
- NEVER begin a description with `"This operation"`, `"This endpoint"`, `"This method"`,
  or `"The API"`.
- NEVER use the second person (`you`, `your`).
- Do NOT repeat the `summary` verbatim in the `description`; the description adds detail
  (side effects, constraints, prerequisites). Omit `description` entirely if it would
  only restate the summary.

### 4. Response descriptions
- State the **specific outcome**, not the generic HTTP reason phrase.
  - `204` -> `"The product was deleted."` NOT `"No Content"`.
  - `404` -> `"The requested product does not exist."` NOT `"Not Found"`.
  - `201` -> `"The sales order was created."` NOT `"Created"`.
  - `409` -> `"An employee with that ID already exists."` NOT `"Conflict"`.

### 5. Lifecycle / deprecation (`x-sap-stateInfo`)
- Mark lifecycle with the vendor extension **`x-sap-stateInfo`** — NOT the bare OpenAPI
  `deprecated: true` flag (the Business Hub reads `x-sap-stateInfo`, not `deprecated`).
- `x-sap-stateInfo.state` is exactly one of: `beta`, `active`, `deprecated`,
  `decommissioned`. The fully-retired state is `decommissioned` — never `retired`,
  `sunset`, `removed`, `obsolete`, or `eol`.
- A `deprecated` API MUST also set:
  - `deprecationDate` — ISO 8601 `YYYY-MM-DD`.
  - `successorApi` — the name of the replacement API.
  - optional: `plannedDecommissionDate` (`YYYY-MM-DD`), `moreInformation` (migration URL).
- `active` is the default; you may state it explicitly but it is not required.
- Timeline: a deprecated API must remain available at least **12 months** after the
  deprecation date before it can be decommissioned, and an API's total lifespan
  (active + deprecated) should be at least **24 months**.

### 6. Other vendor fields & naming
- `x-sap-apiType` is `"REST"` or `"OData"` (this is where the protocol belongs — never
  the title).
- Field/parameter names: camelCase for REST (`employeeId`), PascalCase for OData
  (`EmployeeId`); never `snake_case` or `kebab-case` for JSON fields.

### 7. Character limits (memorize)
| Element | Limit |
|---|---|
| `info.title` | 80 |
| `x-sap-shortText` | 180 |
| Package short description | 250 |
| Operation `summary` | 255 |
| `description` | 1024 |

## Worked examples

**Rule 1 — title strips "API":**
- BEFORE: `title: "Custom Forms API"`
- AFTER:  `title: "Custom Forms"`

**Rule 1 — title strips "SAP":**
- BEFORE: `title: "SAP Document Approval"`
- AFTER:  `title: "Document Approval"`

**Rule 1 — gerund/verb -> noun phrase:**
- BEFORE: `title: "Configuring Customer Portals"`
- AFTER:  `title: "Portal Configuration"`

**Rule 1 — protocol + version in name:**
- BEFORE: `title: "SAP Sales Order OData API v4"`
- AFTER:  `title: "Sales Order"`  (protocol -> `x-sap-apiType: "OData"`, version -> `version:`)

**Rule 1 — over the 80-char limit:**
- BEFORE: `title: "Advanced Real-Time Inventory and Warehouse Stock Level Monitoring and Replenishment Management for SAP S/4HANA"`
- AFTER:  `title: "Inventory and Replenishment Management"`  (38 chars)

**Rule 2 — tile text in the right field:**
- BEFORE: `info: { summary: "Manage employee leave requests" }`
- AFTER:  `info: { x-sap-shortText: "Submit, approve, and track employee leave requests with policy validation" }`

**Rule 3 — operation description:**
- BEFORE: `description: "This endpoint lets you create a new customer record."`
- AFTER:  `description: "Creates a customer record and emits a CustomerCreated event; returns 201 with a Location header."`

**Rule 3 — no summary repetition:**
- summary: `"Create a new user"`
- BEFORE: `description: "Create a new user."`
- AFTER:  `description: "Creates a user account, sends the activation email, and assigns the default role."`

**Rule 4 — specific response outcome:**
- BEFORE: `responses: { '204': { description: "No Content" } }`
- AFTER:  `responses: { '204': { description: "The product was deleted." } }`

**Rule 5 — deprecate, not `deprecated: true`:**
- BEFORE:
  ```yaml
  info:
    title: "Custom Forms"
    deprecated: true
  ```
- AFTER:
  ```yaml
  info:
    title: "Custom Forms"
    x-sap-stateInfo:
      state: deprecated
      deprecationDate: "2026-06-26"
      successorApi: "Custom Forms v2"
      plannedDecommissionDate: "2027-06-26"
  ```

**Rule 5 — beta service:**
- BEFORE: `info: { title: "Shipment Tracking API", x-beta: true }`
- AFTER:
  ```yaml
  info:
    title: "Shipment Tracking"
    x-sap-stateInfo:
      state: beta
  ```

**Rule 5 — decommission term:**
- BEFORE: `state: retired`
- AFTER:  `state: decommissioned`

## Edge cases & exceptions

- **"SAP" inside the name, not a prefix:** strip only the *leading* contextual `SAP`.
  A product name that genuinely contains it for disambiguation may keep it, but default
  to removing it — `"SAP Travel Management"` -> `"Travel Management"`.
- **Acronyms that read as the word "API":** keep legitimate domain acronyms; only drop
  the literal word `API`/`APIs`. `"OAuth"` stays; `"Forms API"` loses `API`.
- **Title at exactly 80 chars:** 80 is allowed (the limit is inclusive); 81 is not.
- **No extra description needed:** if the `summary` already says everything, OMIT
  `description` rather than padding it — an empty description beats a restated one.
- **Deprecated but no successor yet:** the policy still requires `successorApi`; if there
  is genuinely no successor, the API is heading to `decommissioned`, not `deprecated`.
- **active is implicit:** you do not need `x-sap-stateInfo` at all for a healthy API; add
  it only to declare `beta`, `deprecated`, or `decommissioned` (or to be explicit).
- **Date format:** dates are always ISO `YYYY-MM-DD` strings, quoted in YAML; never
  `01/15/2026` or `Jan 15 2026`.

## Do / Don't

- DON'T put `API`, `SAP`, a protocol, or a version in `info.title`. ALWAYS use a bare
  Title-Case noun phrase.
- DON'T write `description: "This operation creates…"`. ALWAYS lead with the bare
  third-person verb `"Creates…"`.
- DON'T address the reader as `you`. ALWAYS describe what the operation does.
- DON'T put the tile text in `summary`/`description`. ALWAYS use `x-sap-shortText`.
- DON'T deprecate with `deprecated: true`. ALWAYS use `x-sap-stateInfo.state: deprecated`
  plus `deprecationDate` and `successorApi`.
- DON'T name the retired state `retired`/`sunset`/`removed`. ALWAYS use `decommissioned`.
- DON'T echo the generic HTTP phrase in a response. ALWAYS state the concrete outcome.

## Common mistakes

The bare base model defaults to these — all wrong for SAP:
- Keeps `"… API"` or a `"SAP "` prefix in the title because that reads natural.
- Names the API with a gerund (`"Managing Orders"`) or embeds `OData`/`v2`.
- Writes `description: "This endpoint allows you to…"` (second person + `"This endpoint"`).
- Copies the `summary` into `description` verbatim.
- Labels a 204 response `"No Content"` and a 404 `"Not Found"` (the HTTP reason phrase).
- Reaches for OpenAPI's standard `deprecated: true` instead of `x-sap-stateInfo`.
- Invents `state: "retired"` / `"sunset"` instead of `decommissioned`.
- Puts the tile line in `summary` or `info.description` instead of `x-sap-shortText`.
- Forgets the 80-char title / 180-char shortText ceilings.

## Quick checklist

- [ ] Title: no `API`, no `SAP`, no protocol, no version, noun phrase, Title Case, ≤80.
- [ ] Tile line in `x-sap-shortText`, ≤180.
- [ ] Operation `description` starts with a third-person verb; no `This …`, no `you`.
- [ ] `description` adds detail beyond `summary` (or is omitted).
- [ ] Response descriptions state the concrete outcome, not the HTTP phrase.
- [ ] Lifecycle via `x-sap-stateInfo`; state ∈ {beta, active, deprecated, decommissioned}.
- [ ] Deprecated has `deprecationDate` (`YYYY-MM-DD`) + `successorApi`; ≥12 months notice.
