Appearance
Calling the CoCoCo API
The CoCoCo API is one GraphQL endpoint on your tenant. Any language that can send an HTTPS POST with a JSON body can call it. The language guides in this section all run the same two operations, list jobs and create a job, with that language's standard HTTP client.
Get an API token
Every request carries a bearer token. You create tokens in the console:
- For an integration, use a service account. Open Service accounts, create one with a descriptive name (for example
Nightly ERP sync) and attach an IAM policy that grants only the permissions the integration needs. Then open the service account and create a token in its API Tokens section. A service account cannot sign in, and the integration keeps working when the person who set it up leaves. - For personal scripts and experiments, use a personal token. Open the user menu, then API Tokens (
/#/api-tokens). A personal token carries all of your permissions, so don't put it in a long-running deployment.
The console shows a new token only once, so copy it straight away. If you leave the expiration empty, the token stays valid until you revoke it.
The examples need these permissions: job:list to list jobs and job:write to create one.
Send a request
| Method and URL | POST https://<your-tenant-host>/graphql (the host you use to open the console) |
Authorization | Bearer <API token> |
Content-Type | application/json |
| Body | {"query": "<GraphQL document>", "variables": { ... }} |
The language guides read the host and token from two environment variables:
bash
export COCOCO_URL="https://<your-tenant-host>"
export COCOCO_TOKEN="<API token>"A quick check that the token works:
graphql
query { listJobs(first: 1) { totalCount } }bash
curl -sS "$COCOCO_URL/graphql" \
-H "Authorization: Bearer $COCOCO_TOKEN" \
-H "Content-Type: application/json" \
-d '{"query":"query { listJobs(first: 1) { totalCount } }"}'The two example operations
List jobs, one page at a time:
graphql
query ListJobs($first: Int, $after: String) {
listJobs(first: $first, after: $after) {
totalCount
pageInfo { hasNextPage endCursor }
edges { node { id name quantity status dueAt } }
}
}With the variables {"first": 2} the response looks like this:
json
{
"data": {
"listJobs": {
"totalCount": 10,
"pageInfo": { "hasNextPage": true, "endCursor": "eyJpZCI6ImpvYl8wMU0w..." },
"edges": [
{ "node": { "id": "job_01M0SYJHB7FX6BKYVZZ7EAG4Y8", "name": "Business cards", "quantity": 5000, "status": "CONFIRMED", "dueAt": null } },
{ "node": { "id": "job_01M0R249JMETNBM1Z7466MXGZD", "name": "Flyer A5", "quantity": 1, "status": "DRAFT", "dueAt": null } }
]
}
}
}Create a job:
graphql
mutation CreateJob($input: CreateJobInput!) {
createJob(input: $input) {
job { id name status }
errors { path message }
}
}with variables such as:
json
{ "input": { "name": "Business cards", "quantity": 500, "externalId": "ERP-10042" } }name and quantity are required. externalId is optional and must be unique in your tenant, so it is a good place for the ID the job has in your own system. See CreateJobInput for the other fields.
Conventions to handle in your code
- Lists are connections. A list query returns
edges { node },pageInfoandtotalCount. Ask for at most 100 items withfirst(the default is 25). To get the next page, passpageInfo.endCursorasafter. Stop whenhasNextPageisfalse. - IDs are typed, prefixed strings such as
job_01M0SYJHB7FX6BKYVZZ7EAG4Y8. In a GraphQL document they have their own scalar types (JobID!,CustomerID, …); in JSON variables you send them as plain strings. - Mutations report validation problems in the payload.
createJobreturns the createdjoband a list oferrors, each with apathand amessage. An emptyerrorslist means the change was saved. - Everything else comes back as top-level
errors. A missing or invalid token (Authentication required), a missing permission (Access denied: not authorized to perform '<action>' on '<resource>') and an invalid document all appear in theerrorsarray next todata, and the HTTP status is still200. Check that array on every response. A400status means the request itself was rejected, for example because the body had noquery.
These guides cover queries and mutations over HTTP. Subscriptions are not covered here.
Explore the schema
- The schema reference on this site lists every query, mutation and type.
- In the console, the GraphQL playground (
/#/graphql-playground) runs queries with your own session, and/#/docshas the in-app API guides. GET https://<your-tenant-host>/graphql/schemareturns the schema as SDL, which code generators can read.