Welcome to Göteborg&Co OpenAPI!
The destination data APIs.
Welcome to the Göteborg&Co Developer Portal. Here you'll find our open API's, documentation, a playground to test things (requires an api key) and instructions to get you started!
This guide will help you get started with the Göteborg & Co Open API, a GraphQL-based API that provides access to information about events, places, guides, and more in Gothenburg.
A Product contains one or more APIs and the terms of use. As a Developer you will subscribe to a Product (get a subscription/api key) and use the product's APIs.
An API can be part of multiple Products. Each API represents a set of operations (http verb, url and parameters).
The Göteborg & Co Open API provides:
Events data (exhibitions, concerts, festivals, etc.)
Places of interest (museums, restaurants, attractions)
City guides and recommendations
Search functionality across all content types
Taxonomy data (categories, areas, tags)
Sign up and verify
Sign up for an account and verify your email
Visit the API Portal to get started
Subscribe to the API
Once signed in, subscribe to get access to our open API
This will generate your API key
Get your API key
Find your subscription/API key under Profile -> Subscriptions
Keep this key secure and don't share it
Set up authentication
You can provide your API key in one of two ways:
As a query string parameter: `?subscription-key=your-key-here`
As a request header: `Ocp-Apim-Subscription-Key: your-key-here`
Start exploring
Browse the documentation
Try the API in the interactive playground
Start building your application!
There are three ways to interact with the API:
Official JavaScript/TypeScript Client (Recommended for JavaScript/TypeScript projects)
Official PHP Client (Recommended for PHP projects)
Direct GraphQL Queries (For those who prefer working directly with GraphQL)
The official clients are designed to make development easier and more secure. They:
Implement all security best practices out of the box
Handle authentication and request formatting automatically
Provide type safety and autocompletion
This means you can focus on building your website/application without worrying about implementing security measures - just fetch the data you need and the client handles the rest!
npm install @goteborgco/open-api-js-clientimport { GoteborgCoApi } from '@goteborgco/open-api-js-client';
const apiUrl = 'https://apim-openapi-gbgco-prod.azure-api.net/gql';
const subscriptionKey = 'your-subscription-key';
const api = new GoteborgCoApi(apiUrl, subscriptionKey);For detailed JavaScript client documentation, visit the GitHub repository.
composer require goteborgco/open-api-php-clientuse GBGCO\API;
$apiUrl = 'https://apim-openapi-gbgco-prod.azure-api.net/gql';
$subscriptionKey = 'your-subscription-key';
$api = new API($apiUrl, $subscriptionKey);
For detailed PHP client documentation, visit the GitHub repository.
If you prefer working directly with GraphQL, you can send queries to the API endpoint. Here's an example using the GraphQL client Apollo:
import { ApolloClient, InMemoryCache, gql } from '@apollo/client';
const client = new ApolloClient({
uri: 'https://apim-openapi-gbgco-prod.azure-api.net/gql',
cache: new InMemoryCache(),
headers: {
'Ocp-Apim-Subscription-Key': 'your-subscription-key',
},
});
const GET_GUIDES = gql`
query {
guides(filter: { lang: "en" }) {
guides {
id
title
excerpt
content
featuredmedia {
sizes {
full {
source_url
}
}
}
}
}
}
`;
client
.query({ query: GET_GUIDES })
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('Error fetching data:', error);
});For a complete example for consuming the API in a React/Next.js application, check out our example project on GitHub.
There is a limit on query size (in bytes) and on max-depth of the query. The limit values are subject to change but you should be aware of their existence.
Subscription Key
Your subscription key should be treated as a secret, e.g., that means you should not use a public client to query the API, i.e., do not query the API directly from a client side javascript application but rather have the client securely send requests to your own backend.
Use environment variables to store sensitive data such as secrets or API keys
Language Support
Always specify the language ('en' or 'sv')
Content is available in both English and Swedish
Pagination
Use 'per_page' and 'page' parameters for large result sets
Default is 10 items per page
Ordering
Some queries supports ordering which is great for getting the data sorted initially, however, allowing for client side sorting should be done client side rather than re-requesting the data with new parameter value for ordering
Variables & OperationName
Please use Variables and set an Operation Name, this will make our statistics better and we will be able to, over time, provide a better Service, e.g.
query MyCustomListGuides {
guides(filter: { lang: "sv" }) {
guides {
id
title
excerpt
link
}
}
}
Error Handling
Always wrap query calls in try-catch blocks to catch eventual errors and handle them. Don't expose API error responses directly to the end users.
Custom Fields
Use custom field selection to optimize response size
Only request the fields you need
To optimize performance and reduce unnecessary API calls, implementing a proper caching strategy is essential. Here are our recommendations:
The JavaScript client utilizes Apollo InMemoryCache, which provides an efficient way to cache GraphQL responses in memory. This reduces redundant requests and improves application responsiveness. By default, Apollo will cache query results automatically
If you need persistent caching beyond a single session, consider integrating localStorage or IndexedDB to store cache data.
For PHP, if you use Wordpress or Laravel we recommend using WordPress Transients or Laravel Cache to store API responses temporarily.
In a WordPress environment, the transient API allows storing API responses for a defined period, reducing load time and API calls:
$cache_key = 'gbgco_guides_cache';
$guides = get_transient($cache_key);
if (!$guides) {
try {
$api = new API($apiUrl, $subscriptionKey);
$fields = <<<GQL
guides {
id
title
excerpt
}
GQL;
$guides = $api->guides()->list(['lang' => 'sv'], $fields);
set_transient($cache_key, $guides, HOUR_IN_SECONDS);
} catch (\InvalidArgumentException $e) {
// Handle empty or invalid queries
echo "Query Error: " . $e->getMessage();
} catch (\Exception $e) {
// Handle API errors
echo "API Error: " . $e->getMessage();
}
}
In Laravel, you can use the cache facade to store API responses:
use Illuminate\Support\Facades\Cache;
use GBGCO\API;
$guides = Cache::remember('gbgco_guides', 3600, function () {
try {
$api = new API($apiUrl, $subscriptionKey);
$fields = <<<GQL
guides {
id
title
excerpt
}
GQL;
return $api->guides()->list(['lang' => 'sv'], $fields);
} catch (\InvalidArgumentException $e) {
// Handle empty or invalid queries
echo "Query Error: " . $e->getMessage();
} catch (\Exception $e) {
// Handle API errors
echo "API Error: " . $e->getMessage();
}
});
By implementing caching in your application, you improve response times, reduce API load, and create a better user experience.
The API Portal provides:
Interactive API documentation
GraphQL playground for testing queries
Check the JavaScript client documentation
Check the PHP client documentation
Explore the example Next.js project
Use the GraphQL playground in the API Portal
Contact for questions regarding the API is Louise Parra Karlander, she can be reached at api@goteborg.com
Powered by Azure API Management.