Client attribution
Billbird can automatically attribute logged hours to clients based on GitHub issue labels. This keeps the billing workflow entirely inside GitHub --- developers don't need to think about which client they're working for.
How it works
- An admin creates a client (e.g., "City of Amsterdam")
- An admin creates a label mapping that connects a GitHub label to that client (e.g., label
client:amsterdammaps to "City of Amsterdam") - When a developer logs time on an issue, Billbird checks the issue's labels
- If a label matches a mapping, the time entry is attributed to that client
The developer sees no difference in their workflow. They comment /log 2h as usual, and the entry is silently attributed.
Label mappings
A label mapping connects a GitHub label to a client record. Mappings can be:
- Repository-specific: Only applies to a specific repository
- Global: Applies to all repositories
Precedence
When both a global and repository-specific mapping exist for the same label, the repository-specific mapping takes precedence.
Multiple labels
If an issue has multiple labels that match different clients, Billbird uses the first match and includes a note in the confirmation comment about the ambiguity.
Example
Given this setup:
| Label | Client | Repository |
|---|---|---|
client:amsterdam |
City of Amsterdam | (global) |
client:amsterdam |
Amsterdam IT Dept | org/internal-tools |
client:rotterdam |
Port of Rotterdam | (global) |
Then:
/log 2hon issueorg/website#42with labelclient:amsterdamattributes to City of Amsterdam (global mapping)/log 2hon issueorg/internal-tools#10with labelclient:amsterdamattributes to Amsterdam IT Dept (repo-specific wins)/log 2hon issueorg/website#43with no client label has no client attribution
Managing clients and mappings
Clients and label mappings are managed through the admin panel or the REST API.
Admin panel
Navigate to the Clients page to create and manage clients. Navigate to Label Mappings to create and manage label-to-client mappings.
REST API
# Create a client
POST /api/v1/clients
{"name": "City of Amsterdam"}
# Create a label mapping
POST /api/v1/label-mappings
{"label_pattern": "client:amsterdam", "client_id": 1}
# Create a repo-specific mapping
POST /api/v1/label-mappings
{"label_pattern": "client:amsterdam", "client_id": 2, "repository": "org/internal-tools"}
Deactivating clients
When a client is deactivated, no new time entries will be attributed to them. Existing entries retain their attribution for historical accuracy.