Get started
This page takes you from nothing to a working, authenticated API call. It uses
the cuttle CLI to create the credentials and curl to make the call, so you
can follow it without writing any code first.
What you need
- an active project, and permission to create service accounts and role bindings in it — the Owner role is enough
- the cuttle CLI, installed and authenticated
- your project ID and the region your project uses, both visible in the dashboard
Set these once so the commands below can be pasted as-is:
PROJECT=your-project
REGION=us-west2
Create an identity for your automation
Automation authenticates as a service account, not as you. Your own login is tied to a human who may change roles or leave; a service account belongs to the project and can be granted exactly the access its job requires.
Service accounts are regional, so they need a region as well as a project.
cuttle iam create service-account automation \
--project $PROJECT --region $REGION
The service account gets an email-style identifier derived from its name, and you will need it in a moment:
automation@your-project.us-west2.serviceaccounts.iam.edgelq.com
Create an API key
A service account is an identity; a key is how you prove you are it. For
scripting, ask for the API_KEY algorithm, which produces a single bearer
token instead of a keypair.
cuttle iam create service-account-key api-key \
--parent projects/$PROJECT/regions/$REGION/serviceAccounts/automation \
--algorithm API_KEY \
-o json
Look for apiKey in the response and store it somewhere safe.
The platform does not retain the secret half of a key. The create response is the only copy you will ever receive. If it is lost, delete the key and create a replacement. See Authentication for how to hold it safely in CI and in long-running services.
Grant it access
A brand-new service account can authenticate but do nothing. Bind a role to it to say what it may do, and where.
Start with read-only. viewer grants read access across the core services,
which is all this walkthrough needs and a good default for a first
integration — you can widen it later once you know which writes you actually
make.
cuttle iam create role-binding automation-viewer \
--parent projects/$PROJECT \
--member "serviceAccount:automation@$PROJECT.$REGION.serviceaccounts.iam.edgelq.com" \
--role "services/iam.edgelq.com/roles/viewer"
To let the automation create and modify resources instead, bind
services/iam.edgelq.com/roles/admin-operator for full access to the core
services, or a narrower operator role. See Roles for what each one
grants, and prefer the narrowest role that works.
Access is applied by a platform controller, not at the moment the
binding is written, so a brand-new binding can take a minute or two to take
effect. A PERMISSION_DENIED immediately after granting access usually means
“not yet”, not “wrong”.
Make your first call
Each service answers on its own host, under the shape
{service}.apis.edgelq.com. Read your project back from IAM:
export API_KEY=<the apiKey value from above>
curl -s -H "Authorization: Bearer $API_KEY" \
"https://iam.apis.edgelq.com/v1/projects/$PROJECT"
Authentication is a single header — Authorization: Bearer $API_KEY — for
every service and every call.
Now read something regional. Devices live under a project and a region, so the path carries both:
curl -s -H "Authorization: Bearer $API_KEY" \
"https://devices.apis.edgelq.com/v1/projects/$PROJECT/regions/$REGION/devices"
And narrow it with a filter, URL-encoded:
curl -s -H "Authorization: Bearer $API_KEY" \
--data-urlencode 'filter=status.connectionStatus="CONNECTED"' \
--get \
"https://devices.apis.edgelq.com/v1/projects/$PROJECT/regions/$REGION/devices"
That is the whole authentication story. What remains is learning to address resources you have not seen before, and to ask for exactly the data you want — which is what the rest of this section covers.
Writing your first code
For anything longer-lived than a script, use gRPC rather than REST. The
quickest route is the Go client in edgelq-sdk; for other languages,
generate a client from the .proto files the SDK ships.
Whichever you choose, the credential handling is the same, and Authentication covers the service-account key file that gRPC clients normally use in place of a bearer token.
Troubleshooting
| Response | Usual cause |
|---|---|
401 / UNAUTHENTICATED | Missing or malformed Authorization header, or a key that has been deleted. |
403 / PERMISSION_DENIED | No role binding covers this call yet, or the binding has not settled. Check the role and the scope you bound it in. |
404 / NOT_FOUND | Usually a name problem, not a missing resource — most often a missing regions/{region} segment. See Resource names. |
429 / RESOURCE_EXHAUSTED | A project limit is reached. See Errors and limits. |
Next steps
- Authentication — key types, rotation, and where to keep credentials.
- Resource names — how to construct a name for any resource.
- Reading resources — filters, field masks, and pagination.