title | description |
---|---|
BC Government API Guidelines |
Province of British Columbia API Guidelines |
NOTE: This is a living document, posted here for your feedback. We gratefully acknowledge the assistance of the Government of Canada in sharing their API standards, providing a baseline for this document.
Published by the Technical Assets Working Group under the BC Data Council
Purpose : The purpose of these guidelines is to promote consistency and provide guidance around the use of Application Programming Interfaces (APIs) across the BC government, and to enable exchange and integration of data between systems, agencies, businesses and citizens.
-
Why API First? – APIs are an efficient and secure way to share data and expose functionality between government's digital services. "API First" is a design principle which stipulates that an API is the first interface for a given application; it is the first artefact to be developed over the data layer, and it is self described.
-
What's in the API Guidelines? – the B.C. Government API Guidelines provide design and best practices for building interfaces between systems or exposing data for secondary use. Other topics include security, metadata, versioning and management. The guidelines have been developed by BC Government IT professionals using internal references and a thorough review of several public and private sector leaders.
-
When to use the API Guidelines? – most real time data integration requirements are best satisfied through APIs. In general, data sharing and integration also encourage the use of APIs to promote platform independence and loosely coupled service design.
- Simplicity and Reusability : strive to make the API the best way for clients to consume your data
- Consistency : design API's with a common look and feel using a consistent style and syntax
- Security by Design : adopt a philosophy where security is inherent in API development
- Continuous Improvement : actively improve and maintain API's over time by incorporating consumer feedback
- Sustainability : avoid short-term optimizations at the expense of unnecessary client-side obligations
- Quality : ensure flexibility, scalability and that your API presents actionable data to the consumer
- Well Described : adopt a simple, consistent and durable API specification and endpoint naming standard that includes API meta information
- Open Standards Based : stay compliant with the standard HTTP methods including status and error codes
- Use a RESTful Approach – use HTTPS request/response format for data access and manipulation and provide proper error responses to the client
- Use JSON – use JavaScript Object Notation (JSON) as the message structure for all web service APIs
- Form responses as a JSON object and not an array
- Use consistent grammar case by using snake_case or CamelCase
- APIs into legacy systems may be required to use a different representation such as XML
- Use URIs to represent resources – URIs (Uniform Resource Identifiers) represent business entities, not the operations on those entities. If data is returned as a part of a response, use URIs to uniquely identify the data as a resource
- Always Use HTTPS –
- ACCEPT and CONTENT-TYPE request headers are mandatory
- AUTHORIZATION header is mandatory for secured APIs
- Pass the API key in the header rather than the URI
- API keys/tokens must be securely setup and used appropriately
- The response must contain the CONTENT-TYPE header
- If caching is desirable, response headers must also include CACHE-CONTROL
- Don't overload verbs – Each verb should represent a single operation on a given resource. Avoid using request parameters to pass additional operations. The following are appropriate uses of HTTP verbs in the context of a RESTful API:
- GET – read either a single or a collection resource
- POST – create a new resource or initiate an action
- PUT – update or replace an existing resource
- DELETE – remove a resource
- Follow properties according to RFC 7231 and RFC 5789:
Method | Safe | Idempotent | Cacheable |
---|---|---|---|
GET | ✔️ Yes | ✔️ Yes | ✔️ Yes |
HEAD | ✔️ Yes | ✔️ Yes | ✔️ Yes |
POST | ❌ No | ❗ No, but Should: Consider To Design POST and PATCH Idempotent | 🔸 May, but only if specific POST endpoint is safe. Hint: not supported by most caches. |
PUT | ❌ No | ✔️ Yes | ❌ No |
PATCH | ❌ No | ❗ No, but Should: Consider To Design POST and PATCH Idempotent | ❌ No |
DELETE | ❌ No | ✔️ Yes | ❌ No |
OPTIONS | ✔️ Yes | ✔️ Yes | ❌ No |
TRACE | ✔️ Yes | ✔️ Yes | ❌ No |
Source: https://opensource.zalando.com/restful-api-guidelines/#http-requests
-
USE W3C HTTP Methods – follow the standard methods as described by the W3 Consortium - https://www.rfc-editor.org/rfc/rfc9110.html#name-methods
-
Segment response data for large queries – APIs exposing large datasets must support some form of data segmentation. The following are some common patterns for pagination along with appropriate use cases:
page
andper_page
– best used to navigate large static datasets (e.g., reference data) where the same set of data is likely to be returned given the same page reference over timeoffset
andlimit
– best used for APIs fronting Structured Query Language (SQL) based backends where the offset represents the data cursor on a given indexed columnsince
andlimit
– Best used for queries where the consumer is interested in the delta since the last query and the backend data structure is indexed based on time
-
Respond with message schemas that are easy to understand and consume - the following practices should be applied:
- Use common information models – Leverage industry recognized common information models where possible. If you must define your own information model, create a model which is technology and platform agnostic and avoid using proprietary schemas
- Standardized error codes – Avoid building custom error codes and schemes which require heavy parsing by the consuming system. Conform to common HTTP status codes when building RESTful API's - https://www.w3.org/Protocols/HTTP/HTRESP.html
- A quality error code will indicate what went wrong and why and should include 3 basic criteria:
1) HTTP Status Code
2) Internal reference ID mapped to internal reference documentation
3) Human readable messaging to summarize the context, cause and a general solution - Standard HTTP error codes are classified as follows:
- 1XX – Informational - protocol state and state of the original request
- 2XX – Success - whether a request was successful, fulfilled or accepted
- 3XX – Redirection - to indicate status of the resource or endpoint; useful in subdomains or moving a resource from one server to another
- 4XX – Client Error - occurences such as when a URI is incorrectly formed or the client has sent too many requests
- 5XX – Server Error - indicates a server side error (not a client issue)
- A quality error code will indicate what went wrong and why and should include 3 basic criteria:
- Abstract internal technical details – Responses, including error messages, should abstract technical details which the API consumer has no visibility into. Internal technical errors, thread dumps, and process identifiers should all be removed from response data
- Implement stateless interactions – The interaction between API consumer and provider must be stateless. APIs must not expect any concept of session or management of state on the part of the consumer. Any transaction where multiple APIs are called in a repeatable sequence to create a singular business interaction should be implemented as a composite API
- Prefer 'Pull' over 'Push' – use APIs to pull data rather than push data into databases. Having consuming systems query APIs based on specific parameters ensures that only data that's required in the context of a business process or transaction is being passed, and that the transmission of data is granular and secure. Data sink APIs and Event Driven Architectures (EDA) often require additional complexity in queuing considerations; however, this approach to data streams can provide lower latency and intermittent fault tolerance than batch or bulk data integration techniques. Bulk or batch data integration techniques and tools should be reserved for data synchronization patterns when network limitations are prevalent, or another limitation dictates its necessity
- Bulk Dataset's via API's – in some cases APIs will be used to transfer bulk datasets between systems or external to BC Government. In those scenarios, apply the following considerations:
- small datasets – Smaller datasets should be returned in low overhead formats (e.g., Comma-separated values (CSV) or JSON) rather than XML. Do not use compressed file attachments as this is a possible method of bypassing content scanning mechanisms
- trigger API – An API may be implemented as a trigger to initiate an out-of-band interface such as a managed file transfer
- search and link API – If the dataset is published on file servers already available to the consumer, an API could be implemented to return a link to a specific file based on specific request parameters
The following practices must be followed for any API which provides access to protected or privileged data and are strongly recommended as part of a "security by design" philosophy for all API development. Outside of this baseline set of security controls, additional controls (e.g., message-level encryption, mutual authentication, and digital signatures) may be required based on the sensitivity of the data:
- Secure Data in Transit – always send data over a secure and encrypted network connection, regardless of data classification; enable TLS 1.2 or higher
- Security by Design – durable API design will include protection against common API attacks such as buffer overflows, SQL injection and cross site scripting. Treat all submitted data as untrusted and validate before processing. Data validation (for both input parameters and inbound data) should be considered in the service tier but should also extend into the data model itself, with such considerations as data staging, mandatory values and referential integrity constraints as appropriate
- See here for the OWASP REST Security Cheat Sheet Project
- Do not put Sensitive Data in URIs – use the JSON payload to submit queries for sensitive data rather than putting it in the URI string
- Authenticate and Authorize – ensure only privileged or authorized users can invoke your API once they are properly authenticated using either an API key or OAUTH token
- Ensure that the API key/secret is adequately secured
- Use API keys with all data API's to track and meter usage
- For each API key, rate limits are applied across all API requests
- For system-to-system integrations consider key/secret revocation and reissue capabilities
- See here for BC Government standards on identity management: https://www2.gov.bc.ca/gov/content/governments/services-for-government/policies-procedures/im-it-standards/find-a-standard#id_mgt
- See here for BC Government standards on general IT security: https://www2.gov.bc.ca/gov/content/governments/services-for-government/policies-procedures/im-it-standards/find-a-standard#it_sec
- Token management – avoid using custom or proprietary tokens in favor of open industry standards such as JSON Web Token (JWT). All access tokens must expire within a reasonable amount of time (less than 24 hours) and refresh intervals should reflect the security characteristics of the data being accessed. Use fine grained access and the principle of least permission when defining tokens
- Restrict dynamic or open queries – the ability to inject consumer defined query strings or objects into an API must be limited to open data, reporting, and statistical APIs only, and strictly prohibited on master data, transactional or business APIs. Dynamic and open queries create dangerous attack surfaces for APIs. It's better to invest more effort in identifying all the valid query use cases and design the API to specifically meet them
- Restrict wildcard queries – wildcard queries in APIs can be dangerous from a data performance perspective. If wildcard characters are allowed, ensure there are restrictions on which and how many parameters can have wildcard input to prevent large data query sizes
- Use gateways and proxies instead of IP whitelists – When exposing APIs to the internet, use a secure gateway layer to provide a security control point instead of simply whitelisting inbound Internet Protocol addresses (IPs). When consuming external APIs, route flows through a forward (egress) proxy instead of using IP address whitelisting on the outbound firewall
- Integrate Security Testing - automate security testing to validate any new changes to API source code and to ensure robustness of requested changes. Assess the change impact and conduct testing accordingly
- Audit Access to Sensitive Data – all API based access to non-public data must be logged and retained for audit purposes. Logging attributes must include the source system, client identifier and associated timestamp from the target system
- Monitor and Log API Activity – track API usage and activity to identify performance bottlenecks, peak usage periods and abnormal access patterns. Use open standards-based logging frameworks such as CEF (Common Event Format) and collect logs in a central repository
- When usage limits are exceeded, by default, a 1-hour timeout (block) will be used
- X-RATELIMIT-LIMIT and X-RATELIMIT-REMAINING can be inspected in the HTTP response to view current usage
Consistent metadata and encoding ensures that APIs are interoperable across organizations and helps to maintain data consistency. The following practices should be followed when defining your API:
- Use Unicode for Encoding – Unicode Transformation Format-8 (UTF-8) is the standard encoding type for all text and textual representations of data through APIs. It must be used for all APIs published across the BC Government for both internal and external consumption
- Standardize Datetime Format – use the ISO 8601 Standard for datetime representation in all BC Government APIs. The standard date format is YYYY-MM-DD while timestamp format YYYY—MM-DD HH24:MI:SS. If other formats are required due to source system limitations, convert it to the standard format within the API
- Support Official Languages – ensure the API can return responses in both English and French. External facing APIs must reply with content in the requested language if the backend data support it. APIs must interpret the ACCEPT-LANGUAGE HTTP header and return the appropriate content. If the header is not set, then content in both languages should be returned
BC Government APIs must be published to the BC Government API Registry to be discoverable. The documentation MVP for BC Government APIs includes everything the API does, including resources, endpoints and methods, parameters, error codes, and example requests and responses:
-
Publish OpenAPI Specification – OpenAPI is a machine-readable interface specification for RESTful APIs. There are open source tools (e.g., Swagger) which can then generate human-readable documentation from this specification which avoids the need to create and maintain separate documentation
- Sample BC Government API Specifications can be found here
-
Publish code samples and test data – the most effective way to document the scope and functionality of an API is to publish the code and data examples used to validate it alongside the API contract
- Be sure to include standard and custom error response codes and interpret their specific meaning
-
Maintain concise documentation – if there is a need to extend the API documentation beyond the OpenAPI specification, this is an indication that the API is too large and/or too complex
- Be sure to document differences between versions of the API
- Include documentation on any consumption constraints such as availability, authorization and rate limiting
-
Gather Feedback – provide a clear mechanism to allow consumers to provide feedback, issue identification and enhancement requests
- The BC Government API Registry can be found here: https://catalogue.data.gov.bc.ca/group/bc-government-api-registry
- The BC Government API Github Repo can be found here: https://github.com/bcgov/api-specs
- Provide a point of contact in the API documentation such that consumers can seek assistance if required
The best way to validate your API design is to consume it with a production application within your organization. Ideally, once the data layer is built, the next step is to build the application on top of an API:
- Build once for Multiple Channels – APIs should be designed in such a way that they can be consumed by systems internal to BC Government, external agencies and the broader public. Design should accommodate for all levels of access to encourage reuse
- Consume what you Build – build your application on top of an API layer that connects to the data layer rather than creating hard dependencies. This ensures the API is production ready for consumers outside of the line of business
APIs will change over time as corresponding source systems evolve. To provide a robust and durable interface to applications, API lifecycle management must include a standard versioning scheme such that any changes to an API do not break the contract with existing consumers:
-
Use Standard Endpoints – each endpoint is a combination of the URI path (e.g. www.gov.bc.ca/finances/accounts/) and the verb (e.g. GET, PUT, POST, DELETE)
https://<base domain>/<business function>/<application name>/<plural noun>
-
API Versioning – each iteration of an API that changes the response type, data format, API functionality or breaks the contract with consumers must be versioned. Follow the
v<Major>.<Minor>.<Patch>
versioning structure whereby:- Major = Significant release that introduces incompatible API changes
- Minor = Addition of optional attributes or new functionality that is backwards compatible, but should be tested
- Patch = Internal fix which should not impact the schema and/or contract of the API
For example:
- moving from v1.1.0 to v1.1.1 would allow a simple deploy-in-place upgrade
- moving from v1.1.0 to v2.0.0 would be a major release and would require the legacy version to be kept while consumers test and migrate to the new version
-
URI vs Accept Header Versioning – both URI and Accept Header versioning are acceptable and the following guidelines are recommended:
- Using a resource specific header approach can be used to maintain a single and consistent URI for an API. This method also allows for other parameters such as caching, compression and content negotiation
- The base URI for the API should always correspond to the latest version
- Previous versions of an API can use a versioned style URI
- Accept header versioning is recommended for APIs designed exclusively for machine to machine interfaces as well as non-breaking changes (minor/patch)
e.g.
GET https://news.api.gov.bc.ca/api/Home Accept: application/json;version=1
-
Respect Existing Consumer Dependencies – support at least one previous major version (N-1) to ensure consuming systems have time to migrate to the latest version of the API
- Set and publish a version deprecation policy and timeline so consumers can plan their dependencies accordingly
- Ensure adequate testing on all minor and major releases
- Backport high value changes to the previous (N-1) version where version integrity can be maintained
- Provide a way to gather feedback from consumers to inform future development
-
API Ownership – publish and maintain a designated point of contact to the API Registry as part of the metadata record; including name, organization, email and phone (for high critically API's)
-
Define an SLO up Front – each API should have a clearly defined Service Level Objective (SLO), which should include:
- Support contact and availability
- Service uptime objective (e.g., 99%)
- Support response time (e.g., within the hour, 24 hours, best effort)
- Scheduled outages (e.g., nightly, weekly, every 2nd Sunday evening)
- Throughput limit (e.g., 100 requests per second per consumer)
- Message size limit (e.g., <1Mb per request)
-
API Publishing – all APIs should be published to the API Registry for the purposes of discovery and lifecycle management. APIs must be tagged with the appropriate metadata to indicate their desired audience (security classification) and appropriate usage patterns
- Publishing a metadata record to the BC Government API Registry helps people discover your API and promote its use
- If the API is an Open Data API, publish a terms of use, such as the example found here
API performance should be benchmarked periodically to ensure the performance and capacity meets the expectations of the SLO. This may include:
- API Load Testing – run performance tests against the API using a simulated workload to determine the response time and throughput. Performance tests should be integrated into the development lifecycle, preferably through an automated CI/CD pipeline
- Publish Performance Data – performance summaries (e.g., average response time) should be included in the metadata record for the API as well as the SLO
- Performance Monitoring – performance should be monitored and reported on routinely, particularly as part of major releases
- API Throttling – throttling mechanisms should be implemented to control throughput against the stated SLO (e.g. number of requests per second). This is typically handled by the API Gateway:
- Information on the primary BC Government API Gateway can be found here