Acumatica · Rest

REST Naming Conventions — A Field Guide

The REST API naming conventions that actually reduce integration friction -- plural nouns, consistent casing, and nesting depth that stays shallow enough to reason about.

John Kihiu12 min read

REST naming conventions are one of the few areas of API design where there's broad, boring, near-universal agreement on what "good" looks like, and yet almost every API I've integrated against violates at least one of these conventions somewhere — usually in a corner added later by a different team than built the original endpoints. None of these rules are subtle; the value is entirely in applying them consistently across the whole surface, not in picking a clever convention nobody's seen before.

Plural nouns for collections, consistently

/invoices for the collection, /invoices/4471 for a specific member — plural throughout, never switching to singular for the collection endpoint just because a single request returns one thing conceptually. The value isn't some deep semantic correctness; it's that a consumer can predict the URL for any resource type without checking docs every time, and tooling (route generators, SDK codegen) that assumes this pattern works without special-casing your API.

HTTP · CONSISTENT RESOURCE NAMING
GET    /invoices          # collection
GET    /invoices/4471     # single member
POST   /invoices          # create
PATCH  /invoices/4471     # partial update
DELETE /invoices/4471     # delete

GET    /invoices/4471/payments   # nested collection
GET    /invoices/4471/payments/9 # nested member

Lowercase, hyphen-separated paths

URIs are case-sensitive per spec, and mixing case or using underscores creates avoidable friction: /invoiceItems versus /invoice_items versus /invoice-items are three different URLs to a strict server, and inconsistency within one API forces every consumer to memorize which convention applies to which endpoint. Lowercase with hyphens (/invoice-items) is the most widely adopted convention and matches URL conventions used elsewhere on the web, which is a real, if soft, argument in its favor — a consumer's existing intuition transfers.

Nest only as deep as the relationship is genuinely owned

/invoices/4471/payments is a reasonable nesting: payments belong to and are scoped by a specific invoice. /customers/88/invoices/4471/payments/9/refunds/2 is not reasonable — by three or four levels deep, the URL has become an ownership chain nobody can type from memory, and it's usually a sign the nested resource actually deserves its own top-level collection with a filter, rather than living at the bottom of an increasingly deep path. A practical rule: nest one level for a genuinely dependent sub-resource, and use a top-level collection with a query filter (/refunds?payment_id=9) for anything beyond that.

Verbs belong in HTTP methods, not URL segments

/invoices/4471/cancel as a POST endpoint is a common and defensible exception — not every state transition maps cleanly to a CRUD verb — but it should be the exception, reserved for actions with no natural resource mapping, not the default pattern for every operation.

Field casing inside the JSON body needs the same discipline

The URL naming convention debate gets most of the attention, but inconsistent field casing inside response bodies — invoice_total next to createdAt next to Status in the same object — is just as much friction for a consumer, and more common because it's easy for different endpoints, built by different people, to drift. Pick one casing convention for the whole API (snake_case or camelCase, either is fine) and enforce it in code review or with an automated schema linter, because it's the kind of inconsistency that's individually trivial and collectively annoying across a whole SDK.

Don't encode a resource's type in its ID

An ID like inv_4471 mixed with plain integer IDs elsewhere in the same API (or worse, IDs that change format between versions) breaks any client code that assumes IDs are opaque, uniformly-typed values. If you want typed-prefix IDs (a legitimate pattern, popularized by Stripe), apply it consistently across every resource type from day one.

Wrapping up

None of these conventions are individually clever, and that's exactly why they work: plural nouns, lowercase hyphenated paths, shallow nesting, and one consistent field-casing scheme remove an entire category of "wait, is it this or that" friction from integration, at zero runtime cost. The discipline is in applying them everywhere, including the endpoint added six months after the original design doc was forgotten.

John Kihiu
Acumatica ERP Developer · Laravel Engineer

Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.