Documentation
¶
Overview ¶
Package freeagent is a client for the FreeAgent v2 API.
See https://dev.freeagent.com for the upstream reference. Resource types mirror the documented payloads; cross-references are carried as ResourceURL, and monetary values as Decimal, never float64.
Example (NewClient) ¶
Build a client backed by a file-stored token that refreshes itself. This is the shape the README documents; keeping it here means it cannot drift.
package main
import (
"context"
"fmt"
"log"
"net/http"
"os"
"github.com/alekc/freeagent-sdk/freeagent"
)
func main() {
ctx := context.Background()
path, err := freeagent.DefaultTokenPath()
if err != nil {
log.Fatal(err)
}
store, err := freeagent.NewFileStore(path, freeagent.Sandbox.Name)
if err != nil {
log.Fatal(err)
}
config := freeagent.Sandbox.OAuthConfig(
os.Getenv("FREEAGENT_CLIENT_ID"),
os.Getenv("FREEAGENT_CLIENT_SECRET"),
"http://localhost:8723/callback",
)
source, err := freeagent.NewTokenSource(ctx, config, store)
if err != nil {
log.Fatal(err)
}
client, err := freeagent.NewClient(
freeagent.WithBaseURL(freeagent.Sandbox.BaseURL),
freeagent.WithTokenSource(source),
freeagent.WithUserAgent("my-app/1.0"),
)
if err != nil {
log.Fatal(err)
}
body, _, err := client.Raw(ctx, http.MethodGet, "company", nil, nil)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(body))
}
Output:
Index ¶
- Constants
- Variables
- func DefaultTokenPath() (string, error)
- func ExpiresIn(t *oauth2.Token, now time.Time) string
- func ResourceNames() []string
- type APIError
- type AccountingPeriod
- type Attachment
- type AttachmentService
- func (s *AttachmentService) Delete(ctx context.Context, id int64) (*Response, error)
- func (s *AttachmentService) Get(ctx context.Context, id int64) (*Attachment, *Response, error)
- func (s *AttachmentService) GetURL(ctx context.Context, ref ResourceURL) (*Attachment, *Response, error)
- func (s *AttachmentService) Meta() ResourceMeta
- type BalanceSheet
- type BalanceSheetAccount
- type BalanceSheetCapitalAssets
- type BalanceSheetEquity
- type BalanceSheetSection
- type BankAccount
- type BankAccountService
- type BankFeed
- type BankFeedService
- type BankTransaction
- type BankTransactionExplanation
- type BankTransactionExplanationService
- func (s *BankTransactionExplanationService) All(context.Context, *ListOptions) iter.Seq2[BankTransactionExplanation, error]
- func (s *BankTransactionExplanationService) AllForAccount(ctx context.Context, account ResourceURL, opts *ListOptions) iter.Seq2[BankTransactionExplanation, error]
- func (s *BankTransactionExplanationService) List(context.Context, *ListOptions) ([]BankTransactionExplanation, *Response, error)
- func (s *BankTransactionExplanationService) ListForAccount(ctx context.Context, account ResourceURL, opts *ListOptions) ([]BankTransactionExplanation, *Response, error)
- type BankTransactionService
- func (s *BankTransactionService) All(context.Context, *ListOptions) iter.Seq2[BankTransaction, error]
- func (s *BankTransactionService) AllForAccount(ctx context.Context, account ResourceURL, opts *ListOptions) iter.Seq2[BankTransaction, error]
- func (s *BankTransactionService) List(context.Context, *ListOptions) ([]BankTransaction, *Response, error)
- func (s *BankTransactionService) ListForAccount(ctx context.Context, account ResourceURL, opts *ListOptions) ([]BankTransaction, *Response, error)
- func (s *BankTransactionService) UploadStatement(ctx context.Context, account ResourceURL, lines []StatementLine) (*Response, error)
- type Bill
- type BillItem
- type BillService
- type CISBand
- type CISBandService
- type CapitalAsset
- type CapitalAssetHistoryEntry
- type CapitalAssetService
- type CapitalAssetType
- type CapitalAssetTypeService
- type Cashflow
- type CashflowMonth
- type CashflowSection
- type Category
- type CategoryGroups
- type CategoryService
- func (s *CategoryService) Create(ctx context.Context, in *Category) (*Category, *Response, error)
- func (s *CategoryService) Delete(ctx context.Context, nominalCode string) (*Response, error)
- func (s *CategoryService) Get(ctx context.Context, nominalCode string) (*Category, *Response, error)
- func (s *CategoryService) List(ctx context.Context, subAccounts bool) (*CategoryGroups, *Response, error)
- func (s *CategoryService) Meta() ResourceMeta
- func (s *CategoryService) Update(ctx context.Context, nominalCode string, in *Category) (*Category, *Response, error)
- type Client
- type Collection
- type Company
- type CompanyService
- type Contact
- type ContactService
- type CorporationTaxReturn
- type CorporationTaxReturnService
- func (s *CorporationTaxReturnService) Get(ctx context.Context, periodEndsOn Date) (*CorporationTaxReturn, *Response, error)
- func (s *CorporationTaxReturnService) List(ctx context.Context) ([]CorporationTaxReturn, *Response, error)
- func (s *CorporationTaxReturnService) MarkAsFiled(ctx context.Context, periodEndsOn Date) (*CorporationTaxReturn, *Response, error)
- func (s *CorporationTaxReturnService) MarkAsPaid(ctx context.Context, periodEndsOn Date) (*CorporationTaxReturn, *Response, error)
- func (s *CorporationTaxReturnService) MarkAsUnfiled(ctx context.Context, periodEndsOn Date) (*CorporationTaxReturn, *Response, error)
- func (s *CorporationTaxReturnService) MarkAsUnpaid(ctx context.Context, periodEndsOn Date) (*CorporationTaxReturn, *Response, error)
- func (s *CorporationTaxReturnService) Meta() ResourceMeta
- type CreditNote
- type CreditNoteItem
- type CreditNoteReconciliation
- type CreditNoteReconciliationService
- type CreditNoteService
- func (s *CreditNoteService) MarkAsDraft(ctx context.Context, id int64) (*CreditNote, *Response, error)
- func (s *CreditNoteService) MarkAsSent(ctx context.Context, id int64) (*CreditNote, *Response, error)
- func (s *CreditNoteService) PDF(ctx context.Context, id int64) (*PDF, *Response, error)
- func (s *CreditNoteService) SendEmail(ctx context.Context, id int64, opts *EmailOptions) (*Response, error)
- type Date
- type Decimal
- type DepreciationProfile
- type ECMossRate
- type ECMossRates
- type EmailAddressService
- type EmailOptions
- type Environment
- type Estimate
- type EstimateItem
- type EstimateService
- func (s *EstimateService) ConvertToInvoice(ctx context.Context, id int64) (*Estimate, *Response, error)
- func (s *EstimateService) Duplicate(ctx context.Context, id int64) (*Estimate, *Response, error)
- func (s *EstimateService) MarkAsApproved(ctx context.Context, id int64) (*Estimate, *Response, error)
- func (s *EstimateService) MarkAsDraft(ctx context.Context, id int64) (*Estimate, *Response, error)
- func (s *EstimateService) MarkAsRejected(ctx context.Context, id int64) (*Estimate, *Response, error)
- func (s *EstimateService) MarkAsSent(ctx context.Context, id int64) (*Estimate, *Response, error)
- func (s *EstimateService) PDF(ctx context.Context, id int64) (*PDF, *Response, error)
- func (s *EstimateService) SendEmail(ctx context.Context, id int64, opts *EmailOptions) (*Response, error)
- type Expense
- type ExpenseService
- type FieldError
- type FileStore
- type FilingPayment
- type FinalAccountsReport
- type FinalAccountsReportService
- func (s *FinalAccountsReportService) Get(ctx context.Context, periodEndsOn Date) (*FinalAccountsReport, *Response, error)
- func (s *FinalAccountsReportService) List(ctx context.Context) ([]FinalAccountsReport, *Response, error)
- func (s *FinalAccountsReportService) MarkAsFiled(ctx context.Context, periodEndsOn Date) (*FinalAccountsReport, *Response, error)
- func (s *FinalAccountsReportService) MarkAsUnfiled(ctx context.Context, periodEndsOn Date) (*FinalAccountsReport, *Response, error)
- func (s *FinalAccountsReportService) Meta() ResourceMeta
- type HirePurchase
- type HirePurchaseService
- type IncomeTaxReturn
- type IncomeTaxReturnService
- func (s *IncomeTaxReturnService) GetForUser(ctx context.Context, user ResourceURL, periodEndsOn Date) (*IncomeTaxReturn, *Response, error)
- func (s *IncomeTaxReturnService) ListForUser(ctx context.Context, user ResourceURL) ([]IncomeTaxReturn, *Response, error)
- func (s *IncomeTaxReturnService) MarkAsFiled(ctx context.Context, user ResourceURL, periodEndsOn Date) (*IncomeTaxReturn, *Response, error)
- func (s *IncomeTaxReturnService) MarkAsUnfiled(ctx context.Context, user ResourceURL, periodEndsOn Date) (*IncomeTaxReturn, *Response, error)
- func (s *IncomeTaxReturnService) MarkPaymentAsPaid(ctx context.Context, user ResourceURL, periodEndsOn, paymentDate Date) (*IncomeTaxReturn, *Response, error)
- func (s *IncomeTaxReturnService) MarkPaymentAsUnpaid(ctx context.Context, user ResourceURL, periodEndsOn, paymentDate Date) (*IncomeTaxReturn, *Response, error)
- func (s *IncomeTaxReturnService) Meta() ResourceMeta
- type Int64
- type Invoice
- type InvoiceItem
- type InvoicePaymentMethods
- type InvoiceService
- func (s *InvoiceService) ConvertToCreditNote(ctx context.Context, id int64) (*Invoice, *Response, error)
- func (s *InvoiceService) Duplicate(ctx context.Context, id int64) (*Invoice, *Response, error)
- func (s *InvoiceService) MarkAsCancelled(ctx context.Context, id int64) (*Invoice, *Response, error)
- func (s *InvoiceService) MarkAsDraft(ctx context.Context, id int64) (*Invoice, *Response, error)
- func (s *InvoiceService) MarkAsScheduled(ctx context.Context, id int64) (*Invoice, *Response, error)
- func (s *InvoiceService) MarkAsSent(ctx context.Context, id int64) (*Invoice, *Response, error)
- func (s *InvoiceService) PDF(ctx context.Context, id int64) (*PDF, *Response, error)
- func (s *InvoiceService) SendEmail(ctx context.Context, id int64, opts *EmailOptions) (*Response, error)
- type JournalEntry
- type JournalSet
- type JournalSetBalance
- type JournalSetService
- type ListOptions
- type MemoryStore
- type MileagePeriod
- type MileageRate
- type MileageSettings
- type Note
- type NoteService
- func (s *NoteService) All(context.Context, *ListOptions) iter.Seq2[Note, error]
- func (s *NoteService) AllForParent(ctx context.Context, parent ResourceURL, opts *ListOptions) iter.Seq2[Note, error]
- func (s *NoteService) Create(context.Context, *Note) (*Note, *Response, error)
- func (s *NoteService) CreateForParent(ctx context.Context, parent ResourceURL, in *Note) (*Note, *Response, error)
- func (s *NoteService) List(context.Context, *ListOptions) ([]Note, *Response, error)
- func (s *NoteService) ListForParent(ctx context.Context, parent ResourceURL, opts *ListOptions) ([]Note, *Response, error)
- type Option
- func WithAPIVersion(v string) Option
- func WithBaseURL(raw string) Option
- func WithHTTPClient(h *http.Client) Option
- func WithMaxResponseBytes(n int64) Option
- func WithRateLimitTest(on bool) Option
- func WithRateLimits(perMinute, perHour int) Option
- func WithReadOnly() Option
- func WithRetryPolicy(p RetryPolicy) Option
- func WithSandbox() Option
- func WithTokenSource(ts oauth2.TokenSource) Option
- func WithUserAgent(ua string) Option
- func WithoutAuth() Option
- func WithoutRateLimit() Option
- func WithoutRetry() Option
- type PDF
- type PayrollPeriod
- type PayrollProfile
- type PayrollProfileService
- type PayrollService
- func (s *PayrollService) MarkPaymentAsPaid(ctx context.Context, year int, paymentDate Date) (*Response, error)
- func (s *PayrollService) MarkPaymentAsUnpaid(ctx context.Context, year int, paymentDate Date) (*Response, error)
- func (s *PayrollService) Meta() ResourceMeta
- func (s *PayrollService) Payslips(ctx context.Context, year, period int) ([]Payslip, *Response, error)
- func (s *PayrollService) Period(ctx context.Context, year, period int) (*PayrollPeriod, *Response, error)
- func (s *PayrollService) Year(ctx context.Context, year int) (*PayrollYear, *Response, error)
- type PayrollYear
- type Payslip
- type PriceListItem
- type PriceListItemService
- type ProfitAndLoss
- type ProfitAndLossRow
- type Project
- type ProjectService
- type Property
- type PropertyService
- type RateLimit
- type ReadCollection
- func (c *ReadCollection[T]) All(ctx context.Context, opts *ListOptions) iter.Seq2[T, error]
- func (c *ReadCollection[T]) Get(ctx context.Context, id int64) (*T, *Response, error)
- func (c *ReadCollection[T]) GetURL(ctx context.Context, ref ResourceURL) (*T, *Response, error)
- func (c *ReadCollection[T]) List(ctx context.Context, opts *ListOptions) ([]T, *Response, error)
- func (c *ReadCollection[T]) Meta() ResourceMeta
- type Reader
- type RecurringInvoice
- type RecurringInvoiceService
- type ReportOptions
- type ReportService
- func (s *ReportService) BalanceSheet(ctx context.Context, opts *ReportOptions) (*BalanceSheet, *Response, error)
- func (s *ReportService) Cashflow(ctx context.Context, from, to Date) (*Cashflow, *Response, error)
- func (s *ReportService) ProfitAndLoss(ctx context.Context, opts *ReportOptions) (*ProfitAndLoss, *Response, error)
- func (s *ReportService) TrialBalance(ctx context.Context, opts *ReportOptions) ([]TrialBalanceEntry, *Response, error)
- type ResourceMeta
- type ResourceURL
- type Response
- type RetryPolicy
- type SalesTaxPeriod
- type SalesTaxPeriodService
- type SalesTaxService
- type StatementLine
- type StockItem
- type StockItemService
- type Task
- type TaskService
- type TaxTimelineItem
- type Time
- type Timeslip
- type TimeslipService
- type TimeslipTimer
- type TokenSource
- type TokenStore
- type Transaction
- type TransactionForeignCurrency
- type TransactionService
- type TrialBalanceEntry
- type User
- type UserPayrollProfile
- type UserService
- type VATBreakdown
- type VATBreakdownRow
- type VATReturn
- type VATReturnService
- func (s *VATReturnService) Get(ctx context.Context, periodEndsOn Date) (*VATReturn, *Response, error)
- func (s *VATReturnService) List(ctx context.Context) ([]VATReturn, *Response, error)
- func (s *VATReturnService) MarkAsFiled(ctx context.Context, periodEndsOn Date) (*VATReturn, *Response, error)
- func (s *VATReturnService) MarkAsUnfiled(ctx context.Context, periodEndsOn Date) (*VATReturn, *Response, error)
- func (s *VATReturnService) MarkPaymentAsPaid(ctx context.Context, periodEndsOn, paymentDate Date) (*VATReturn, *Response, error)
- func (s *VATReturnService) MarkPaymentAsUnpaid(ctx context.Context, periodEndsOn, paymentDate Date) (*VATReturn, *Response, error)
- func (s *VATReturnService) Meta() ResourceMeta
Examples ¶
Constants ¶
const ( BankAccountTypeStandard = "StandardBankAccount" BankAccountTypeCreditCard = "CreditCardAccount" BankAccountTypeEcommerce = "EcommerceAccount" BankAccountTypeRentalStatement = "RentalStatementAccount" BankAccountTypeAmazonSeller = "AmazonSellerBankAccount" BankAccountTypeGoCardless = "GocardlessBankAccount" BankAccountTypePaypalClassic = "PaypalClassicAccount" BankAccountTypePaypalCurrency = "Paypal::CurrencyAccount" BankAccountTypeStripe = "StripeBankAccount" )
Bank account type values accepted by BankAccount.Type.
const ( BankAccountViewStandard = "standard_bank_accounts" //nolint:gosec // G101 false positive: this is a query filter, not a credential BankAccountViewCreditCard = "credit_card_accounts" BankAccountViewPaypal = "paypal_accounts" )
Views accepted by the bank accounts list endpoint.
const ( BankFeedTypeAPI = "api" BankFeedTypeOpenBanking = "open_banking" )
Feed types returned by BankFeed.FeedType.
const ( CISBandGross = "cis_gross" CISBandStandard = "cis_standard" CISBandHigher = "cis_higher" )
CIS band names.
const ( BillViewAll = "all" BillViewOpen = "open" BillViewOverdue = "overdue" BillViewOpenOrOverdue = "open_or_overdue" BillViewOpenOrOverduePayments = "open_or_overdue_payments" BillViewOpenOrOverdueRefunds = "open_or_overdue_refunds" BillViewPaid = "paid" BillViewRecurring = "recurring" BillViewHirePurchase = "hire_purchase" BillViewCIS = "cis" )
Views accepted by the bills list endpoint.
const ( DepreciationStraightLine = "straight_line" DepreciationReducingBalance = "reducing_balance" DepreciationNone = "no_depreciation" DepreciationFrequencyMonthly = "monthly" DepreciationFrequencyAnnual = "annually" )
Depreciation methods accepted by DepreciationProfile.
const ( CapitalAssetViewAll = "all" CapitalAssetViewDisposed = "disposed" CapitalAssetViewDisposable = "disposable" )
Views accepted by the capital assets list endpoint.
const ( CategoryGroupAdminExpenses = "admin_expenses_categories" CategoryGroupCostOfSales = "cost_of_sales_categories" CategoryGroupIncome = "income_categories" CategoryGroupGeneral = "general_categories" )
The four envelope keys the categories endpoint groups results under.
const ( DefaultBaseURL = "https://api.freeagent.com/v2/" SandboxBaseURL = "https://api.sandbox.freeagent.com/v2/" )
Endpoints. Both carry the /v2/ prefix and a trailing slash so relative resource paths resolve against them.
const ( ContactViewAll = "all" ContactViewActive = "active" ContactViewClients = "clients" ContactViewSuppliers = "suppliers" ContactViewActiveProjects = "active_projects" ContactViewCompletedProjects = "completed_projects" ContactViewOpenClients = "open_clients" ContactViewOpenSuppliers = "open_suppliers" ContactViewHidden = "hidden" )
Views accepted by the contacts list endpoint.
const ( CreditNoteViewAll = "all" //nolint:gosec // G101 false positive: this is a query filter, not a credential CreditNoteViewRecentOpenOverdue = "recent_open_or_overdue" CreditNoteViewOpen = "open" CreditNoteViewOverdue = "overdue" CreditNoteViewOpenOrOverdue = "open_or_overdue" CreditNoteViewDraft = "draft" CreditNoteViewRefunded = "refunded" )
Views accepted by the credit notes list endpoint.
const ( EstimateViewAll = "all" EstimateViewRecent = "recent" EstimateViewDraft = "draft" EstimateViewNonDraft = "non_draft" EstimateViewSent = "sent" EstimateViewApproved = "approved" EstimateViewRejected = "rejected" EstimateViewInvoiced = "invoiced" )
Views accepted by the estimates list endpoint.
const ( ExpenseViewRecent = "recent" ExpenseViewRecurring = "recurring" )
Views accepted by the expenses list endpoint.
const ( FilingStatusDraft = "draft" FilingStatusUnfiled = "unfiled" FilingStatusPending = "pending" FilingStatusRejected = "rejected" FilingStatusFiled = "filed" FilingStatusMarkedAsFiled = "marked_as_filed" )
Filing statuses a FinalAccountsReport can hold.
const ( InvoiceViewAll = "all" InvoiceViewRecentOpenOverdue = "recent_open_or_overdue" InvoiceViewOpen = "open" InvoiceViewOverdue = "overdue" InvoiceViewOpenOrOverdue = "open_or_overdue" InvoiceViewDraft = "draft" InvoiceViewPaid = "paid" InvoiceViewScheduledToEmail = "scheduled_to_email" InvoiceViewThankYouEmails = "thank_you_emails" InvoiceViewReminderEmails = "reminder_emails" )
Views accepted by the invoices list endpoint. LastNMonths is a template: substitute the month count, for example "last_3_months".
const ( PaymentStatusUnpaid = "unpaid" PaymentStatusMarkedAsPaid = "marked_as_paid" )
Payment statuses used across the filing families.
const ( ProjectViewActive = "active" ProjectViewCompleted = "completed" ProjectViewCancelled = "cancelled" ProjectViewHidden = "hidden" )
Views accepted by the projects list endpoint.
const ( DefaultRequestsPerMinute = 100 DefaultRequestsPerHour = 3400 )
FreeAgent enforces 120 requests per minute and 3600 per hour per end user. The defaults below sit under both: the token buckets refill continuously while the API counters reset on fixed boundaries, so burst plus refill must still fit inside a single window.
const ( VATStatusOutOfScope = "out_of_scope" VATStatusReduced = "reduced" VATStatusStandard = "standard" VATStatusZero = "zero" )
VAT statuses accepted by PriceListItem.VATStatus.
const ( TaskViewAll = "all" TaskViewActive = "active" TaskViewCompleted = "completed" TaskViewHidden = "hidden" )
Views accepted by the tasks list endpoint.
const ( TimeslipViewAll = "all" TimeslipViewUnbilled = "unbilled" TimeslipViewRunning = "running" )
Views accepted by the timeslips list endpoint.
const ( RecurringInvoiceViewDraft = "draft" RecurringInvoiceViewActive = "active" RecurringInvoiceViewInactive = "inactive" )
Views accepted by the recurring invoices list endpoint.
const ( DateLayout = "2006-01-02" TimestampLayout = "2006-01-02T15:04:05.000Z07:00" )
Layouts used on the wire. FreeAgent documents dates as YYYY-MM-DD and timestamps as ISO 8601 with milliseconds, which is what updated_since filters expect to receive back.
const ( UserViewAll = "all" UserViewStaff = "staff" UserViewActiveStaff = "active_staff" UserViewAdvisors = "advisors" UserViewActiveAdvisors = "active_advisors" )
Views accepted by the users list endpoint.
const DefaultAPIVersion = "2026-08-16"
DefaultAPIVersion pins the X-Api-Version header. Sending no header opts into pre-versioning behaviour, which drifts from the documentation this library was modelled on, so a date is always sent. Bump it only alongside the model changes the new version implies.
const DefaultMaxResponseBytes = 32 << 20
DefaultMaxResponseBytes bounds a single response body. Legitimate pages of 100 records are far smaller; the cap exists so a broken or hostile upstream cannot exhaust memory.
const MaxAttachmentBytes = 5 << 20
MaxAttachmentBytes is the upload limit FreeAgent documents for the attachment field on bills, expenses and bank transaction explanations.
const MaxPerPage = 100
MaxPerPage is the largest page size FreeAgent accepts.
const Version = "0.1.0-dev"
Version is the library version reported in the default user agent.
Variables ¶
var ( Production = Environment{ Name: "production", BaseURL: DefaultBaseURL, AuthorizeURL: "https://api.freeagent.com/v2/approve_app", TokenURL: "https://api.freeagent.com/v2/token_endpoint", } Sandbox = Environment{ Name: "sandbox", BaseURL: SandboxBaseURL, AuthorizeURL: "https://api.sandbox.freeagent.com/v2/approve_app", TokenURL: "https://api.sandbox.freeagent.com/v2/token_endpoint", } )
The two deployments FreeAgent operates.
var ( ErrForbidden = errors.New("freeagent: forbidden") ErrNotFound = errors.New("freeagent: not found") ErrValidation = errors.New("freeagent: validation failed") ErrRateLimited = errors.New("freeagent: rate limited") ErrServer = errors.New("freeagent: server error") )
Sentinels for errors.Is. They classify by HTTP status so callers can branch without importing net/http or matching on message text.
var DefaultRetryPolicy = RetryPolicy{ MaxAttempts: 3, BaseDelay: 500 * time.Millisecond, MaxDelay: 30 * time.Second, MaxRetryAfter: 2 * time.Minute, }
DefaultRetryPolicy is applied unless overridden.
var DefaultUserAgent = "freeagent-sdk-go/" + Version + " (+https://github.com/alekc/freeagent-sdk)"
DefaultUserAgent identifies the library. FreeAgent asks integrations to send something identifying, and callers should append their own name via WithUserAgent.
var ErrNoToken = errors.New("freeagent: no stored token")
ErrNoToken is returned by a TokenStore that holds no token yet. It is the signal for tooling to run the authorisation flow.
var ErrNoTokenSource = errors.New("freeagent: no token source configured, pass WithTokenSource or WithoutAuth")
ErrNoTokenSource is returned by NewClient when neither WithTokenSource nor WithoutAuth was supplied. Every FreeAgent endpoint requires a bearer token, so an unauthenticated client is a configuration mistake worth catching at construction rather than on the first 401.
var ErrNotAMember = errors.New("freeagent: resource URL does not address a collection member")
ErrNotAMember is returned by ResourceURL.ID for URLs that do not address a single member of a collection, such as the /v2/company singleton.
var ErrReadOnly = errors.New("freeagent: client is read-only")
ErrReadOnly is returned instead of sending a mutating request on a client built WithReadOnly.
var Resources = map[string]ResourceMeta{ "attachments": { Name: "attachments", Path: "attachments", Singular: "attachment", NoList: true, Doc: "https://dev.freeagent.com/docs/attachments", }, "balance_sheet": { Name: "balance_sheet", Path: "accounting/balance_sheet", Singleton: true, ReadOnly: true, Doc: "https://dev.freeagent.com/docs/balance_sheet", }, "bank_accounts": { Name: "bank_accounts", Path: "bank_accounts", Singular: "bank_account", Plural: "bank_accounts", Doc: "https://dev.freeagent.com/docs/bank_accounts", }, "bank_transaction_explanations": { Name: "bank_transaction_explanations", Path: "bank_transaction_explanations", Singular: "bank_transaction_explanation", Plural: "bank_transaction_explanations", RequiresBankAccount: true, Doc: "https://dev.freeagent.com/docs/bank_transaction_explanations", }, "bank_transactions": { Name: "bank_transactions", Path: "bank_transactions", Singular: "bank_transaction", Plural: "bank_transactions", ReadOnly: true, RequiresBankAccount: true, Doc: "https://dev.freeagent.com/docs/bank_transactions", }, "bank_feeds": { Name: "bank_feeds", Path: "bank_feeds", Singular: "bank_feed", Plural: "bank_feeds", ReadOnly: true, Doc: "https://dev.freeagent.com/docs/bank_feeds", }, "bills": { Name: "bills", Path: "bills", Singular: "bill", Plural: "bills", Doc: "https://dev.freeagent.com/docs/bills", }, "categories": { Name: "categories", Path: "categories", Singular: "category", Grouped: true, Doc: "https://dev.freeagent.com/docs/categories", }, "capital_asset_types": { Name: "capital_asset_types", Path: "capital_asset_types", Singular: "capital_asset_type", Plural: "capital_asset_types", Doc: "https://dev.freeagent.com/docs/capital_asset_types", }, "capital_assets": { Name: "capital_assets", Path: "capital_assets", Singular: "capital_asset", Plural: "capital_assets", ReadOnly: true, Doc: "https://dev.freeagent.com/docs/capital_assets", }, "cashflow": { Name: "cashflow", Path: "cashflow", Singular: "cashflow", Singleton: true, ReadOnly: true, Doc: "https://dev.freeagent.com/docs/cashflow", }, "cis_bands": { Name: "cis_bands", Path: "cis_bands", Singleton: true, ReadOnly: true, CustomEnvelope: true, Doc: "https://dev.freeagent.com/docs/cis_bands", }, "company": { Name: "company", Path: "company", Singular: "company", Singleton: true, ReadOnly: true, Doc: "https://dev.freeagent.com/docs/company", }, "credit_note_reconciliations": { Name: "credit_note_reconciliations", Path: "credit_note_reconciliations", Singular: "credit_note_reconciliation", Plural: "credit_note_reconciliations", Doc: "https://dev.freeagent.com/docs/credit_note_reconciliations", }, "credit_notes": { Name: "credit_notes", Path: "credit_notes", Singular: "credit_note", Plural: "credit_notes", Doc: "https://dev.freeagent.com/docs/credit_notes", }, "contacts": { Name: "contacts", Path: "contacts", Singular: "contact", Plural: "contacts", Doc: "https://dev.freeagent.com/docs/contacts", }, "corporation_tax_returns": { Name: "corporation_tax_returns", Path: "corporation_tax_returns", Singular: "corporation_tax_return", Plural: "corporation_tax_returns", Doc: "https://dev.freeagent.com/docs/corporation_tax_returns", }, "email_addresses": { Name: "email_addresses", Path: "email_addresses", Plural: "email_addresses", Singleton: true, ReadOnly: true, Doc: "https://dev.freeagent.com/docs/email_addresses", }, "estimates": { Name: "estimates", Path: "estimates", Singular: "estimate", Plural: "estimates", Doc: "https://dev.freeagent.com/docs/estimates", }, "expenses": { Name: "expenses", Path: "expenses", Singular: "expense", Plural: "expenses", Doc: "https://dev.freeagent.com/docs/expenses", }, "final_accounts_reports": { Name: "final_accounts_reports", Path: "final_accounts_reports", Singular: "final_accounts_report", Plural: "final_accounts_reports", Doc: "https://dev.freeagent.com/docs/final_accounts_reports", }, "hire_purchases": { Name: "hire_purchases", Path: "hire_purchases", Singular: "hire_purchase", Plural: "hire_purchases", ReadOnly: true, Doc: "https://dev.freeagent.com/docs/hire_purchases", }, "income_tax_returns": { Name: "income_tax_returns", Path: "self_assessment_returns", Singular: "self_assessment_return", Plural: "self_assessment_returns", Doc: "https://dev.freeagent.com/docs/income_tax_returns", }, "invoices": { Name: "invoices", Path: "invoices", Singular: "invoice", Plural: "invoices", Doc: "https://dev.freeagent.com/docs/invoices", }, "journal_sets": { Name: "journal_sets", Path: "journal_sets", Singular: "journal_set", Plural: "journal_sets", Doc: "https://dev.freeagent.com/docs/journal_sets", }, "notes": { Name: "notes", Path: "notes", Singular: "note", Plural: "notes", Doc: "https://dev.freeagent.com/docs/notes", }, "payroll": { Name: "payroll", Path: "payroll", ReadOnly: true, CustomEnvelope: true, Doc: "https://dev.freeagent.com/docs/payroll", }, "payroll_profiles": { Name: "payroll_profiles", Path: "payroll_profiles", ReadOnly: true, CustomEnvelope: true, Doc: "https://dev.freeagent.com/docs/payroll_profiles", }, "price_list_items": { Name: "price_list_items", Path: "price_list_items", Singular: "price_list_item", Plural: "price_list_items", Doc: "https://dev.freeagent.com/docs/price_list_items", }, "profit_and_loss": { Name: "profit_and_loss", Path: "accounting/profit_and_loss/summary", Singleton: true, ReadOnly: true, Doc: "https://dev.freeagent.com/docs/profit_and_loss", }, "projects": { Name: "projects", Path: "projects", Singular: "project", Plural: "projects", Doc: "https://dev.freeagent.com/docs/projects", }, "properties": { Name: "properties", Path: "properties", Singular: "property", Plural: "properties", Doc: "https://dev.freeagent.com/docs/properties", }, "recurring_invoices": { Name: "recurring_invoices", Path: "recurring_invoices", Singular: "recurring_invoice", Plural: "recurring_invoices", ReadOnly: true, Doc: "https://dev.freeagent.com/docs/recurring_invoices", }, "sales_tax_periods": { Name: "sales_tax_periods", Path: "sales_tax_periods", Singular: "sales_tax_period", Plural: "sales_tax_periods", Doc: "https://dev.freeagent.com/docs/sales_tax_periods", }, "stock_items": { Name: "stock_items", Path: "stock_items", Singular: "stock_item", Plural: "stock_items", ReadOnly: true, Doc: "https://dev.freeagent.com/docs/stock_items", }, "tasks": { Name: "tasks", Path: "tasks", Singular: "task", Plural: "tasks", Doc: "https://dev.freeagent.com/docs/tasks", }, "timeslips": { Name: "timeslips", Path: "timeslips", Singular: "timeslip", Plural: "timeslips", Doc: "https://dev.freeagent.com/docs/timeslips", }, "transactions": { Name: "transactions", Path: "accounting/transactions", Singular: "transaction", Plural: "transactions", ReadOnly: true, Doc: "https://dev.freeagent.com/docs/transactions", }, "vat_returns": { Name: "vat_returns", Path: "vat_returns", Singular: "vat_return", Plural: "vat_returns", Doc: "https://dev.freeagent.com/docs/vat_returns", }, "trial_balance": { Name: "trial_balance", Path: "accounting/trial_balance/summary", Singleton: true, ReadOnly: true, Doc: "https://dev.freeagent.com/docs/trial_balance", }, "users": { Name: "users", Path: "users", Singular: "user", Plural: "users", Doc: "https://dev.freeagent.com/docs/users", }, }
Resources holds the families whose paths have been verified against the upstream documentation. Entries are added as each wave of typed models lands; until then, facli raw reaches any endpoint by path.
Functions ¶
func DefaultTokenPath ¶
DefaultTokenPath is where facli keeps credentials when not told otherwise.
func ResourceNames ¶
func ResourceNames() []string
ResourceNames lists the registered families in a stable order.
Types ¶
type APIError ¶
type APIError struct {
StatusCode int
Method string
URL string
Message string
Errors []FieldError
RetryAfter time.Duration
RequestID string
// Body is the raw response, truncated to errorBodyLimit. It is kept so a
// caller can log the original when the parsed message proves unhelpful.
Body []byte
}
APIError is returned for any response with a 4xx or 5xx status.
Example ¶
Classify a failure without matching on message text.
package main
import (
"errors"
"fmt"
"net/http"
"github.com/alekc/freeagent-sdk/freeagent"
)
func main() {
err := error(&freeagent.APIError{
StatusCode: http.StatusUnprocessableEntity,
Method: http.MethodPost,
URL: "/v2/invoices",
Errors: []freeagent.FieldError{
{Field: "dated_on", Message: "can't be blank"},
},
})
if errors.Is(err, freeagent.ErrValidation) {
var apiErr *freeagent.APIError
if errors.As(err, &apiErr) {
for _, fieldErr := range apiErr.Errors {
fmt.Printf("%s: %s\n", fieldErr.Field, fieldErr.Message)
}
}
}
}
Output: dated_on: can't be blank
type AccountingPeriod ¶
type AccountingPeriod struct {
StartsOn Date `json:"starts_on,omitzero"`
EndsOn Date `json:"ends_on,omitzero"`
}
AccountingPeriod is one entry in a company's annual accounting periods.
type Attachment ¶
type Attachment struct {
URL ResourceURL `json:"url,omitempty"`
// Data is the file content, base64 encoded on the wire. Write-only.
Data []byte `json:"data,omitempty"`
FileName string `json:"file_name,omitempty"`
ContentType string `json:"content_type,omitempty"`
Description string `json:"description,omitempty"`
FileSize int `json:"file_size,omitempty"`
ContentSrc string `json:"content_src,omitempty"`
ContentSrcMedium string `json:"content_src_medium,omitempty"`
ContentSrcSmall string `json:"content_src_small,omitempty"`
ExpiresAt Time `json:"expires_at,omitzero"`
}
Attachment is a file attached to another record.
The same JSON key carries two shapes: on read the API returns the stored file's metadata and time-limited download URLs, and on write it expects the file content. Set Data, FileName and ContentType to upload; everything else is populated by the server.
See https://dev.freeagent.com/docs/attachments
func (Attachment) MarshalJSON ¶
func (a Attachment) MarshalJSON() ([]byte, error)
MarshalJSON enforces the documented size limit at encode time, so an oversized upload fails locally on any resource that carries an attachment rather than after transferring several megabytes.
type AttachmentService ¶
type AttachmentService struct {
// contains filtered or unexported fields
}
AttachmentService reads and removes attachments. There is no list or create endpoint: attachments are created through the parent record's attachment field, so this service deliberately offers neither.
See https://dev.freeagent.com/docs/attachments
func (*AttachmentService) Get ¶
func (s *AttachmentService) Get(ctx context.Context, id int64) (*Attachment, *Response, error)
Get fetches one attachment by numeric id.
func (*AttachmentService) GetURL ¶
func (s *AttachmentService) GetURL(ctx context.Context, ref ResourceURL) (*Attachment, *Response, error)
GetURL fetches the attachment a payload reference points at.
func (*AttachmentService) Meta ¶
func (s *AttachmentService) Meta() ResourceMeta
Meta returns the resource metadata.
type BalanceSheet ¶
type BalanceSheet struct {
AccountingPeriodStartDate Date `json:"accounting_period_start_date,omitzero"`
AsAtDate Date `json:"as_at_date,omitzero"`
Currency string `json:"currency,omitempty"`
CapitalAssets *BalanceSheetCapitalAssets `json:"capital_assets,omitempty"`
CurrentAssets *BalanceSheetSection `json:"current_assets,omitempty"`
CurrentLiabilities *BalanceSheetSection `json:"current_liabilities,omitempty"`
OwnersEquity *BalanceSheetEquity `json:"owners_equity,omitempty"`
NetCurrentAssets *Decimal `json:"net_current_assets,omitempty"`
TotalAssets *Decimal `json:"total_assets,omitempty"`
TotalOwnersEquity *Decimal `json:"total_owners_equity,omitempty"`
}
BalanceSheet is the balance sheet as at a date.
type BalanceSheetAccount ¶
type BalanceSheetAccount struct {
Name string `json:"name,omitempty"`
NominalCode string `json:"nominal_code,omitempty"`
TotalDebit *Decimal `json:"total_debit_value,omitempty"`
}
BalanceSheetAccount is one account line.
type BalanceSheetCapitalAssets ¶
type BalanceSheetCapitalAssets struct {
NetBookValue *Decimal `json:"net_book_value,omitempty"`
}
BalanceSheetCapitalAssets summarises capital assets.
type BalanceSheetEquity ¶
type BalanceSheetEquity struct {
RetainedProfit *Decimal `json:"retained_profit,omitempty"`
}
BalanceSheetEquity summarises owners' equity.
type BalanceSheetSection ¶
type BalanceSheetSection struct {
Accounts []BalanceSheetAccount `json:"accounts,omitempty"`
}
BalanceSheetSection groups the accounts under one heading.
type BankAccount ¶
type BankAccount struct {
URL ResourceURL `json:"url,omitempty"`
// Type, Name, BankName and OpeningBalance are required on create.
Type string `json:"type,omitempty"`
Name string `json:"name,omitempty"`
BankName string `json:"bank_name,omitempty"`
// OpeningBalance is the balance at the FreeAgent start date.
OpeningBalance *Decimal `json:"opening_balance,omitempty"`
// Currency is immutable once the account has transactions.
Currency string `json:"currency,omitempty"`
// Status is active or hidden.
Status string `json:"status,omitempty"`
IsPersonal *bool `json:"is_personal,omitempty"`
IsPrimary *bool `json:"is_primary,omitempty"`
BankCode string `json:"bank_code,omitempty"`
BankGuessEnabled *bool `json:"bank_guess_enabled,omitempty"`
// Standard and credit card accounts.
AccountNumber string `json:"account_number,omitempty"`
SortCode string `json:"sort_code,omitempty"`
SecondarySortCode string `json:"secondary_sort_code,omitempty"`
IBAN string `json:"iban,omitempty"`
BIC string `json:"bic,omitempty"`
// PayPal accounts.
Email string `json:"email,omitempty"`
// Read-only.
CurrentBalance *Decimal `json:"current_balance,omitempty"`
LatestActivityDate Date `json:"latest_activity_date,omitzero"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
// Transaction tallies. Undocumented, observed on the live API, and
// useful for spotting an account with unexplained items waiting.
TotalCount *int `json:"total_count,omitempty"`
UnexplainedTransactionCount *int `json:"unexplained_transaction_count,omitempty"`
MarkedForReviewCount *int `json:"marked_for_review_count,omitempty"`
ManuallyAddedTransactionCount *int `json:"manually_added_transaction_count,omitempty"`
}
BankAccount is a bank, credit card or payment-provider account.
Several fields apply only to certain account types: AccountNumber, SortCode, IBAN and BIC to standard accounts, AccountNumber alone to credit cards, and Email to PayPal accounts.
type BankAccountService ¶
type BankAccountService struct {
Collection[BankAccount]
}
BankAccountService covers https://dev.freeagent.com/docs/bank_accounts
type BankFeed ¶
type BankFeed struct {
URL ResourceURL `json:"url,omitempty"`
BankAccount ResourceURL `json:"bank_account,omitempty"`
// State is the feed's current status, for example enabled.
State string `json:"state,omitempty"`
// FeedType is api or open_banking.
FeedType string `json:"feed_type,omitempty"`
BankServiceName string `json:"bank_service_name,omitempty"`
// SCAExpiresAt is when strong customer authentication lapses and the feed
// needs reconnecting. API feeds only.
SCAExpiresAt Time `json:"sca_expires_at,omitzero"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
BankFeed is a live connection importing transactions into a bank account.
Read-only: a feed is established through the FreeAgent interface or a banking partner, not through this API.
type BankFeedService ¶
type BankFeedService struct {
ReadCollection[BankFeed]
}
BankFeedService covers https://dev.freeagent.com/docs/bank_feeds
type BankTransaction ¶
type BankTransaction struct {
URL ResourceURL `json:"url,omitempty"`
BankAccount ResourceURL `json:"bank_account,omitempty"`
// Amount is in the company's native currency.
Amount *Decimal `json:"amount,omitempty"`
DatedOn Date `json:"dated_on,omitzero"`
Description string `json:"description,omitempty"`
FullDescription string `json:"full_description,omitempty"`
// TransactionID is the bank's own identifier, also known as fit_id.
TransactionID string `json:"transaction_id,omitempty"`
// Read-only.
UnexplainedAmount *Decimal `json:"unexplained_amount,omitempty"`
IsManual *bool `json:"is_manual,omitempty"`
MatchingTransactionsCount *int `json:"matching_transactions_count,omitempty"`
BankTransactionExplanations []BankTransactionExplanation `json:"bank_transaction_explanations,omitempty"`
UploadedAt Time `json:"uploaded_at,omitzero"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
BankTransaction is a line on a bank statement or feed.
Individual transactions are not created, updated or deleted through the API: they arrive by statement upload or bank feed, which is why this family exposes only reads plus UploadStatement.
type BankTransactionExplanation ¶
type BankTransactionExplanation struct {
URL ResourceURL `json:"url,omitempty"`
// One of BankAccount or BankTransaction is required.
BankAccount ResourceURL `json:"bank_account,omitempty"`
BankTransaction ResourceURL `json:"bank_transaction,omitempty"`
DatedOn Date `json:"dated_on,omitzero"`
GrossValue *Decimal `json:"gross_value,omitempty"`
Description string `json:"description,omitempty"`
Category ResourceURL `json:"category,omitempty"`
ChequeNumber string `json:"cheque_number,omitempty"`
SalesTaxRate *Decimal `json:"sales_tax_rate,omitempty"`
SalesTaxValue *Decimal `json:"sales_tax_value,omitempty"`
// SalesTaxStatus is TAXABLE, EXEMPT or OUT_OF_SCOPE.
SalesTaxStatus string `json:"sales_tax_status,omitempty"`
SecondSalesTaxRate *Decimal `json:"second_sales_tax_rate,omitempty"`
SecondSalesTaxValue *Decimal `json:"second_sales_tax_value,omitempty"`
SecondSalesTaxStatus string `json:"second_sales_tax_status,omitempty"`
// ECStatus is UK/Non-EC, EC Goods, EC Services, Reverse Charge or
// EC VAT MOSS. PlaceOfSupply is required for EC VAT MOSS.
ECStatus string `json:"ec_status,omitempty"`
PlaceOfSupply string `json:"place_of_supply,omitempty"`
// Payments and refunds.
Project ResourceURL `json:"project,omitempty"`
RebillType string `json:"rebill_type,omitempty"`
RebillFactor *Decimal `json:"rebill_factor,omitempty"`
ReceiptReference string `json:"receipt_reference,omitempty"`
// Invoice and bill settlement. ForeignCurrencyValue applies when the
// settled document is in another currency.
PaidInvoice ResourceURL `json:"paid_invoice,omitempty"`
PaidBill ResourceURL `json:"paid_bill,omitempty"`
ForeignCurrencyValue *Decimal `json:"foreign_currency_value,omitempty"`
// Money paid to or from a user.
PaidUser ResourceURL `json:"paid_user,omitempty"`
// Transfers between accounts.
TransferBankAccount ResourceURL `json:"transfer_bank_account,omitempty"`
// Stock movements.
StockItem ResourceURL `json:"stock_item,omitempty"`
StockAlteringQuantity *int `json:"stock_altering_quantity,omitempty"`
// Capital assets. DisposedAsset is required for a disposal.
DisposedAsset ResourceURL `json:"disposed_asset,omitempty"`
// UK unincorporated landlords.
Property ResourceURL `json:"property,omitempty"`
// Opening balances against an initial debtor or creditor category.
DirectContact ResourceURL `json:"direct_contact,omitempty"`
Attachment *Attachment `json:"attachment,omitempty"`
// Read-only.
Type string `json:"type,omitempty"`
CapitalAsset ResourceURL `json:"capital_asset,omitempty"`
LinkedTransferExplanation ResourceURL `json:"linked_transfer_explanation,omitempty"`
LinkedTransferAccount ResourceURL `json:"linked_transfer_account,omitempty"`
MarkedForReview *bool `json:"marked_for_review,omitempty"`
IsMoneyIn *bool `json:"is_money_in,omitempty"`
IsMoneyOut *bool `json:"is_money_out,omitempty"`
IsMoneyPaidToUser *bool `json:"is_money_paid_to_user,omitempty"`
IsLocked *bool `json:"is_locked,omitempty"`
IsDeletable *bool `json:"is_deletable,omitempty"`
LockedAttributes []string `json:"locked_attributes,omitempty"`
LockedReason string `json:"locked_reason,omitempty"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
BankTransactionExplanation records what a bank transaction was for.
Which fields are required depends on the kind of explanation: PaidInvoice for an invoice receipt, PaidBill for a bill payment, TransferBankAccount for a transfer, and so on. The grouped comments below follow the upstream documentation.
See https://dev.freeagent.com/docs/bank_transaction_explanations
type BankTransactionExplanationService ¶
type BankTransactionExplanationService struct {
Collection[BankTransactionExplanation]
}
BankTransactionExplanationService covers https://dev.freeagent.com/docs/bank_transaction_explanations
func (*BankTransactionExplanationService) All ¶
func (s *BankTransactionExplanationService) All(context.Context, *ListOptions) iter.Seq2[BankTransactionExplanation, error]
All is unavailable without a bank account. Use AllForAccount.
func (*BankTransactionExplanationService) AllForAccount ¶
func (s *BankTransactionExplanationService) AllForAccount(ctx context.Context, account ResourceURL, opts *ListOptions) iter.Seq2[BankTransactionExplanation, error]
AllForAccount iterates every explanation for a bank account.
func (*BankTransactionExplanationService) List ¶
func (s *BankTransactionExplanationService) List(context.Context, *ListOptions) ([]BankTransactionExplanation, *Response, error)
List is unavailable without a bank account. The API requires the bank_account parameter, so this shadows the inherited List rather than letting it fail remotely. Use ListForAccount.
func (*BankTransactionExplanationService) ListForAccount ¶
func (s *BankTransactionExplanationService) ListForAccount(ctx context.Context, account ResourceURL, opts *ListOptions) ([]BankTransactionExplanation, *Response, error)
ListForAccount fetches one page of explanations for a bank account.
type BankTransactionService ¶
type BankTransactionService struct {
ReadCollection[BankTransaction]
}
BankTransactionService covers https://dev.freeagent.com/docs/bank_transactions
func (*BankTransactionService) All ¶
func (s *BankTransactionService) All(context.Context, *ListOptions) iter.Seq2[BankTransaction, error]
All is unavailable without a bank account. Use AllForAccount.
func (*BankTransactionService) AllForAccount ¶
func (s *BankTransactionService) AllForAccount(ctx context.Context, account ResourceURL, opts *ListOptions) iter.Seq2[BankTransaction, error]
AllForAccount iterates every transaction for a bank account.
func (*BankTransactionService) List ¶
func (s *BankTransactionService) List(context.Context, *ListOptions) ([]BankTransaction, *Response, error)
List is unavailable without a bank account. The API requires the bank_account parameter, so this shadows the inherited List rather than letting it fail remotely. Use ListForAccount.
func (*BankTransactionService) ListForAccount ¶
func (s *BankTransactionService) ListForAccount(ctx context.Context, account ResourceURL, opts *ListOptions) ([]BankTransaction, *Response, error)
ListForAccount fetches one page of transactions for a bank account.
func (*BankTransactionService) UploadStatement ¶
func (s *BankTransactionService) UploadStatement(ctx context.Context, account ResourceURL, lines []StatementLine) (*Response, error)
UploadStatement posts statement lines to a bank account. This is the only way transactions enter FreeAgent through the API.
Import is asynchronous. The call returns before the lines are queryable, and the delay has been observed to range from under a second to most of a minute, so a read straight afterwards will often come back empty. Poll ListForAccount until the lines appear rather than treating the 200 as confirmation that they exist.
type Bill ¶
type Bill struct {
URL ResourceURL `json:"url,omitempty"`
// Contact is required.
Contact ResourceURL `json:"contact,omitempty"`
Project ResourceURL `json:"project,omitempty"`
Property ResourceURL `json:"property,omitempty"`
Reference string `json:"reference,omitempty"`
DatedOn Date `json:"dated_on,omitzero"`
DueOn Date `json:"due_on,omitzero"`
Currency string `json:"currency,omitempty"`
Comments string `json:"comments,omitempty"`
// InputTotalValuesIncTax defaults to false for the native currency and
// true otherwise.
InputTotalValuesIncTax *bool `json:"input_total_values_inc_tax,omitempty"`
IsPaidByHirePurchase *bool `json:"is_paid_by_hire_purchase,omitempty"`
// ECStatus is UK/Non-EC, EC Goods, EC Services or Reverse Charge.
ECStatus string `json:"ec_status,omitempty"`
// Rebilling. RebillFactor is required when RebillType is markup or price.
RebillType string `json:"rebill_type,omitempty"`
RebillFactor *Decimal `json:"rebill_factor,omitempty"`
RebillToProject ResourceURL `json:"rebill_to_project,omitempty"`
// Recurring is Weekly, Two Weekly, Four Weekly, Two Monthly, Quarterly,
// Biannually, Annually or 2-Yearly.
Recurring string `json:"recurring,omitempty"`
RecurringEndDate Date `json:"recurring_end_date,omitzero"`
// CISDeductionBand is cis_gross, cis_standard or cis_higher.
CISDeductionBand string `json:"cis_deduction_band,omitempty"`
Attachment *Attachment `json:"attachment,omitempty"`
BillItems []BillItem `json:"bill_items,omitempty"`
// Read-only.
Status string `json:"status,omitempty"`
LongStatus string `json:"long_status,omitempty"`
PaidOn Date `json:"paid_on,omitzero"`
TotalValue *Decimal `json:"total_value,omitempty"`
NetValue *Decimal `json:"net_value,omitempty"`
DueValue *Decimal `json:"due_value,omitempty"`
NativeDueValue *Decimal `json:"native_due_value,omitempty"`
ExchangeRate *Decimal `json:"exchange_rate,omitempty"`
SalesTaxValue *Decimal `json:"sales_tax_value,omitempty"`
SecondSalesTaxValue *Decimal `json:"second_sales_tax_value,omitempty"`
CISDeductionRate *Decimal `json:"cis_deduction_rate,omitempty"`
CISDeduction *Decimal `json:"cis_deduction,omitempty"`
CISDeductionSuffered *Decimal `json:"cis_deduction_suffered,omitempty"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
Bill is a purchase invoice owed to a supplier.
type BillItem ¶
type BillItem struct {
URL ResourceURL `json:"url,omitempty"`
// Destroy set to 1 removes the line on a write.
Destroy *int `json:"_destroy,omitempty"`
// Category is required.
Category ResourceURL `json:"category,omitempty"`
Description string `json:"description,omitempty"`
Project ResourceURL `json:"project,omitempty"`
// TotalValue includes tax; TotalValueExTax is the alternative form. Send
// one or the other, not both.
TotalValue *Decimal `json:"total_value,omitempty"`
TotalValueExTax *Decimal `json:"total_value_ex_tax,omitempty"`
ManualSalesTaxAmount *Decimal `json:"manual_sales_tax_amount,omitempty"`
SalesTaxRate *Decimal `json:"sales_tax_rate,omitempty"`
// SalesTaxStatus is TAXABLE, EXEMPT or OUT_OF_SCOPE.
SalesTaxStatus string `json:"sales_tax_status,omitempty"`
SecondSalesTaxRate *Decimal `json:"second_sales_tax_rate,omitempty"`
SecondSalesTaxStatus string `json:"second_sales_tax_status,omitempty"`
// Unit is -no unit-, Hours, Days, Weeks, Months, Years, Products,
// Services, Training or Stock.
Unit string `json:"unit,omitempty"`
Quantity *Decimal `json:"quantity,omitempty"`
StockItem ResourceURL `json:"stock_item,omitempty"`
StockAlteringQuantity *Decimal `json:"stock_altering_quantity,omitempty"`
CISDeductionRate *Decimal `json:"cis_deduction_rate,omitempty"`
// Read-only.
Bill ResourceURL `json:"bill,omitempty"`
CapitalAsset ResourceURL `json:"capital_asset,omitempty"`
StockItemDescription string `json:"stock_item_description,omitempty"`
}
BillItem is one line on a bill. A bill accepts up to 40 items.
type BillService ¶
type BillService struct {
Collection[Bill]
}
BillService covers https://dev.freeagent.com/docs/bills
type CISBand ¶
type CISBand struct {
// Name is cis_gross, cis_standard or cis_higher.
Name string `json:"name,omitempty"`
// DeductionRate is a fraction, so 20% arrives as "0.2".
DeductionRate *Decimal `json:"deduction_rate,omitempty"`
IncomeDescription string `json:"income_description,omitempty"`
DeductionDescription string `json:"deduction_description,omitempty"`
NominalCode string `json:"nominal_code,omitempty"`
}
CISBand is one Construction Industry Scheme deduction band.
UK companies enrolled in CIS for subcontractors only; the list is empty otherwise.
type CISBandService ¶
type CISBandService struct {
// contains filtered or unexported fields
}
CISBandService covers https://dev.freeagent.com/docs/cis_bands
The envelope key is available_bands, not cis_bands, so this does not fit the generic collection.
func (*CISBandService) Meta ¶
func (s *CISBandService) Meta() ResourceMeta
Meta returns the resource metadata.
type CapitalAsset ¶
type CapitalAsset struct {
URL ResourceURL `json:"url,omitempty"`
Description string `json:"description,omitempty"`
// AssetType is a capital asset type name, not a URL.
AssetType string `json:"asset_type,omitempty"`
PurchasedOn Date `json:"purchased_on,omitzero"`
DisposedOn Date `json:"disposed_on,omitzero"`
DepreciationProfile *DepreciationProfile `json:"depreciation_profile,omitempty"`
// AssetLifeYears is superseded by DepreciationProfile.
//
// Deprecated: use DepreciationProfile.AssetLifeYears.
AssetLifeYears *int `json:"asset_life_years,omitempty"`
// CapitalAssetHistory is only populated when include_history=true.
CapitalAssetHistory []CapitalAssetHistoryEntry `json:"capital_asset_history,omitempty"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
CapitalAsset is a purchase written down over time.
The API exposes reads only: assets come into being through the expense, bill or bank explanation that bought them, which is why this family embeds ReadCollection.
type CapitalAssetHistoryEntry ¶
type CapitalAssetHistoryEntry struct {
// Type is purchase, depreciation, annual_investment_allowance or
// disposal.
Type string `json:"type,omitempty"`
Description string `json:"description,omitempty"`
Date Date `json:"date,omitzero"`
Value *Decimal `json:"value,omitempty"`
TaxValue *Decimal `json:"tax_value,omitempty"`
Link ResourceURL `json:"link,omitempty"`
}
CapitalAssetHistoryEntry is one event in an asset's life.
type CapitalAssetService ¶
type CapitalAssetService struct {
ReadCollection[CapitalAsset]
}
CapitalAssetService covers https://dev.freeagent.com/docs/capital_assets
func (*CapitalAssetService) GetWithHistory ¶
func (s *CapitalAssetService) GetWithHistory(ctx context.Context, id int64) (*CapitalAsset, *Response, error)
GetWithHistory is Get with include_history=true.
func (*CapitalAssetService) ListWithHistory ¶
func (s *CapitalAssetService) ListWithHistory(ctx context.Context, opts *ListOptions) ([]CapitalAsset, *Response, error)
ListWithHistory is List with include_history=true, which populates CapitalAssetHistory. It is off by default because the history is large.
type CapitalAssetType ¶
type CapitalAssetType struct {
URL ResourceURL `json:"url,omitempty"`
Name string `json:"name,omitempty"`
// Read-only.
SystemDefault *bool `json:"system_default,omitempty"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
CapitalAssetType names a class of capital asset. Four are seeded by FreeAgent and marked SystemDefault; the rest are user-created and are the only ones that may be changed or removed.
type CapitalAssetTypeService ¶
type CapitalAssetTypeService struct {
Collection[CapitalAssetType]
}
CapitalAssetTypeService covers https://dev.freeagent.com/docs/capital_asset_types
type Cashflow ¶
type Cashflow struct {
From Date `json:"from,omitzero"`
To Date `json:"to,omitzero"`
Incoming *CashflowSection `json:"incoming,omitempty"`
Outgoing *CashflowSection `json:"outgoing,omitempty"`
Balance *Decimal `json:"balance,omitempty"`
}
Cashflow is money in and out over a period, bucketed by month.
It reports history only: dates in the future come back as zero rather than as a forecast.
type CashflowMonth ¶
type CashflowMonth struct {
Month int `json:"month,omitempty"`
Year int `json:"year,omitempty"`
Total *Decimal `json:"total,omitempty"`
}
CashflowMonth is one month's bucket.
type CashflowSection ¶
type CashflowSection struct {
Total *Decimal `json:"total,omitempty"`
Months []CashflowMonth `json:"months,omitempty"`
}
CashflowSection is one direction of the cashflow report.
type Category ¶
type Category struct {
URL ResourceURL `json:"url,omitempty"`
Description string `json:"description,omitempty"`
// NominalCode identifies the category. On create it must be free and
// inside the range the group allows: admin expenses are 200 to 399.
NominalCode string `json:"nominal_code,omitempty"`
// GroupDescription is present on income and spending categories. It is
// read-only in practice: writes use CategoryGroup instead.
GroupDescription string `json:"group_description,omitempty"`
// CategoryGroup selects the group on create and is required there, even
// though the documented attribute list does not mention it. Omitting it
// returns 422 "” is not a valid category_group". Values are the group
// names without the _categories suffix: admin_expenses, cost_of_sales,
// income, general.
CategoryGroup string `json:"category_group,omitempty"`
// AllowableForTax appears on spending categories only.
AllowableForTax *bool `json:"allowable_for_tax,omitempty"`
// TaxReportingName is where the category lands in statutory accounts. It
// is required on create and only accepts values from a fixed list, which
// is not published: read one off an existing category in the same group.
TaxReportingName string `json:"tax_reporting_name,omitempty"`
// AutoSalesTaxRate is Outside scope, Zero rate, Reduced rate,
// Standard rate or Exempt.
AutoSalesTaxRate string `json:"auto_sales_tax_rate,omitempty"`
// Sub-account links. Each is present only on the matching code range.
BankAccount ResourceURL `json:"bank_account,omitempty"`
CapitalAssetType ResourceURL `json:"capital_asset_type,omitempty"`
StockItem ResourceURL `json:"stock_item,omitempty"`
HirePurchase ResourceURL `json:"hire_purchase,omitempty"`
User ResourceURL `json:"user,omitempty"`
// Group is the envelope the category arrived in. It is filled in by this
// library rather than sent by the API, and is never written back.
Group string `json:"-"`
}
Category is an accounting category, identified by its nominal code rather than a numeric id.
type CategoryGroups ¶
type CategoryGroups struct {
AdminExpenses []Category `json:"admin_expenses_categories,omitempty"`
CostOfSales []Category `json:"cost_of_sales_categories,omitempty"`
Income []Category `json:"income_categories,omitempty"`
General []Category `json:"general_categories,omitempty"`
}
CategoryGroups is the grouped response the categories endpoint returns. Unlike every other collection there is no flat list, so this mirrors the envelope rather than pretending otherwise.
func (*CategoryGroups) Flatten ¶
func (g *CategoryGroups) Flatten() []Category
Flatten returns every category with Group set, for callers that want one list rather than four.
type CategoryService ¶
type CategoryService struct {
// contains filtered or unexported fields
}
CategoryService covers https://dev.freeagent.com/docs/categories
Categories do not fit the generic collection: results come back grouped under four keys with no flat list, and records are addressed by nominal code rather than a numeric id.
func (*CategoryService) Delete ¶
Delete removes a category. Only user-created categories with no items can be deleted.
func (*CategoryService) Get ¶
func (s *CategoryService) Get(ctx context.Context, nominalCode string) (*Category, *Response, error)
Get fetches one category by nominal code. The reply is nested under whichever group the category belongs to, so the group is resolved here and recorded on the result.
func (*CategoryService) List ¶
func (s *CategoryService) List(ctx context.Context, subAccounts bool) (*CategoryGroups, *Response, error)
List returns the categories grouped as the API reports them. Set subAccounts to fetch sub-accounts in place of their parent accounts.
func (*CategoryService) Meta ¶
func (s *CategoryService) Meta() ResourceMeta
Meta returns the resource metadata.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a FreeAgent API client. It is safe for concurrent use.
func NewClient ¶
NewClient builds a client. Exactly one of WithTokenSource or WithoutAuth is required.
func (*Client) Raw ¶
func (c *Client) Raw(ctx context.Context, method, path string, query url.Values, body any) ([]byte, *Response, error)
Raw issues an arbitrary request against the API root and returns the undecoded response body. It exists so tooling can reach endpoints that have no typed model yet, and so a caller can inspect fields this library does not model. path is relative to the API root, for example "invoices/123".
type Collection ¶
type Collection[T any] struct { ReadCollection[T] }
Collection adds the write verbs to ReadCollection. Resource services embed one of the two and add only the endpoints that do not fit the shape, which is what keeps 45 resource families from turning into 225 near-identical methods.
func (*Collection[T]) Create ¶
func (c *Collection[T]) Create(ctx context.Context, in *T) (*T, *Response, error)
Create posts a new record and returns the server's version of it.
type Company ¶
type Company struct {
URL ResourceURL `json:"url,omitempty"`
// ID is typed as an integer in the documentation while the example on the
// same page returns it quoted. The live API sends an unquoted number, so
// the example is the stale one, but the type stays lenient rather than
// betting on that staying true.
ID Int64 `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Subdomain string `json:"subdomain,omitempty"`
// Locale is undocumented but returned by the live API.
Locale string `json:"locale,omitempty"`
// Type is one of UkLimitedCompany, UkLimitedLiabilityPartnership,
// UkPartnership, UkSoleTrader, UkUnincorporatedLandlord,
// UsLimitedLiabilityCompany, UsPartnership, UsSoleProprietor, UsCCorp,
// UsSCorp or UniversalCompany.
Type string `json:"type,omitempty"`
Currency string `json:"currency,omitempty"`
// MileageUnits is miles or kilometers.
MileageUnits string `json:"mileage_units,omitempty"`
CompanyStartDate Date `json:"company_start_date,omitzero"`
TradingStartDate Date `json:"trading_start_date,omitzero"`
FirstAccountingYearEnd Date `json:"first_accounting_year_end,omitzero"`
FreeAgentStartDate Date `json:"freeagent_start_date,omitzero"`
AnnualAccountingPeriods []AccountingPeriod `json:"annual_accounting_periods,omitempty"`
Address1 string `json:"address1,omitempty"`
Address2 string `json:"address2,omitempty"`
Address3 string `json:"address3,omitempty"`
Town string `json:"town,omitempty"`
Region string `json:"region,omitempty"`
Postcode string `json:"postcode,omitempty"`
Country string `json:"country,omitempty"`
CompanyRegistrationNumber string `json:"company_registration_number,omitempty"`
ContactEmail string `json:"contact_email,omitempty"`
ContactPhone string `json:"contact_phone,omitempty"`
Website string `json:"website,omitempty"`
BusinessType string `json:"business_type,omitempty"`
BusinessCategory string `json:"business_category,omitempty"`
// ShortDateFormat is one of "dd mmm yy", "dd-mm-yyyy", "mm/dd/yyyy" or
// "yyyy-mm-dd".
ShortDateFormat string `json:"short_date_format,omitempty"`
SalesTaxName string `json:"sales_tax_name,omitempty"`
SalesTaxRegistrationNumber string `json:"sales_tax_registration_number,omitempty"`
SalesTaxRegistrationStatus string `json:"sales_tax_registration_status,omitempty"`
SalesTaxEffectiveDate Date `json:"sales_tax_effective_date,omitzero"`
SalesTaxIsValueAdded *bool `json:"sales_tax_is_value_added,omitempty"`
SalesTaxDeregistrationEffectiveDate Date `json:"sales_tax_deregistration_effective_date,omitzero"`
SalesTaxRates []Decimal `json:"sales_tax_rates,omitempty"`
// Undocumented, observed on the live API.
ECVATReportingEnabled *bool `json:"ec_vat_reporting_enabled,omitempty"`
SupportsAutoSalesTaxOnPurchases *bool `json:"supports_auto_sales_tax_on_purchases,omitempty"`
// Universal and US accounts only.
SecondSalesTaxName string `json:"second_sales_tax_name,omitempty"`
SecondSalesTaxRates []Decimal `json:"second_sales_tax_rates,omitempty"`
SecondSalesTaxIsCompound *bool `json:"second_sales_tax_is_compound,omitempty"`
// UK VAT accounts only. InitialVATBasis is Invoice or Cash.
VATFirstReturnPeriodEndsOn Date `json:"vat_first_return_period_ends_on,omitzero"`
InitialVATBasis string `json:"initial_vat_basis,omitempty"`
InitiallyOnFRS *bool `json:"initially_on_frs,omitempty"`
InitialVATFRSType string `json:"initial_vat_frs_type,omitempty"`
// Construction Industry Scheme. CISEnabled and CISSubcontractor are
// aliases of each other in the API.
CISEnabled *bool `json:"cis_enabled,omitempty"`
CISSubcontractor *bool `json:"cis_subcontractor,omitempty"`
CISContractor *bool `json:"cis_contractor,omitempty"`
LockedAttributes []string `json:"locked_attributes,omitempty"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
Company is the account's own details. It is a singleton: there is no collection and no id segment.
type CompanyService ¶
CompanyService covers https://dev.freeagent.com/docs/company
func (*CompanyService) BusinessCategories ¶
BusinessCategories lists the business categories the account may use.
func (*CompanyService) TaxTimeline ¶
func (s *CompanyService) TaxTimeline(ctx context.Context) ([]TaxTimelineItem, *Response, error)
TaxTimeline returns upcoming tax events. It needs the Tax, Accounting and Users access level.
type Contact ¶
type Contact struct {
URL ResourceURL `json:"url,omitempty"`
FirstName string `json:"first_name,omitempty"`
LastName string `json:"last_name,omitempty"`
OrganisationName string `json:"organisation_name,omitempty"`
Email string `json:"email,omitempty"`
BillingEmail string `json:"billing_email,omitempty"`
PhoneNumber string `json:"phone_number,omitempty"`
Mobile string `json:"mobile,omitempty"`
Address1 string `json:"address1,omitempty"`
Address2 string `json:"address2,omitempty"`
Address3 string `json:"address3,omitempty"`
Town string `json:"town,omitempty"`
Region string `json:"region,omitempty"`
Postcode string `json:"postcode,omitempty"`
Country string `json:"country,omitempty"`
// Status is Active or Hidden.
Status string `json:"status,omitempty"`
// Locale is one of the language codes FreeAgent supports for invoices.
Locale string `json:"locale,omitempty"`
// ChargeSalesTax is Auto, Always or Never.
ChargeSalesTax string `json:"charge_sales_tax,omitempty"`
SalesTaxRegistrationNumber string `json:"sales_tax_registration_number,omitempty"`
ContactNameOnInvoices *bool `json:"contact_name_on_invoices,omitempty"`
UsesContactInvoiceSequence *bool `json:"uses_contact_invoice_sequence,omitempty"`
DefaultPaymentTermsInDays *int `json:"default_payment_terms_in_days,omitempty"`
// Construction Industry Scheme. CISDeductionRate is required when
// IsCISSubcontractor is true, and is one of cis_gross, cis_standard or
// cis_higher.
IsCISSubcontractor *bool `json:"is_cis_subcontractor,omitempty"`
CISDeductionRate string `json:"cis_deduction_rate,omitempty"`
UniqueTaxReference string `json:"unique_tax_reference,omitempty"`
SubcontractorVerificationNumber string `json:"subcontractor_verification_number,omitempty"`
// Read-only.
AccountBalance *Decimal `json:"account_balance,omitempty"`
ActiveProjectsCount Int64 `json:"active_projects_count,omitempty"`
DirectDebitMandateState string `json:"direct_debit_mandate_state,omitempty"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
Contact is a client or supplier.
Either OrganisationName, or FirstName and LastName, is required. Several fields need the Contacts and Projects permission and are absent otherwise.
type ContactService ¶
type ContactService struct {
Collection[Contact]
}
ContactService covers https://dev.freeagent.com/docs/contacts
type CorporationTaxReturn ¶
type CorporationTaxReturn struct {
URL ResourceURL `json:"url,omitempty"`
PeriodStartsOn Date `json:"period_starts_on,omitzero"`
PeriodEndsOn Date `json:"period_ends_on,omitzero"`
FilingDueOn Date `json:"filing_due_on,omitzero"`
// FilingStatus is draft, unfiled, pending, rejected, filed or
// marked_as_filed.
FilingStatus string `json:"filing_status,omitempty"`
FiledAt Time `json:"filed_at,omitzero"`
FiledReference string `json:"filed_reference,omitempty"`
AmountDue *Decimal `json:"amount_due,omitempty"`
// PaymentDueOn and PaymentStatus sit on the return itself here, rather
// than in a payments array as VAT and income tax have them.
PaymentDueOn Date `json:"payment_due_on,omitzero"`
PaymentStatus string `json:"payment_status,omitempty"`
}
CorporationTaxReturn is one corporation tax period.
type CorporationTaxReturnService ¶
type CorporationTaxReturnService struct {
// contains filtered or unexported fields
}
CorporationTaxReturnService covers https://dev.freeagent.com/docs/corporation_tax_returns
func (*CorporationTaxReturnService) Get ¶
func (s *CorporationTaxReturnService) Get(ctx context.Context, periodEndsOn Date) (*CorporationTaxReturn, *Response, error)
Get fetches one period by its end date.
func (*CorporationTaxReturnService) List ¶
func (s *CorporationTaxReturnService) List(ctx context.Context) ([]CorporationTaxReturn, *Response, error)
List returns every corporation tax period.
func (*CorporationTaxReturnService) MarkAsFiled ¶
func (s *CorporationTaxReturnService) MarkAsFiled(ctx context.Context, periodEndsOn Date) (*CorporationTaxReturn, *Response, error)
MarkAsFiled records the return as filed. Needs Full Access.
func (*CorporationTaxReturnService) MarkAsPaid ¶
func (s *CorporationTaxReturnService) MarkAsPaid(ctx context.Context, periodEndsOn Date) (*CorporationTaxReturn, *Response, error)
MarkAsPaid records the tax as paid. Unlike VAT, the payment is a property of the return rather than a dated entry, so there is no payment date.
func (*CorporationTaxReturnService) MarkAsUnfiled ¶
func (s *CorporationTaxReturnService) MarkAsUnfiled(ctx context.Context, periodEndsOn Date) (*CorporationTaxReturn, *Response, error)
MarkAsUnfiled reverses MarkAsFiled.
func (*CorporationTaxReturnService) MarkAsUnpaid ¶
func (s *CorporationTaxReturnService) MarkAsUnpaid(ctx context.Context, periodEndsOn Date) (*CorporationTaxReturn, *Response, error)
MarkAsUnpaid reverses MarkAsPaid.
func (*CorporationTaxReturnService) Meta ¶
func (s *CorporationTaxReturnService) Meta() ResourceMeta
Meta returns the resource metadata.
type CreditNote ¶
type CreditNote struct {
URL ResourceURL `json:"url,omitempty"`
// Contact is required.
Contact ResourceURL `json:"contact,omitempty"`
Project ResourceURL `json:"project,omitempty"`
Property ResourceURL `json:"property,omitempty"`
BankAccount ResourceURL `json:"bank_account,omitempty"`
Reference string `json:"reference,omitempty"`
// DatedOn is required.
DatedOn Date `json:"dated_on,omitzero"`
DueOn Date `json:"due_on,omitzero"`
// PaymentTermsInDays is required; zero means due on receipt.
PaymentTermsInDays *int `json:"payment_terms_in_days,omitempty"`
Currency string `json:"currency,omitempty"`
// Status is Draft, Open, Overdue, Refunded or Written-off, and is driven
// by the transitions rather than set directly.
Status string `json:"status,omitempty"`
Comments string `json:"comments,omitempty"`
DiscountPercent *Decimal `json:"discount_percent,omitempty"`
ClientContactName string `json:"client_contact_name,omitempty"`
PaymentTerms string `json:"payment_terms,omitempty"`
POReference string `json:"po_reference,omitempty"`
OmitHeader *bool `json:"omit_header,omitempty"`
ShowProjectName *bool `json:"show_project_name,omitempty"`
// ECStatus is UK/Non-EC, EC Goods, EC Services, Reverse Charge or
// EC VAT MOSS.
ECStatus string `json:"ec_status,omitempty"`
PlaceOfSupply string `json:"place_of_supply,omitempty"`
// Construction Industry Scheme.
CISRate string `json:"cis_rate,omitempty"`
CISDeductionRate *Decimal `json:"cis_deduction_rate,omitempty"`
CISDeduction *Decimal `json:"cis_deduction,omitempty"`
CISDeductionSuffered *Decimal `json:"cis_deduction_suffered,omitempty"`
CreditNoteItems []CreditNoteItem `json:"credit_note_items,omitempty"`
// Read-only.
LongStatus string `json:"long_status,omitempty"`
NetValue *Decimal `json:"net_value,omitempty"`
SalesTaxValue *Decimal `json:"sales_tax_value,omitempty"`
SecondSalesTaxValue *Decimal `json:"second_sales_tax_value,omitempty"`
TotalValue *Decimal `json:"total_value,omitempty"`
RefundedValue *Decimal `json:"refunded_value,omitempty"`
DueValue *Decimal `json:"due_value,omitempty"`
ExchangeRate *Decimal `json:"exchange_rate,omitempty"`
InvolvesSalesTax *bool `json:"involves_sales_tax,omitempty"`
IsInterimUKVAT *bool `json:"is_interim_uk_vat,omitempty"`
RefundedOn Date `json:"refunded_on,omitzero"`
WrittenOffDate Date `json:"written_off_date,omitzero"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
CreditNote is a credit issued against a contact, the mirror of an invoice.
type CreditNoteItem ¶
type CreditNoteItem struct {
URL ResourceURL `json:"url,omitempty"`
// ID identifies an existing line on a write; leave unset to add one.
ID *int64 `json:"id,omitempty"`
// Destroy set to 1 removes the line on a write.
Destroy *int `json:"_destroy,omitempty"`
Position *Decimal `json:"position,omitempty"`
ItemType string `json:"item_type,omitempty"`
Description string `json:"description,omitempty"`
Quantity *Decimal `json:"quantity,omitempty"`
Price *Decimal `json:"price,omitempty"`
SalesTaxRate *Decimal `json:"sales_tax_rate,omitempty"`
SalesTaxStatus string `json:"sales_tax_status,omitempty"`
SecondSalesTaxRate *Decimal `json:"second_sales_tax_rate,omitempty"`
SecondSalesTaxStatus string `json:"second_sales_tax_status,omitempty"`
// Category is required.
Category ResourceURL `json:"category,omitempty"`
Project ResourceURL `json:"project,omitempty"`
StockItem ResourceURL `json:"stock_item,omitempty"`
}
CreditNoteItem is one line on a credit note.
type CreditNoteReconciliation ¶
type CreditNoteReconciliation struct {
URL ResourceURL `json:"url,omitempty"`
// All four are required.
CreditNote ResourceURL `json:"credit_note,omitempty"`
Invoice ResourceURL `json:"invoice,omitempty"`
GrossValue *Decimal `json:"gross_value,omitempty"`
DatedOn Date `json:"dated_on,omitzero"`
Currency string `json:"currency,omitempty"`
ExchangeRate *Decimal `json:"exchange_rate,omitempty"`
// Read-only.
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
CreditNoteReconciliation records how much of a credit note was applied to an invoice.
See https://dev.freeagent.com/docs/credit_note_reconciliations
type CreditNoteReconciliationService ¶
type CreditNoteReconciliationService struct {
Collection[CreditNoteReconciliation]
}
CreditNoteReconciliationService covers https://dev.freeagent.com/docs/credit_note_reconciliations
type CreditNoteService ¶
type CreditNoteService struct {
Collection[CreditNote]
}
CreditNoteService covers https://dev.freeagent.com/docs/credit_notes
func (*CreditNoteService) MarkAsDraft ¶
func (s *CreditNoteService) MarkAsDraft(ctx context.Context, id int64) (*CreditNote, *Response, error)
MarkAsDraft returns the credit note to draft.
func (*CreditNoteService) MarkAsSent ¶
func (s *CreditNoteService) MarkAsSent(ctx context.Context, id int64) (*CreditNote, *Response, error)
MarkAsSent moves a draft credit note to sent, or reopens a cancelled one.
func (*CreditNoteService) SendEmail ¶
func (s *CreditNoteService) SendEmail(ctx context.Context, id int64, opts *EmailOptions) (*Response, error)
SendEmail emails the credit note. Pass nil to use the account's template.
type Date ¶
Date is a calendar date with no time component, serialised as YYYY-MM-DD. The zero value marshals to null, which FreeAgent reads as unset.
func ParseDate ¶
ParseDate accepts the documented YYYY-MM-DD form and, tolerantly, a full timestamp: several endpoints document a date but return a timestamp.
func (Date) MarshalJSON ¶
MarshalJSON implements json.Marshaler.
func (*Date) UnmarshalJSON ¶
UnmarshalJSON implements json.Unmarshaler.
type Decimal ¶
Decimal carries money, rates and quantities. FreeAgent sends these as JSON strings such as "-90.0" and "0.25", so float64 would lose exactness on values the accounting system treats as authoritative.
type DepreciationProfile ¶
type DepreciationProfile struct {
Method string `json:"method,omitempty"`
AssetLifeYears *int `json:"asset_life_years,omitempty"`
AnnualDepreciationPercentage *int `json:"annual_depreciation_percentage,omitempty"`
// Frequency is monthly (the default) or annually.
Frequency string `json:"frequency,omitempty"`
}
DepreciationProfile describes how an asset loses value.
It is not a resource of its own despite having a documentation page: there is no /v2/depreciation_profiles endpoint. It appears nested on a capital asset, and is accepted nested on expenses, bill items and bank transaction explanations when those create an asset.
AssetLifeYears applies to straight_line, AnnualDepreciationPercentage to reducing_balance; which one is required depends on Method.
type ECMossRate ¶
type ECMossRate struct {
Percentage *Decimal `json:"percentage,omitempty"`
// Band is Standard, Reduced, Parking or Super Reduced.
Band string `json:"band,omitempty"`
}
ECMossRate is one VAT rate available for an EU country on a given date.
type ECMossRates ¶
type ECMossRates struct {
Rates []ECMossRate `json:"sales_tax_rates,omitempty"`
// ECTaxName is the local name for the tax, usually VAT.
ECTaxName string `json:"ec_tax_name,omitempty"`
}
ECMossRates is the reply from the EC VAT MOSS rate lookup.
type EmailAddressService ¶
type EmailAddressService struct {
// contains filtered or unexported fields
}
EmailAddressService covers https://dev.freeagent.com/docs/email_addresses
The reply is an array of plain strings, not of objects, each formatted as `Name <address@example.com>`. There is no model type for that reason.
func (*EmailAddressService) Meta ¶
func (s *EmailAddressService) Meta() ResourceMeta
Meta returns the resource metadata.
type EmailOptions ¶
type EmailOptions struct {
To string `json:"to,omitempty"`
From string `json:"from,omitempty"`
Subject string `json:"subject,omitempty"`
Body string `json:"body,omitempty"`
EmailToSelf bool `json:"email_to_self,omitempty"`
}
EmailOptions overrides the message used when sending a document. A zero value tells FreeAgent to use the account's configured template.
type Environment ¶
Environment bundles the endpoints for one FreeAgent deployment.
One app registered at dev.freeagent.com serves both, so the client ID and secret are shared. What differs is the user account you approve with, and therefore the token, which is why tokens are stored under separate keys.
func EnvironmentByName ¶
func EnvironmentByName(name string) (Environment, error)
EnvironmentByName resolves "production" or "sandbox".
func (Environment) OAuthConfig ¶
func (e Environment) OAuthConfig(clientID, clientSecret, redirectURL string) *oauth2.Config
OAuthConfig builds the OAuth configuration for an environment. The token endpoint authenticates the app with HTTP Basic, so the auth style is pinned rather than probed.
type Estimate ¶
type Estimate struct {
URL ResourceURL `json:"url,omitempty"`
Contact ResourceURL `json:"contact,omitempty"`
Project ResourceURL `json:"project,omitempty"`
// EstimateType is Estimate, Quote or Proposal.
EstimateType string `json:"estimate_type,omitempty"`
// Status is Draft, Sent, Open, Approved, Rejected or Invoiced.
//
// Unlike an invoice, an estimate will not accept a create without one:
// omitting it returns 422 "status is not valid". Send "Draft" and use the
// transitions from there.
Status string `json:"status,omitempty"`
Reference string `json:"reference,omitempty"`
DatedOn Date `json:"dated_on,omitzero"`
Currency string `json:"currency,omitempty"`
Notes string `json:"notes,omitempty"`
DiscountPercent *Decimal `json:"discount_percent,omitempty"`
ClientContactName string `json:"client_contact_name,omitempty"`
// ECStatus is UK/Non-EC, EC Goods, EC Services, Reverse Charge or
// EC VAT MOSS.
ECStatus string `json:"ec_status,omitempty"`
PlaceOfSupply string `json:"place_of_supply,omitempty"`
IncludeSalesTaxOnTotalValue *bool `json:"include_sales_tax_on_total_value,omitempty"`
EstimateItems []EstimateItem `json:"estimate_items,omitempty"`
// Read-only.
NetValue *Decimal `json:"net_value,omitempty"`
SalesTaxValue *Decimal `json:"sales_tax_value,omitempty"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
Estimate is a quote, proposal or estimate sent to a contact.
type EstimateItem ¶
type EstimateItem struct {
URL ResourceURL `json:"url,omitempty"`
// Position starts at 1.
Position *int `json:"position,omitempty"`
// ItemType is Hours, Days, Weeks, Months, Years, -no unit-, Products,
// Services, Training, Expenses, Comments, Bills, Discount or Credit.
ItemType string `json:"item_type,omitempty"`
Description string `json:"description,omitempty"`
Quantity *Decimal `json:"quantity,omitempty"`
Price *Decimal `json:"price,omitempty"`
SalesTaxRate *Decimal `json:"sales_tax_rate,omitempty"`
SalesTaxStatus string `json:"sales_tax_status,omitempty"`
SalesTaxValue *Decimal `json:"sales_tax_value,omitempty"`
SecondSalesTaxRate *Decimal `json:"second_sales_tax_rate,omitempty"`
SecondSalesTaxStatus string `json:"second_sales_tax_status,omitempty"`
SecondSalesTaxValue *Decimal `json:"second_sales_tax_value,omitempty"`
Category ResourceURL `json:"category,omitempty"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
EstimateItem is one line on an estimate.
type EstimateService ¶
type EstimateService struct {
Collection[Estimate]
}
EstimateService covers https://dev.freeagent.com/docs/estimates
func (*EstimateService) ConvertToInvoice ¶
func (s *EstimateService) ConvertToInvoice(ctx context.Context, id int64) (*Estimate, *Response, error)
ConvertToInvoice turns the estimate into an invoice. The reply is the estimate as the API returns it, not the new invoice.
func (*EstimateService) MarkAsApproved ¶
func (s *EstimateService) MarkAsApproved(ctx context.Context, id int64) (*Estimate, *Response, error)
MarkAsApproved marks the estimate approved.
func (*EstimateService) MarkAsDraft ¶
MarkAsDraft returns the estimate to draft.
func (*EstimateService) MarkAsRejected ¶
func (s *EstimateService) MarkAsRejected(ctx context.Context, id int64) (*Estimate, *Response, error)
MarkAsRejected marks the estimate rejected.
func (*EstimateService) MarkAsSent ¶
MarkAsSent marks the estimate sent.
func (*EstimateService) SendEmail ¶
func (s *EstimateService) SendEmail(ctx context.Context, id int64, opts *EmailOptions) (*Response, error)
SendEmail emails the estimate. Pass nil to use the account's template.
type Expense ¶
type Expense struct {
URL ResourceURL `json:"url,omitempty"`
// User and Category are required.
User ResourceURL `json:"user,omitempty"`
Category ResourceURL `json:"category,omitempty"`
Project ResourceURL `json:"project,omitempty"`
Property ResourceURL `json:"property,omitempty"`
DatedOn Date `json:"dated_on,omitzero"`
Currency string `json:"currency,omitempty"`
Description string `json:"description,omitempty"`
ReceiptReference string `json:"receipt_reference,omitempty"`
GrossValue *Decimal `json:"gross_value,omitempty"`
NativeGrossValue *Decimal `json:"native_gross_value,omitempty"`
SalesTaxRate *Decimal `json:"sales_tax_rate,omitempty"`
SalesTaxValue *Decimal `json:"sales_tax_value,omitempty"`
NativeSalesTaxValue *Decimal `json:"native_sales_tax_value,omitempty"`
ManualSalesTaxAmount *Decimal `json:"manual_sales_tax_amount,omitempty"`
// SalesTaxStatus is TAXABLE, EXEMPT or OUT_OF_SCOPE.
SalesTaxStatus string `json:"sales_tax_status,omitempty"`
SecondSalesTaxRate *Decimal `json:"second_sales_tax_rate,omitempty"`
SecondSalesTaxStatus string `json:"second_sales_tax_status,omitempty"`
// ECStatus is UK/Non-EC, EC Goods, EC Services or Reverse Charge.
ECStatus string `json:"ec_status,omitempty"`
// Rebilling. RebillFactor is required when RebillType is markup or price.
RebillType string `json:"rebill_type,omitempty"`
RebillFactor *Decimal `json:"rebill_factor,omitempty"`
RebillToProject ResourceURL `json:"rebill_to_project,omitempty"`
// Stock. Both are required for the purchase of stock category.
StockItem ResourceURL `json:"stock_item,omitempty"`
StockAlteringQuantity *Decimal `json:"stock_altering_quantity,omitempty"`
// Mileage claims. VehicleType is Car, Motorcycle or Bicycle.
Mileage *Decimal `json:"mileage,omitempty"`
VehicleType string `json:"vehicle_type,omitempty"`
EngineType string `json:"engine_type,omitempty"`
EngineSize string `json:"engine_size,omitempty"`
ReclaimMileage *int `json:"reclaim_mileage,omitempty"`
InitialRateMileage *Decimal `json:"initial_rate_mileage,omitempty"`
ReclaimMileageRate *Decimal `json:"reclaim_mileage_rate,omitempty"`
RebillMileageRate *Decimal `json:"rebill_mileage_rate,omitempty"`
HaveVATReceipt *bool `json:"have_vat_receipt,omitempty"`
// Recurring is Weekly, Two Weekly, Four Weekly, Two Monthly, Quarterly,
// Biannually, Annually or 2-Yearly.
Recurring string `json:"recurring,omitempty"`
NextRecursOn Date `json:"next_recurs_on,omitzero"`
RecurringEndDate Date `json:"recurring_end_date,omitzero"`
Attachment *Attachment `json:"attachment,omitempty"`
// Read-only.
CapitalAsset ResourceURL `json:"capital_asset,omitempty"`
RebilledOnInvoice ResourceURL `json:"rebilled_on_invoice,omitempty"`
StockItemDescription string `json:"stock_item_description,omitempty"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
Expense is an out-of-pocket cost incurred by a user.
GrossValue is negative for a payment and positive for a refund. It is required unless the category is Mileage, in which case Mileage and VehicleType are.
type ExpenseService ¶
type ExpenseService struct {
Collection[Expense]
}
ExpenseService covers https://dev.freeagent.com/docs/expenses
func (*ExpenseService) MileageSettings ¶
func (s *ExpenseService) MileageSettings(ctx context.Context) (*MileageSettings, *Response, error)
MileageSettings returns the account's mileage configuration. The reply is enveloped under mileage_settings, unlike the other expense sub-resources.
type FieldError ¶
FieldError is one validation failure attributed to a specific attribute. Field is empty when the API reported the failure without naming one.
func (FieldError) String ¶
func (f FieldError) String() string
type FileStore ¶
type FileStore struct {
// contains filtered or unexported fields
}
FileStore persists tokens as 0600 JSON. One file holds one entry per environment, so sandbox and production credentials coexist without the caller juggling paths.
func NewFileStore ¶
NewFileStore stores tokens for one environment at path. Pass the environment name as key.
type FilingPayment ¶
type FilingPayment struct {
Label string `json:"label,omitempty"`
DueOn Date `json:"due_on,omitzero"`
AmountDue *Decimal `json:"amount_due,omitempty"`
// Status is unpaid or marked_as_paid, and is omitted entirely when the
// amount due is zero or negative.
Status string `json:"status,omitempty"`
}
FilingPayment is one payment due against a filing period.
type FinalAccountsReport ¶
type FinalAccountsReport struct {
// URL ends in the period end date rather than a numeric id, so
// ResourceURL.ID does not apply to it. Use PeriodEndsOn.
URL ResourceURL `json:"url,omitempty"`
PeriodStartsOn Date `json:"period_starts_on,omitzero"`
PeriodEndsOn Date `json:"period_ends_on,omitzero"`
FilingDueOn Date `json:"filing_due_on,omitzero"`
// FilingStatus is draft, unfiled, pending, rejected, filed or
// marked_as_filed.
FilingStatus string `json:"filing_status,omitempty"`
FiledAt Time `json:"filed_at,omitzero"`
FiledReference string `json:"filed_reference,omitempty"`
}
FinalAccountsReport is one accounting period's end-of-year filing state.
type FinalAccountsReportService ¶
type FinalAccountsReportService struct {
// contains filtered or unexported fields
}
FinalAccountsReportService covers https://dev.freeagent.com/docs/final_accounts_reports
Reports are addressed by the period end date, not a numeric id, which is the shape it shares with the VAT, corporation tax and income tax families.
func (*FinalAccountsReportService) Get ¶
func (s *FinalAccountsReportService) Get(ctx context.Context, periodEndsOn Date) (*FinalAccountsReport, *Response, error)
Get fetches one period's report by its end date.
func (*FinalAccountsReportService) List ¶
func (s *FinalAccountsReportService) List(ctx context.Context) ([]FinalAccountsReport, *Response, error)
List returns every accounting period's report.
func (*FinalAccountsReportService) MarkAsFiled ¶
func (s *FinalAccountsReportService) MarkAsFiled(ctx context.Context, periodEndsOn Date) (*FinalAccountsReport, *Response, error)
MarkAsFiled records the period as filed outside FreeAgent. It needs Full Access, or Account Manager on a practice-managed account.
func (*FinalAccountsReportService) MarkAsUnfiled ¶
func (s *FinalAccountsReportService) MarkAsUnfiled(ctx context.Context, periodEndsOn Date) (*FinalAccountsReport, *Response, error)
MarkAsUnfiled reverses MarkAsFiled.
func (*FinalAccountsReportService) Meta ¶
func (s *FinalAccountsReportService) Meta() ResourceMeta
Meta returns the resource metadata.
type HirePurchase ¶
type HirePurchase struct {
URL ResourceURL `json:"url,omitempty"`
Description string `json:"description,omitempty"`
Bill ResourceURL `json:"bill,omitempty"`
LiabilitiesOverOneYearCategory ResourceURL `json:"liabilities_over_one_year_category,omitempty"`
LiabilitiesUnderOneYearCategory ResourceURL `json:"liabilities_under_one_year_category,omitempty"`
}
HirePurchase is a bill paid off in instalments.
Every field is read-only: the record is created by flagging a bill as paid by hire purchase, not through this endpoint. UK companies only.
type HirePurchaseService ¶
type HirePurchaseService struct {
ReadCollection[HirePurchase]
}
HirePurchaseService covers https://dev.freeagent.com/docs/hire_purchases
type IncomeTaxReturn ¶
type IncomeTaxReturn struct {
URL ResourceURL `json:"url,omitempty"`
PeriodStartsOn Date `json:"period_starts_on,omitzero"`
PeriodEndsOn Date `json:"period_ends_on,omitzero"`
FilingDueOn Date `json:"filing_due_on,omitzero"`
// FilingStatus is unfiled, pending, rejected, provisionally_filed, filed
// or marked_as_filed. provisionally_filed is unique to this family.
FilingStatus string `json:"filing_status,omitempty"`
FiledAt Time `json:"filed_at,omitzero"`
FiledReference string `json:"filed_reference,omitempty"`
Payments []FilingPayment `json:"payments,omitempty"`
}
IncomeTaxReturn is one self assessment period for a user.
The documentation has two pages for this, Self Assessment Returns and Income Tax Returns; the former redirects to the latter and they are the same resource. Neither /v2/self_assessment_returns nor /v2/income_tax_returns exists: the collection is nested under a user.
type IncomeTaxReturnService ¶
type IncomeTaxReturnService struct {
// contains filtered or unexported fields
}
IncomeTaxReturnService covers https://dev.freeagent.com/docs/income_tax_returns
Every call is scoped to a user, so each method takes the user's URL.
func (*IncomeTaxReturnService) GetForUser ¶
func (s *IncomeTaxReturnService) GetForUser(ctx context.Context, user ResourceURL, periodEndsOn Date) (*IncomeTaxReturn, *Response, error)
GetForUser fetches one period for a user.
func (*IncomeTaxReturnService) ListForUser ¶
func (s *IncomeTaxReturnService) ListForUser(ctx context.Context, user ResourceURL) ([]IncomeTaxReturn, *Response, error)
ListForUser returns every self assessment period for a user.
func (*IncomeTaxReturnService) MarkAsFiled ¶
func (s *IncomeTaxReturnService) MarkAsFiled(ctx context.Context, user ResourceURL, periodEndsOn Date) (*IncomeTaxReturn, *Response, error)
MarkAsFiled records a user's return as filed. Needs Full Access.
func (*IncomeTaxReturnService) MarkAsUnfiled ¶
func (s *IncomeTaxReturnService) MarkAsUnfiled(ctx context.Context, user ResourceURL, periodEndsOn Date) (*IncomeTaxReturn, *Response, error)
MarkAsUnfiled reverses MarkAsFiled.
func (*IncomeTaxReturnService) MarkPaymentAsPaid ¶
func (s *IncomeTaxReturnService) MarkPaymentAsPaid(ctx context.Context, user ResourceURL, periodEndsOn, paymentDate Date) (*IncomeTaxReturn, *Response, error)
MarkPaymentAsPaid records one dated payment as settled.
func (*IncomeTaxReturnService) MarkPaymentAsUnpaid ¶
func (s *IncomeTaxReturnService) MarkPaymentAsUnpaid(ctx context.Context, user ResourceURL, periodEndsOn, paymentDate Date) (*IncomeTaxReturn, *Response, error)
MarkPaymentAsUnpaid reverses MarkPaymentAsPaid.
func (*IncomeTaxReturnService) Meta ¶
func (s *IncomeTaxReturnService) Meta() ResourceMeta
Meta returns the resource metadata.
type Int64 ¶
type Int64 int64
Int64 accepts either a JSON number or a numeric string, and always writes a number. FreeAgent is inconsistent here: the company documentation types id as an integer while the example on the same page returns "12345" quoted.
func (Int64) MarshalJSON ¶
MarshalJSON implements json.Marshaler.
func (*Int64) UnmarshalJSON ¶
UnmarshalJSON implements json.Unmarshaler.
type Invoice ¶
type Invoice struct {
URL ResourceURL `json:"url,omitempty"`
// Contact is required.
Contact ResourceURL `json:"contact,omitempty"`
Project ResourceURL `json:"project,omitempty"`
Property ResourceURL `json:"property,omitempty"`
// BankAccount nominates the account shown for remittance.
BankAccount ResourceURL `json:"bank_account,omitempty"`
// Reference is required; omit it to use the account's invoice sequence.
Reference string `json:"reference,omitempty"`
// DatedOn is required.
DatedOn Date `json:"dated_on,omitzero"`
DueOn Date `json:"due_on,omitzero"`
// PaymentTermsInDays is required; zero means due on receipt.
PaymentTermsInDays *int `json:"payment_terms_in_days,omitempty"`
Currency string `json:"currency,omitempty"`
// Status is one of Draft, Scheduled To Email, Open, Zero Value, Overdue,
// Paid, Overpaid, Refunded, Written-off or Part written-off. It is driven
// by the transitions rather than set directly.
Status string `json:"status,omitempty"`
Comments string `json:"comments,omitempty"`
DiscountPercent *Decimal `json:"discount_percent,omitempty"`
ClientContactName string `json:"client_contact_name,omitempty"`
PaymentTerms string `json:"payment_terms,omitempty"`
POReference string `json:"po_reference,omitempty"`
OmitHeader *bool `json:"omit_header,omitempty"`
ShowProjectName *bool `json:"show_project_name,omitempty"`
AlwaysShowBICAndIBAN *bool `json:"always_show_bic_and_iban,omitempty"`
SendNewInvoiceEmails *bool `json:"send_new_invoice_emails,omitempty"`
SendReminderEmails *bool `json:"send_reminder_emails,omitempty"`
SendThankYouEmails *bool `json:"send_thank_you_emails,omitempty"`
// Roll-up options. Each is either null or one of the documented
// billed_grouped_by_* values.
IncludeTimeslips string `json:"include_timeslips,omitempty"`
IncludeExpenses string `json:"include_expenses,omitempty"`
IncludeEstimates string `json:"include_estimates,omitempty"`
// ECStatus is UK/Non-EC, EC Goods, EC Services, Reverse Charge or
// EC VAT MOSS.
ECStatus string `json:"ec_status,omitempty"`
PlaceOfSupply string `json:"place_of_supply,omitempty"`
// Construction Industry Scheme.
CISRate string `json:"cis_rate,omitempty"`
CISDeductionRate *Decimal `json:"cis_deduction_rate,omitempty"`
CISDeduction *Decimal `json:"cis_deduction,omitempty"`
CISDeductionSuffered *Decimal `json:"cis_deduction_suffered,omitempty"`
InvoiceItems []InvoiceItem `json:"invoice_items,omitempty"`
// Read-only.
LongStatus string `json:"long_status,omitempty"`
ContactName string `json:"contact_name,omitempty"`
NetValue *Decimal `json:"net_value,omitempty"`
SalesTaxValue *Decimal `json:"sales_tax_value,omitempty"`
SecondSalesTaxValue *Decimal `json:"second_sales_tax_value,omitempty"`
TotalValue *Decimal `json:"total_value,omitempty"`
PaidValue *Decimal `json:"paid_value,omitempty"`
DueValue *Decimal `json:"due_value,omitempty"`
ExchangeRate *Decimal `json:"exchange_rate,omitempty"`
InvolvesSalesTax *bool `json:"involves_sales_tax,omitempty"`
IsInterimUKVAT *bool `json:"is_interim_uk_vat,omitempty"`
PaidOn Date `json:"paid_on,omitzero"`
WrittenOffDate Date `json:"written_off_date,omitzero"`
RecurringInvoice ResourceURL `json:"recurring_invoice,omitempty"`
PaymentURL string `json:"payment_url,omitempty"`
PaymentMethods *InvoicePaymentMethods `json:"payment_methods,omitempty"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
Invoice is a sales invoice.
type InvoiceItem ¶
type InvoiceItem struct {
URL ResourceURL `json:"url,omitempty"`
// ID identifies an existing line on a write. Leave it unset to add one.
ID *int64 `json:"id,omitempty"`
// Destroy set to 1 removes the line on a write.
Destroy *int `json:"_destroy,omitempty"`
// Position is read-only and starts at 1.
Position *Decimal `json:"position,omitempty"`
// ItemType is Hours, Days, Weeks, Months, Years, Products, Services,
// Training, Expenses, Comment, Bills, Discount, Credit, VAT or Stock.
// Blank means "no unit".
ItemType string `json:"item_type,omitempty"`
Description string `json:"description,omitempty"`
Quantity *Decimal `json:"quantity,omitempty"`
Price *Decimal `json:"price,omitempty"`
SalesTaxRate *Decimal `json:"sales_tax_rate,omitempty"`
SalesTaxStatus string `json:"sales_tax_status,omitempty"`
SecondSalesTaxRate *Decimal `json:"second_sales_tax_rate,omitempty"`
SecondSalesTaxStatus string `json:"second_sales_tax_status,omitempty"`
Category ResourceURL `json:"category,omitempty"`
Project ResourceURL `json:"project,omitempty"`
StockItem ResourceURL `json:"stock_item,omitempty"`
}
InvoiceItem is one line on an invoice.
type InvoicePaymentMethods ¶
type InvoicePaymentMethods struct {
PayPal bool `json:"paypal,omitempty"`
GoCardlessPreauth bool `json:"gocardless_preauth,omitempty"`
GoCardlessInstantBankPay bool `json:"gocardless_instant_bank_pay,omitempty"`
Stripe bool `json:"stripe,omitempty"`
Tyl bool `json:"tyl,omitempty"`
}
InvoicePaymentMethods reports which online payment routes are enabled. All fields are read-only and depend on the integrations configured.
type InvoiceService ¶
type InvoiceService struct {
Collection[Invoice]
}
InvoiceService covers https://dev.freeagent.com/docs/invoices
func (*InvoiceService) ConvertToCreditNote ¶
func (s *InvoiceService) ConvertToCreditNote(ctx context.Context, id int64) (*Invoice, *Response, error)
ConvertToCreditNote turns a draft invoice with a negative total into a credit note.
func (*InvoiceService) MarkAsCancelled ¶
func (s *InvoiceService) MarkAsCancelled(ctx context.Context, id int64) (*Invoice, *Response, error)
MarkAsCancelled cancels the invoice.
func (*InvoiceService) MarkAsDraft ¶
MarkAsDraft returns the invoice to draft.
func (*InvoiceService) MarkAsScheduled ¶
func (s *InvoiceService) MarkAsScheduled(ctx context.Context, id int64) (*Invoice, *Response, error)
MarkAsScheduled schedules the invoice to be emailed.
func (*InvoiceService) MarkAsSent ¶
MarkAsSent moves a draft invoice to sent, or reopens a cancelled one.
func (*InvoiceService) SendEmail ¶
func (s *InvoiceService) SendEmail(ctx context.Context, id int64, opts *EmailOptions) (*Response, error)
SendEmail emails the invoice. Pass nil to use the account's template.
type JournalEntry ¶
type JournalEntry struct {
URL ResourceURL `json:"url,omitempty"`
// Destroy removes the entry on an update.
Destroy *bool `json:"_destroy,omitempty"`
// Category and DebitValue are required.
Category ResourceURL `json:"category,omitempty"`
DebitValue *Decimal `json:"debit_value,omitempty"`
Description string `json:"description,omitempty"`
// Each of these applies only to the matching category range.
CapitalAssetType ResourceURL `json:"capital_asset_type,omitempty"`
User ResourceURL `json:"user,omitempty"`
StockItem ResourceURL `json:"stock_item,omitempty"`
StockAlteringQuantity *int `json:"stock_altering_quantity,omitempty"`
BankAccount ResourceURL `json:"bank_account,omitempty"`
Property ResourceURL `json:"property,omitempty"`
Contact ResourceURL `json:"contact,omitempty"`
}
JournalEntry is one side of a journal set. A negative DebitValue is a credit, and a set must balance to zero.
type JournalSet ¶
type JournalSet struct {
URL ResourceURL `json:"url,omitempty"`
// DatedOn and Description are required, except on the opening balances
// set which has no date.
DatedOn Date `json:"dated_on,omitzero"`
Description string `json:"description,omitempty"`
// Tag marks sets created by your integration. Tagged sets are read-only
// in the FreeAgent interface, which stops a user editing them out from
// under you.
Tag string `json:"tag,omitempty"`
JournalEntries []JournalEntry `json:"journal_entries,omitempty"`
// Read-only, and present on the opening balances set only. The
// documentation types both as bare arrays; they are arrays of objects
// carrying their own value, not lists of references.
BankAccounts []JournalSetBalance `json:"bank_accounts,omitempty"`
StockItems []JournalSetBalance `json:"stock_items,omitempty"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
JournalSet is a balanced set of double-entry journal entries.
type JournalSetBalance ¶
type JournalSetBalance struct {
URL ResourceURL `json:"url,omitempty"`
Description string `json:"description,omitempty"`
DebitValue *Decimal `json:"debit_value,omitempty"`
}
JournalSetBalance is one opening-balance line for a bank account or a stock item, as carried on the opening balances journal set.
type JournalSetService ¶
type JournalSetService struct {
Collection[JournalSet]
}
JournalSetService covers https://dev.freeagent.com/docs/journal_sets
func (*JournalSetService) OpeningBalances ¶
func (s *JournalSetService) OpeningBalances(ctx context.Context) (*JournalSet, *Response, error)
OpeningBalances returns the account's opening balance journal set, which has its own endpoint rather than an id.
It is not an ordinary journal set. It carries no date, and its bank and stock legs live in BankAccounts and StockItems rather than in JournalEntries, so the entries alone do not sum to zero.
type ListOptions ¶
type ListOptions struct {
// Page is 1-based. Zero means the server default (page 1).
Page int
// PerPage defaults to 25 server-side and may not exceed MaxPerPage.
PerPage int
// UpdatedSince filters to records changed at or after this instant. It is
// the basis for incremental reads.
UpdatedSince Time
// Sort is a field name, optionally prefixed with "-" for descending, for
// example "-updated_at".
Sort string
// View selects a server-side named filter such as "open_or_overdue".
View string
// FromDate and ToDate bound date-ranged collections such as bank
// transactions.
FromDate Date
ToDate Date
// Extra is merged last and wins on key collisions.
Extra url.Values
}
ListOptions carries the filters shared by the collection endpoints. Not every resource honours every field; the API ignores what it does not know, and Extra is the escape hatch for resource-specific parameters.
Example ¶
ListOptions renders the filters an incremental read depends on.
package main
import (
"fmt"
"log"
"time"
"github.com/alekc/freeagent-sdk/freeagent"
)
func main() {
cursor := time.Date(2026, time.August, 1, 9, 30, 0, 0, time.UTC)
opts := &freeagent.ListOptions{
UpdatedSince: freeagent.TimeOf(cursor),
Sort: "updated_at",
PerPage: freeagent.MaxPerPage,
}
values, err := opts.Values()
if err != nil {
log.Fatal(err)
}
fmt.Println(values.Encode())
}
Output: per_page=100&sort=updated_at&updated_since=2026-08-01T09%3A30%3A00.000Z
type MemoryStore ¶
type MemoryStore struct {
// contains filtered or unexported fields
}
MemoryStore keeps a token for the life of the process. Useful in tests and for short-lived jobs that receive a token by other means.
func NewMemoryStore ¶
func NewMemoryStore(token *oauth2.Token) *MemoryStore
NewMemoryStore seeds a store, optionally with an existing token.
type MileagePeriod ¶
type MileagePeriod[T any] struct { From Date `json:"from,omitzero"` To Date `json:"to,omitzero"` Value T `json:"value,omitempty"` }
MileagePeriod is one dated slice of a mileage setting.
func (MileagePeriod[T]) RatesFor ¶
func (p MileagePeriod[T]) RatesFor(vehicleType string) (MileageRate, bool)
RatesFor decodes the per-vehicle rates in a period, skipping the basic_rate_limit sibling that shares the object.
type MileageRate ¶
type MileageRate struct {
BasicRate *Decimal `json:"basic_rate,omitempty"`
AdditionalRate *Decimal `json:"additional_rate,omitempty"`
}
MileageRate is the rate pair for one vehicle type inside a MileageRates period. Decode a member of the period's Value into it; the sibling basic_rate_limit key is a number, not a rate, so it will not fit.
type MileageSettings ¶
type MileageSettings struct {
// EngineTypeAndSizeOptions maps an engine type such as "Petrol" to the
// engine sizes valid in that period.
EngineTypeAndSizeOptions []MileagePeriod[map[string][]string] `json:"engine_type_and_size_options,omitempty"`
// MileageRates maps a vehicle type such as "Car" to its rates. The same
// object also carries a basic_rate_limit, which is why the value is
// decoded loosely rather than as a fixed struct.
MileageRates []MileagePeriod[map[string]json.RawMessage] `json:"mileage_rates,omitempty"`
}
MileageSettings reports the account's mileage configuration.
Both members are historical: each entry covers a date range, because HMRC rates and the engine-size bands have changed over time. Pick the entry whose range contains the expense date rather than assuming the last one applies.
type Note ¶
type Note struct {
URL ResourceURL `json:"url,omitempty"`
// Note is the content, and is required.
Note string `json:"note,omitempty"`
// Read-only. ParentURL points at the contact or project the note hangs
// off; the parent is chosen with a query parameter on create, not by
// setting this field.
ParentURL ResourceURL `json:"parent_url,omitempty"`
Author string `json:"author,omitempty"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
Note is a free-text note attached to a contact or a project.
type NoteService ¶
type NoteService struct {
Collection[Note]
}
NoteService covers https://dev.freeagent.com/docs/notes
Notes are always scoped to a parent. Listing without one is a 400, and creating without one has nowhere to attach, so the inherited List, All and Create are shadowed in favour of the parent-taking forms.
func (*NoteService) All ¶
func (s *NoteService) All(context.Context, *ListOptions) iter.Seq2[Note, error]
All is unavailable without a parent. Use AllForParent.
func (*NoteService) AllForParent ¶
func (s *NoteService) AllForParent(ctx context.Context, parent ResourceURL, opts *ListOptions) iter.Seq2[Note, error]
AllForParent iterates every note on one contact or project.
func (*NoteService) CreateForParent ¶
func (s *NoteService) CreateForParent(ctx context.Context, parent ResourceURL, in *Note) (*Note, *Response, error)
CreateForParent adds a note to one contact or project.
func (*NoteService) List ¶
func (s *NoteService) List(context.Context, *ListOptions) ([]Note, *Response, error)
List is unavailable without a parent. Use ListForParent.
func (*NoteService) ListForParent ¶
func (s *NoteService) ListForParent(ctx context.Context, parent ResourceURL, opts *ListOptions) ([]Note, *Response, error)
ListForParent fetches the notes on one contact or project.
type Option ¶
Option configures a Client.
func WithAPIVersion ¶
WithAPIVersion overrides the X-Api-Version header. The value is a date such as "2024-10-01"; the API serves the newest version at or before it.
func WithBaseURL ¶
WithBaseURL overrides the API endpoint. A trailing slash is added when missing so relative resource paths resolve correctly.
func WithHTTPClient ¶
WithHTTPClient supplies the underlying transport.
func WithMaxResponseBytes ¶
WithMaxResponseBytes overrides the response body cap.
func WithRateLimitTest ¶
WithRateLimitTest sends X-RateLimit-Test, which lowers the sandbox budget to 5 requests per minute so back-off handling can be exercised for real.
func WithRateLimits ¶
WithRateLimits sets the client-side request budgets. Zero disables the corresponding limiter.
func WithReadOnly ¶
func WithReadOnly() Option
WithReadOnly refuses every mutating request before it is built, returning ErrReadOnly instead. Only GET, HEAD and OPTIONS are allowed through.
This exists for pointing a client at an account whose data must not be touched. It is a structural guarantee rather than a matter of discipline: no typed service, no transition, no Raw call can write through a read-only client, because the check sits in request construction rather than in each caller.
func WithRetryPolicy ¶
func WithRetryPolicy(p RetryPolicy) Option
WithRetryPolicy overrides the retry behaviour.
func WithSandbox ¶
func WithSandbox() Option
WithSandbox points the client at the sandbox environment.
func WithTokenSource ¶
func WithTokenSource(ts oauth2.TokenSource) Option
WithTokenSource supplies OAuth credentials. Use TokenSource for a source that refreshes and persists rotated refresh tokens.
func WithUserAgent ¶
WithUserAgent replaces the default user agent.
func WithoutAuth ¶
func WithoutAuth() Option
WithoutAuth builds a client that sends no Authorization header. It exists for tests and for talking to a local fake; real endpoints will reject it.
func WithoutRateLimit ¶
func WithoutRateLimit() Option
WithoutRateLimit removes client-side throttling. The server limits still apply, so the retry path becomes the only protection.
type PDF ¶
type PDF struct {
Content string `json:"content"`
}
PDF is a rendered document. FreeAgent returns the file base64 encoded in a JSON envelope rather than as an octet stream.
type PayrollPeriod ¶
type PayrollPeriod struct {
URL ResourceURL `json:"url,omitempty"`
Period *int `json:"period,omitempty"`
Frequency string `json:"frequency,omitempty"`
DatedOn Date `json:"dated_on,omitzero"`
// Status is unfiled, pending, rejected, partially_filed or filed.
Status string `json:"status,omitempty"`
EmploymentAllowanceClaimed *bool `json:"employment_allowance_claimed,omitempty"`
EmploymentAllowanceAmount *Decimal `json:"employment_allowance_amount,omitempty"`
ConstructionIndustrySchemeDeduction *Decimal `json:"construction_industry_scheme_deduction,omitempty"`
// Payslips is populated when a single period is fetched, and absent from
// the year listing.
Payslips []Payslip `json:"payslips,omitempty"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
PayrollPeriod is one pay run in a tax year. Every field is read-only: payroll is filed through the FreeAgent interface, not the API.
type PayrollProfile ¶
type PayrollProfile struct {
User ResourceURL `json:"user,omitempty"`
PayrollReference string `json:"payroll_reference,omitempty"`
Title string `json:"title,omitempty"`
Gender string `json:"gender,omitempty"`
DateOfBirth Date `json:"date_of_birth,omitzero"`
// The address lines are numbered rather than named here, unlike the
// address1..address3 used everywhere else in the API.
AddressLine1 string `json:"address_line_1,omitempty"`
AddressLine2 string `json:"address_line_2,omitempty"`
AddressLine3 string `json:"address_line_3,omitempty"`
AddressLine4 string `json:"address_line_4,omitempty"`
Postcode string `json:"postcode,omitempty"`
Country string `json:"country,omitempty"`
TotalPayInPreviousEmployment *Decimal `json:"total_pay_in_previous_employment,omitempty"`
TotalTaxInPreviousEmployment *Decimal `json:"total_tax_in_previous_employment,omitempty"`
EmploymentStartsOn Date `json:"employment_starts_on,omitzero"`
EmploymentEndsOn Date `json:"employment_ends_on,omitzero"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
PayrollProfile is an employee's payroll details for a tax year.
type PayrollProfileService ¶
type PayrollProfileService struct {
// contains filtered or unexported fields
}
PayrollProfileService covers https://dev.freeagent.com/docs/payroll_profiles
Like payroll, addressed by tax year: /v2/payroll_profiles alone is a 404.
func (*PayrollProfileService) Meta ¶
func (s *PayrollProfileService) Meta() ResourceMeta
Meta returns the resource metadata.
func (*PayrollProfileService) Year ¶
func (s *PayrollProfileService) Year(ctx context.Context, year int, user ResourceURL) ([]PayrollProfile, *Response, error)
Year lists every profile for a tax year. Pass a user URL to narrow it to one employee, or the zero value for all of them.
type PayrollService ¶
type PayrollService struct {
// contains filtered or unexported fields
}
PayrollService covers https://dev.freeagent.com/docs/payroll
Payroll is addressed by tax year rather than by id, and there is no collection at /v2/payroll: the year is part of the path. UK companies with payroll only.
func (*PayrollService) MarkPaymentAsPaid ¶
func (s *PayrollService) MarkPaymentAsPaid(ctx context.Context, year int, paymentDate Date) (*Response, error)
MarkPaymentAsPaid records an HMRC payment for the year as settled.
The documentation lists the unpaid variant as a GET, which is a typo: both are PUT, matching every other mark_as_* transition in the API.
func (*PayrollService) MarkPaymentAsUnpaid ¶
func (s *PayrollService) MarkPaymentAsUnpaid(ctx context.Context, year int, paymentDate Date) (*Response, error)
MarkPaymentAsUnpaid reverses MarkPaymentAsPaid.
func (*PayrollService) Meta ¶
func (s *PayrollService) Meta() ResourceMeta
Meta returns the resource metadata.
func (*PayrollService) Payslips ¶
func (s *PayrollService) Payslips(ctx context.Context, year, period int) ([]Payslip, *Response, error)
Payslips returns just the payslips in one period.
func (*PayrollService) Period ¶
func (s *PayrollService) Period(ctx context.Context, year, period int) (*PayrollPeriod, *Response, error)
Period fetches one period of a tax year, including its payslips.
The reply is enveloped under "period" and carries the payslips nested inside it, not under a top-level "payslips" key as the documentation's wording suggests.
func (*PayrollService) Year ¶
func (s *PayrollService) Year(ctx context.Context, year int) (*PayrollYear, *Response, error)
Year lists the periods and HMRC payments for one tax year.
type PayrollYear ¶
type PayrollYear struct {
Periods []PayrollPeriod `json:"periods,omitempty"`
Payments []FilingPayment `json:"payments,omitempty"`
}
PayrollYear is what a year's payroll listing returns: its periods and the payments due to HMRC.
type Payslip ¶
type Payslip struct {
User ResourceURL `json:"user,omitempty"`
DatedOn Date `json:"dated_on,omitzero"`
TaxCode string `json:"tax_code,omitempty"`
NILetter string `json:"ni_letter,omitempty"`
Frequency string `json:"frequency,omitempty"`
// NICalcType is the National Insurance calculation basis.
NICalcType string `json:"ni_calc_type,omitempty"`
BasicPay *Decimal `json:"basic_pay,omitempty"`
Overtime *Decimal `json:"overtime,omitempty"`
Commission *Decimal `json:"commission,omitempty"`
Bonus *Decimal `json:"bonus,omitempty"`
Allowance *Decimal `json:"allowance,omitempty"`
HoursWorked *Decimal `json:"hours_worked,omitempty"`
TaxDeducted *Decimal `json:"tax_deducted,omitempty"`
EmployeeNI *Decimal `json:"employee_ni,omitempty"`
EmployerNI *Decimal `json:"employer_ni,omitempty"`
// Statutory payments.
StatutorySickPay *Decimal `json:"statutory_sick_pay,omitempty"`
StatutoryMaternityPay *Decimal `json:"statutory_maternity_pay,omitempty"`
StatutoryPaternityPay *Decimal `json:"statutory_paternity_pay,omitempty"`
AdditionalStatutoryPaternityPay *Decimal `json:"additional_statutory_paternity_pay,omitempty"`
StatutoryAdoptionPay *Decimal `json:"statutory_adoption_pay,omitempty"`
StatutoryParentalBereavementPay *Decimal `json:"statutory_parental_bereavement_pay,omitempty"`
// Undocumented, but sent by the live API: Northern Ireland has its own
// parental bereavement figure.
StatutoryParentalBereavementPayNIreland *Decimal `json:"statutory_parental_bereavement_pay_n_ireland,omitempty"`
StatutoryNeonatalCarePay *Decimal `json:"statutory_neonatal_care_pay,omitempty"`
AbsencePayments *Decimal `json:"absence_payments,omitempty"`
OtherPayments *Decimal `json:"other_payments,omitempty"`
// Pensions and salary sacrifice.
EmployeePension *Decimal `json:"employee_pension,omitempty"`
EmployerPension *Decimal `json:"employer_pension,omitempty"`
EmployeePensionNotUnderNetPay *Decimal `json:"employee_pension_not_under_net_pay,omitempty"`
EmployeePensionSalarySacrifice *Decimal `json:"employee_pension_salary_sacrifice,omitempty"`
OtherSalarySacrificeDeductions *Decimal `json:"other_salary_sacrifice_deductions,omitempty"`
// Deductions.
OtherDeductions *Decimal `json:"other_deductions,omitempty"`
OtherDeductionsFromNetPay *Decimal `json:"other_deductions_from_net_pay,omitempty"`
DeductionsSubjectToNICButNotPAYE *Decimal `json:"deductions_subject_to_nic_but_not_paye,omitempty"`
DeductionFreePay *Decimal `json:"deduction_free_pay,omitempty"`
Attachments *Decimal `json:"attachments,omitempty"`
PayrollGiving *Decimal `json:"payroll_giving,omitempty"`
// Student and postgraduate loans.
StudentLoanDeduction *Decimal `json:"student_loan_deduction,omitempty"`
DeductStudentLoan *bool `json:"deduct_student_loan,omitempty"`
StudentLoanDeductionPlan string `json:"student_loan_deductions_plan,omitempty"`
PostgradLoanDeduction *Decimal `json:"postgrad_loan_deduction,omitempty"`
DeductPostgradLoan *bool `json:"deduct_postgrad_loan,omitempty"`
Week1Month1Basis *bool `json:"week_1_month_1_basis,omitempty"`
LeavingPayslip *bool `json:"leaving_payslip,omitempty"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
Payslip is one employee's pay for one period. Every field is read-only.
The field list is long because RTI reporting is: statutory payments, pension arrangements and loan plans each need their own line.
type PriceListItem ¶
type PriceListItem struct {
URL ResourceURL `json:"url,omitempty"`
// Code, Quantity, ItemType and Description are all required.
Code string `json:"code,omitempty"`
// ItemType is Hours, Days, Weeks, Months, Years, Products, Services,
// Training, Expenses, Comment, Bills, Discount, Credit, VAT or Stock.
ItemType string `json:"item_type,omitempty"`
Description string `json:"description,omitempty"`
Quantity *Decimal `json:"quantity,omitempty"`
Price *Decimal `json:"price,omitempty"`
// VATStatus is UK only: out_of_scope (the default), reduced, standard or
// zero. Universal and US accounts use the sales tax rates instead.
VATStatus string `json:"vat_status,omitempty"`
SalesTaxRate *Decimal `json:"sales_tax_rate,omitempty"`
SecondSalesTaxRate *Decimal `json:"second_sales_tax_rate,omitempty"`
Category ResourceURL `json:"category,omitempty"`
// StockItem is required when ItemType is Stock.
StockItem ResourceURL `json:"stock_item,omitempty"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
PriceListItem is a saved line that can be dropped onto an invoice or estimate.
type PriceListItemService ¶
type PriceListItemService struct {
Collection[PriceListItem]
}
PriceListItemService covers https://dev.freeagent.com/docs/price_list_items
type ProfitAndLoss ¶
type ProfitAndLoss struct {
From Date `json:"from,omitzero"`
To Date `json:"to,omitzero"`
Income *Decimal `json:"income,omitempty"`
Expenses *Decimal `json:"expenses,omitempty"`
OperatingProfit *Decimal `json:"operating_profit,omitempty"`
Less []ProfitAndLossRow `json:"less,omitempty"`
RetainedProfit *Decimal `json:"retained_profit,omitempty"`
RetainedProfitBroughtForward *Decimal `json:"retained_profit_brought_forward,omitempty"`
RetainedProfitCarriedForward *Decimal `json:"retained_profit_carried_forward,omitempty"`
}
ProfitAndLoss is the profit and loss summary.
Its money values arrive as quoted strings, unlike BalanceSheet and Cashflow which send bare numbers. Decimal accepts both, so the inconsistency does not reach callers.
type ProfitAndLossRow ¶
type ProfitAndLossRow struct {
Title string `json:"title,omitempty"`
Total *Decimal `json:"total,omitempty"`
}
ProfitAndLossRow is one deduction line under "less".
type Project ¶
type Project struct {
URL ResourceURL `json:"url,omitempty"`
// Contact is required and references the contact to bill.
Contact ResourceURL `json:"contact,omitempty"`
Name string `json:"name,omitempty"`
// Status is Active, Completed, Cancelled or Hidden.
Status string `json:"status,omitempty"`
ContractPOReference string `json:"contract_po_reference,omitempty"`
Currency string `json:"currency,omitempty"`
// Budget is required; send zero when the project has no budget.
Budget *Decimal `json:"budget,omitempty"`
// BudgetUnits is Hours, Days or Monetary.
BudgetUnits string `json:"budget_units,omitempty"`
HoursPerDay *Decimal `json:"hours_per_day,omitempty"`
NormalBillingRate *Decimal `json:"normal_billing_rate,omitempty"`
// BillingPeriod is hour or day.
BillingPeriod string `json:"billing_period,omitempty"`
UsesProjectInvoiceSequence *bool `json:"uses_project_invoice_sequence,omitempty"`
IncludeUnbilledTimeInProfitability *bool `json:"include_unbilled_time_in_profitability,omitempty"`
IsIR35 *bool `json:"is_ir35,omitempty"`
StartsOn Date `json:"starts_on,omitzero"`
EndsOn Date `json:"ends_on,omitzero"`
// Read-only. ContactName is a display convenience the API adds to
// responses; it is not accepted on write.
ContactName string `json:"contact_name,omitempty"`
IsDeletable *bool `json:"is_deletable,omitempty"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
Project is a body of work billed to a contact.
type ProjectService ¶
type ProjectService struct {
Collection[Project]
}
ProjectService covers https://dev.freeagent.com/docs/projects
type Property ¶
type Property struct {
URL ResourceURL `json:"url,omitempty"`
// Name is absent from the documented attribute list but present in its
// example response.
Name string `json:"name,omitempty"`
Address1 string `json:"address1,omitempty"`
Address2 string `json:"address2,omitempty"`
Address3 string `json:"address3,omitempty"`
Town string `json:"town,omitempty"`
Region string `json:"region,omitempty"`
Postcode string `json:"postcode,omitempty"`
// Country defaults to United Kingdom and cannot be overridden.
Country string `json:"country,omitempty"`
}
Property is a rental property. Only UkUnincorporatedLandlord companies can hold them; on any other company type the collection is simply empty.
type PropertyService ¶
type PropertyService struct {
Collection[Property]
}
PropertyService covers https://dev.freeagent.com/docs/properties
type RateLimit ¶
RateLimit reports the server's own accounting, when it sends it. FreeAgent documents only Retry-After, so these fields are best effort and a zero value means the response carried no such header.
type ReadCollection ¶
type ReadCollection[T any] struct { // contains filtered or unexported fields }
ReadCollection is the read surface of a collection endpoint. Some families are genuinely read-only per record (bank transactions arrive by statement upload or feed, not by POST), so they embed this rather than Collection and the type system rules out the writes the API does not offer.
func (*ReadCollection[T]) All ¶
func (c *ReadCollection[T]) All(ctx context.Context, opts *ListOptions) iter.Seq2[T, error]
All iterates the entire collection, following pagination. Iteration stops on the first error, which is yielded alongside the zero value; breaking out of the range loop stops it cleanly without further requests.
func (*ReadCollection[T]) GetURL ¶
func (c *ReadCollection[T]) GetURL(ctx context.Context, ref ResourceURL) (*T, *Response, error)
GetURL fetches the record a payload reference points at. The URL must be on the client's own host: references come from API responses, so following one blindly would let an upstream response redirect the client elsewhere.
func (*ReadCollection[T]) List ¶
func (c *ReadCollection[T]) List(ctx context.Context, opts *ListOptions) ([]T, *Response, error)
List fetches one page. Callers that want the whole collection should use All, which walks the Link header for them.
func (*ReadCollection[T]) Meta ¶
func (c *ReadCollection[T]) Meta() ResourceMeta
Meta returns the resource metadata backing this collection.
type Reader ¶
type Reader[T any] struct { // contains filtered or unexported fields }
Reader is the read-only surface for singletons and reports, which have no id segment and no write verbs.
func (*Reader[T]) Get ¶
Get fetches the resource. params carries endpoint-specific filters such as from_date and to_date on the accounting reports.
func (*Reader[T]) Meta ¶
func (r *Reader[T]) Meta() ResourceMeta
Meta returns the resource metadata backing this reader.
type RecurringInvoice ¶
type RecurringInvoice struct {
URL ResourceURL `json:"url,omitempty"`
Contact ResourceURL `json:"contact,omitempty"`
ContactName string `json:"contact_name,omitempty"`
Reference string `json:"reference,omitempty"`
DatedOn Date `json:"dated_on,omitzero"`
// Frequency is Weekly, Two Weekly, Four Weekly, Monthly, Two Monthly,
// Quarterly, Biannually, Annually or 2-Yearly.
Frequency string `json:"frequency,omitempty"`
// NextRecursOn is when the next invoice will be raised.
NextRecursOn Date `json:"next_recurs_on,omitzero"`
// RecurringEndDate is blank when the schedule runs forever.
RecurringEndDate Date `json:"recurring_end_date,omitzero"`
// RecurringStatus is Draft or Active.
RecurringStatus string `json:"recurring_status,omitempty"`
Currency string `json:"currency,omitempty"`
ExchangeRate *Decimal `json:"exchange_rate,omitempty"`
NetValue *Decimal `json:"net_value,omitempty"`
SalesTaxValue *Decimal `json:"sales_tax_value,omitempty"`
TotalValue *Decimal `json:"total_value,omitempty"`
PaymentTermsInDays *int `json:"payment_terms_in_days,omitempty"`
OmitHeader *bool `json:"omit_header,omitempty"`
AlwaysShowBICAndIBAN *bool `json:"always_show_bic_and_iban,omitempty"`
InvoiceItems []InvoiceItem `json:"invoice_items,omitempty"`
PaymentMethods *InvoicePaymentMethods `json:"payment_methods,omitempty"`
}
RecurringInvoice is a template that generates invoices on a schedule.
The API exposes reads only: creating and editing one is done in the FreeAgent interface, which is why this family embeds ReadCollection.
type RecurringInvoiceService ¶
type RecurringInvoiceService struct {
ReadCollection[RecurringInvoice]
}
RecurringInvoiceService covers https://dev.freeagent.com/docs/recurring_invoices
type ReportOptions ¶
type ReportOptions struct {
FromDate Date
ToDate Date
// AccountingPeriod selects a named period instead of a date range, for
// the reports that support it.
AccountingPeriod string
// Extra carries anything not modelled here.
Extra url.Values
}
ReportOptions bounds an accounting report. Most reports accept a date range; some also accept an accounting period reference instead.
Leaving everything unset asks for the report's own default, which is generally the current accounting year to date.
type ReportService ¶
type ReportService struct {
// contains filtered or unexported fields
}
ReportService covers the accounting reports. They are read-only, have no id segment, and each has its own response shape, so they are gathered here rather than forced through the collection generics.
func (*ReportService) BalanceSheet ¶
func (s *ReportService) BalanceSheet(ctx context.Context, opts *ReportOptions) (*BalanceSheet, *Response, error)
BalanceSheet returns the balance sheet.
func (*ReportService) Cashflow ¶
Cashflow returns money in and out between two dates. Both are required.
Note the path: this one sits at the API root, not under accounting/.
func (*ReportService) ProfitAndLoss ¶
func (s *ReportService) ProfitAndLoss(ctx context.Context, opts *ReportOptions) (*ProfitAndLoss, *Response, error)
ProfitAndLoss returns the profit and loss summary.
func (*ReportService) TrialBalance ¶
func (s *ReportService) TrialBalance(ctx context.Context, opts *ReportOptions) ([]TrialBalanceEntry, *Response, error)
TrialBalance returns the trial balance summary. Unlike the other reports it answers with an array rather than an object.
type ResourceMeta ¶
type ResourceMeta struct {
// Name is the registry key and the name facli accepts.
Name string
// Path is relative to the API root, for example "invoices" or
// "accounting/profit_and_loss/summary".
Path string
// Singular is the JSON envelope key for a single record. Empty means the
// endpoint returns an unenveloped body.
Singular string
// Plural is the JSON envelope key for a list. Empty for singletons.
Plural string
// Singleton marks endpoints with no id segment, such as company.
Singleton bool
// ReadOnly marks endpoints with no write verbs.
ReadOnly bool
// Grouped marks endpoints whose results are split across several
// envelope keys instead of one plural key. Categories is the only one.
Grouped bool
// NoList marks families with no collection endpoint, such as
// attachments, which are reached only through a parent record.
NoList bool
// RequiresBankAccount marks list endpoints that reject a request without
// a bank_account filter.
RequiresBankAccount bool
// CustomEnvelope marks families whose response uses neither the singular
// nor the plural key, such as payroll, which answers with periods and
// payments. Their services decode the envelope themselves.
CustomEnvelope bool
// Doc is the upstream documentation URL.
Doc string
}
ResourceMeta describes one FreeAgent resource family. The same metadata drives the typed services and the facli generic commands, so a resource is added in exactly one place.
func LookupResource ¶
func LookupResource(name string) (ResourceMeta, bool)
LookupResource returns the metadata registered under name.
type ResourceURL ¶
type ResourceURL string
ResourceURL is how FreeAgent identifies records. Every cross-reference in a payload is a full URL rather than a bare id, so this type carries them and extracts the parts callers actually need.
Example ¶
Payload cross-references are URLs, not ids.
package main
import (
"errors"
"fmt"
"log"
"github.com/alekc/freeagent-sdk/freeagent"
)
func main() {
ref := freeagent.ResourceURL("https://api.freeagent.com/v2/bank_accounts/1")
id, err := ref.ID()
if err != nil {
log.Fatal(err)
}
fmt.Println(id, ref.Kind())
// A singleton is not a collection member, and Kind says so too.
company := freeagent.ResourceURL("https://api.freeagent.com/v2/company")
_, err = company.ID()
fmt.Println(errors.Is(err, freeagent.ErrNotAMember), company.Kind() == "")
}
Output: 1 bank_accounts true true
func (ResourceURL) ID ¶
func (r ResourceURL) ID() (int64, error)
ID returns the numeric identifier of a collection member URL. Singleton URLs such as /v2/company return ErrNotAMember.
func (ResourceURL) IsZero ¶
func (r ResourceURL) IsZero() bool
IsZero reports whether the reference is unset.
func (ResourceURL) Kind ¶
func (r ResourceURL) Kind() string
Kind returns the collection segment of a member URL, for example "invoices" for .../v2/invoices/123. It returns "" when the URL is not a member URL, which makes it safe to use for routing a heterogeneous set of references.
type Response ¶
type Response struct {
*http.Response
// Page numbers extracted from the Link header. Zero means the relation
// was absent, so NextPage == 0 is the end of the collection.
FirstPage int
PrevPage int
NextPage int
LastPage int
// TotalCount comes from X-Total-Count and is -1 when not sent.
TotalCount int
RateLimit RateLimit
}
Response wraps the HTTP response with the pagination and rate-limit state parsed out of its headers.
type RetryPolicy ¶
type RetryPolicy struct {
// MaxAttempts counts the first try. 1 disables retries.
MaxAttempts int
// BaseDelay is the first backoff interval, doubled per attempt.
BaseDelay time.Duration
// MaxDelay caps the computed backoff. It does not cap Retry-After.
MaxDelay time.Duration
// MaxRetryAfter is the longest server-requested wait that is honoured.
// Beyond it the error is returned so the caller decides, rather than the
// client blocking for an unbounded time.
MaxRetryAfter time.Duration
}
RetryPolicy governs automatic retries. Retries apply to 429 on any method, and to transport errors and 5xx on idempotent methods only.
type SalesTaxPeriod ¶
type SalesTaxPeriod struct {
URL ResourceURL `json:"url,omitempty"`
SalesTaxName string `json:"sales_tax_name,omitempty"`
// SalesTaxRegistrationStatus is Registered or Not Registered.
SalesTaxRegistrationStatus string `json:"sales_tax_registration_status,omitempty"`
SalesTaxRegistrationNumber string `json:"sales_tax_registration_number,omitempty"`
SalesTaxIsValueAdded *bool `json:"sales_tax_is_value_added,omitempty"`
SalesTaxRate1 *Decimal `json:"sales_tax_rate_1,omitempty"`
SalesTaxRate2 *Decimal `json:"sales_tax_rate_2,omitempty"`
SalesTaxRate3 *Decimal `json:"sales_tax_rate_3,omitempty"`
// Universal companies only.
SecondSalesTaxName string `json:"second_sales_tax_name,omitempty"`
SecondSalesTaxRate1 *Decimal `json:"second_sales_tax_rate_1,omitempty"`
SecondSalesTaxRate2 *Decimal `json:"second_sales_tax_rate_2,omitempty"`
SecondSalesTaxRate3 *Decimal `json:"second_sales_tax_rate_3,omitempty"`
SecondSalesTaxIsCompound *bool `json:"second_sales_tax_is_compound,omitempty"`
EffectiveDate Date `json:"effective_date,omitzero"`
// Read-only. A locked period cannot be deleted.
IsLocked *bool `json:"is_locked,omitempty"`
LockedReason string `json:"locked_reason,omitempty"`
}
SalesTaxPeriod is a dated set of sales tax rates.
US and Universal companies only: on a UK company the endpoint is a 404. Verifying it needs a sandbox company created with one of those types, which is a free test fixture rather than a real US business.
type SalesTaxPeriodService ¶
type SalesTaxPeriodService struct {
Collection[SalesTaxPeriod]
}
SalesTaxPeriodService covers https://dev.freeagent.com/docs/sales_tax_periods
type SalesTaxService ¶
type SalesTaxService struct {
// contains filtered or unexported fields
}
SalesTaxService covers the one endpoint on https://dev.freeagent.com/docs/sales_tax
That page is mostly prose about how sales tax is expressed on other resources; the EC VAT MOSS rate lookup is the only endpoint it defines.
func (*SalesTaxService) ECMossRates ¶
func (s *SalesTaxService) ECMossRates(ctx context.Context, country string, on Date) (*ECMossRates, *Response, error)
ECMossRates returns the VAT rates for an EU country on a date. Both are required; the country is a name such as "Ireland", not a code.
type StatementLine ¶
type StatementLine struct {
DatedOn Date `json:"dated_on"`
Amount Decimal `json:"amount"`
Description string `json:"description,omitempty"`
// FitID is the bank's own identifier for the row. Supplying it lets
// FreeAgent recognise a re-upload instead of duplicating the line.
FitID string `json:"fitid,omitempty"`
}
StatementLine is one row of a statement upload.
This is deliberately not a BankTransaction: the upload takes a different and much smaller shape, and its amount is a JSON number where every other money value in the API is a quoted string. Posting a BankTransaction here is accepted with a 200 and then silently imports nothing.
func (StatementLine) MarshalJSON ¶
func (l StatementLine) MarshalJSON() ([]byte, error)
MarshalJSON writes amount unquoted. Decimal marshals as a string by design, which is right everywhere else and wrong here.
type StockItem ¶
type StockItem struct {
URL ResourceURL `json:"url,omitempty"`
// Description doubles as the item code shown on invoices and estimates.
Description string `json:"description,omitempty"`
// CostOfSaleCategory is the spending category sales are accounted to.
CostOfSaleCategory ResourceURL `json:"cost_of_sale_category,omitempty"`
// Opening figures are as at the FreeAgent start date.
OpeningQuantity *Decimal `json:"opening_quantity,omitempty"`
OpeningBalance *Decimal `json:"opening_balance,omitempty"`
// StockOnHand is read-only and moves as stock is bought and sold.
StockOnHand *Decimal `json:"stock_on_hand,omitempty"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
StockItem is something the company buys and sells by quantity.
The quantity fields are documented as integers but arrive as quoted decimals ("10.0"), so they are Decimal here.
type StockItemService ¶
type StockItemService struct {
ReadCollection[StockItem]
}
StockItemService covers https://dev.freeagent.com/docs/stock_items
Read-only: the documentation lists only GET endpoints, and POST answers 404 Not Found rather than 405, so stock items are created in the FreeAgent interface or as a side effect of a stock purchase.
type Task ¶
type Task struct {
URL ResourceURL `json:"url,omitempty"`
Project ResourceURL `json:"project,omitempty"`
Name string `json:"name,omitempty"`
Currency string `json:"currency,omitempty"`
// Status is Active, Completed or Hidden.
Status string `json:"status,omitempty"`
IsBillable *bool `json:"is_billable,omitempty"`
// Needs the Contacts and Projects permission. BillingPeriod is day or
// hour.
BillingRate *Decimal `json:"billing_rate,omitempty"`
BillingPeriod string `json:"billing_period,omitempty"`
// Read-only.
IsDeletable *bool `json:"is_deletable,omitempty"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
Task is a unit of work within a project, used to bill timeslips.
type TaskService ¶
type TaskService struct {
Collection[Task]
}
TaskService covers https://dev.freeagent.com/docs/tasks
Creating a task differs from the other collections: the parent project goes in the query string rather than the body, so CreateForProject replaces the inherited Create.
func (*TaskService) Create ¶
Create is not available on tasks: the API takes the parent project as a query parameter, so this shadows the inherited Create rather than letting it silently post a task with no project. Use CreateForProject.
func (*TaskService) CreateForProject ¶
func (s *TaskService) CreateForProject(ctx context.Context, project ResourceURL, in *Task) (*Task, *Response, error)
CreateForProject posts a new task under the given project.
type TaxTimelineItem ¶
type TaxTimelineItem struct {
Description string `json:"description,omitempty"`
Nature string `json:"nature,omitempty"`
DatedOn Date `json:"dated_on,omitzero"`
AmountDue *Decimal `json:"amount_due,omitempty"`
IsPersonal *bool `json:"is_personal,omitempty"`
}
TaxTimelineItem is an upcoming tax event.
type Time ¶
Time is an instant, serialised as ISO 8601 with milliseconds in UTC. The zero value marshals to null.
func (Time) MarshalJSON ¶
MarshalJSON implements json.Marshaler.
func (*Time) UnmarshalJSON ¶
UnmarshalJSON implements json.Unmarshaler.
type Timeslip ¶
type Timeslip struct {
URL ResourceURL `json:"url,omitempty"`
// User, Project, Task and DatedOn are all required.
User ResourceURL `json:"user,omitempty"`
Project ResourceURL `json:"project,omitempty"`
Task ResourceURL `json:"task,omitempty"`
DatedOn Date `json:"dated_on,omitzero"`
// Hours is decimal, so 1:30 is 1.5.
Hours *Decimal `json:"hours,omitempty"`
Comment string `json:"comment,omitempty"`
// Read-only.
BilledOnInvoice ResourceURL `json:"billed_on_invoice,omitempty"`
Timer *TimeslipTimer `json:"timer,omitempty"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
Timeslip is time recorded against a task.
type TimeslipService ¶
type TimeslipService struct {
Collection[Timeslip]
}
TimeslipService covers https://dev.freeagent.com/docs/timeslips
func (*TimeslipService) StartTimer ¶
StartTimer starts the timer on a timeslip.
type TimeslipTimer ¶
type TimeslipTimer struct {
Running *bool `json:"running,omitempty"`
// StartFrom is the effective start, which already accounts for any time
// logged before the timer was started.
StartFrom Time `json:"start_from,omitzero"`
}
TimeslipTimer is present only while a timer is running on the timeslip.
type TokenSource ¶
type TokenSource struct {
// contains filtered or unexported fields
}
TokenSource refreshes access tokens and persists the rotated refresh token. FreeAgent issues a new refresh token on every refresh, so a source that does not write the new one back loses access as soon as the old one is retired. It satisfies oauth2.TokenSource and is safe for concurrent use.
func NewTokenSource ¶
func NewTokenSource(ctx context.Context, cfg *oauth2.Config, store TokenStore) (*TokenSource, error)
NewTokenSource builds a refreshing source over a store. ctx governs the refresh requests and may carry an oauth2.HTTPClient override.
func (*TokenSource) AuthCodeURL ¶
func (s *TokenSource) AuthCodeURL(state string) string
AuthCodeURL builds the URL the user visits to approve the app.
func (*TokenSource) Exchange ¶
Exchange trades an authorisation code for a token and stores it. It is the final step of the interactive login flow.
func (*TokenSource) Peek ¶
func (s *TokenSource) Peek() (*oauth2.Token, error)
Peek returns the cached token without triggering a refresh, loading from the store on first use. Tooling uses it to report expiry.
func (*TokenSource) Token ¶
func (s *TokenSource) Token() (*oauth2.Token, error)
Token returns a valid access token, refreshing and persisting when needed. The lock is deliberately held across the refresh: FreeAgent allows only 15 refreshes per minute, so serialising concurrent callers onto one refresh is the correct behaviour rather than a bottleneck to optimise away.
type TokenStore ¶
type TokenStore interface {
Load(ctx context.Context) (*oauth2.Token, error)
Save(ctx context.Context, token *oauth2.Token) error
}
TokenStore persists OAuth tokens between processes. Load returns ErrNoToken when nothing has been stored yet.
type Transaction ¶
type Transaction struct {
URL ResourceURL `json:"url,omitempty"`
DatedOn Date `json:"dated_on,omitzero"`
Description string `json:"description,omitempty"`
Category ResourceURL `json:"category,omitempty"`
CategoryName string `json:"category_name,omitempty"`
NominalCode string `json:"nominal_code,omitempty"`
// DebitValue is negative for a credit.
DebitValue *Decimal `json:"debit_value,omitempty"`
// SourceItemURL points at whatever produced the entry, such as a bank
// transaction explanation. It may be absent.
SourceItemURL ResourceURL `json:"source_item_url,omitempty"`
// ForeignCurrencyData is an empty object unless foreign currency was
// involved.
ForeignCurrencyData *TransactionForeignCurrency `json:"foreign_currency_data,omitempty"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
Transaction is a posted accounting entry. Transactions are generated by FreeAgent from invoices, bills, explanations and journals, so this family is read-only.
type TransactionForeignCurrency ¶
type TransactionForeignCurrency struct {
CurrencyCode string `json:"currency_code,omitempty"`
DebitValue *Decimal `json:"debit_value,omitempty"`
}
TransactionForeignCurrency carries the original currency amounts.
type TransactionService ¶
type TransactionService struct {
ReadCollection[Transaction]
}
TransactionService covers https://dev.freeagent.com/docs/transactions
Note the path: transactions live under accounting/, not at the API root.
The date range is more constrained than the documented 12-month limit suggests: it must fall inside a single accounting period. A range that starts before the company's first period returns 400 "No accounting period includes the specified dates", so derive the bounds from Company.AnnualAccountingPeriods rather than from today's date.
type TrialBalanceEntry ¶
type TrialBalanceEntry struct {
Category ResourceURL `json:"category,omitempty"`
// NominalCode is the internal code, which for sub-accounts embeds the
// underlying record id, for example "750-47915". DisplayNominalCode is
// the one shown to users, "750-1". They are not interchangeable.
NominalCode string `json:"nominal_code,omitempty"`
DisplayNominalCode string `json:"display_nominal_code,omitempty"`
Name string `json:"name,omitempty"`
Total *Decimal `json:"total,omitempty"`
BankAccount ResourceURL `json:"bank_account,omitempty"`
User ResourceURL `json:"user,omitempty"`
StockItem ResourceURL `json:"stock_item,omitempty"`
}
TrialBalanceEntry is one line of the trial balance.
type User ¶
type User struct {
URL ResourceURL `json:"url,omitempty"`
Email string `json:"email,omitempty"`
FirstName string `json:"first_name,omitempty"`
LastName string `json:"last_name,omitempty"`
// Role is Owner, Director, Partner, Company Secretary, Employee,
// Shareholder or Accountant.
Role string `json:"role,omitempty"`
NINumber string `json:"ni_number,omitempty"`
UniqueTaxReference string `json:"unique_tax_reference,omitempty"`
OpeningMileage *Decimal `json:"opening_mileage,omitempty"`
// PermissionLevel is 0 to 8; see the access levels in the API docs.
PermissionLevel *int `json:"permission_level,omitempty"`
// SendInvitation asks FreeAgent to email a password invitation. Write-only.
SendInvitation *bool `json:"send_invitation,omitempty"`
// Hidden is undocumented but returned by the live API.
Hidden *bool `json:"hidden,omitempty"`
// Read-only.
CurrentPayrollProfile *UserPayrollProfile `json:"current_payroll_profile,omitempty"`
CreatedAt Time `json:"created_at,omitzero"`
UpdatedAt Time `json:"updated_at,omitzero"`
}
User is a person with access to the FreeAgent account.
type UserPayrollProfile ¶
type UserPayrollProfile struct {
TotalPayInPreviousEmployment *Decimal `json:"total_pay_in_previous_employment,omitempty"`
TotalTaxInPreviousEmployment *Decimal `json:"total_tax_in_previous_employment,omitempty"`
}
UserPayrollProfile is the read-only payroll summary present when a profile has been set for the current tax year.
type UserService ¶
type UserService struct {
Collection[User]
}
UserService covers https://dev.freeagent.com/docs/users
type VATBreakdown ¶
type VATBreakdown struct {
Title string `json:"title,omitempty"`
Rows []VATBreakdownRow `json:"rows,omitempty"`
}
VATBreakdown is the box-by-box detail of a return.
type VATBreakdownRow ¶
type VATBreakdownRow struct {
Title string `json:"title,omitempty"`
Value *Decimal `json:"value,omitempty"`
Key string `json:"key,omitempty"`
// BoxNumber is documented as a string but the live API sends a bare
// number, which would fail to decode into one. Int64 takes either.
BoxNumber Int64 `json:"box_number,omitempty"`
}
VATBreakdownRow is one box on the return.
type VATReturn ¶
type VATReturn struct {
// URL ends in the period end date, so ResourceURL.ID does not apply.
URL ResourceURL `json:"url,omitempty"`
PeriodStartsOn Date `json:"period_starts_on,omitzero"`
PeriodEndsOn Date `json:"period_ends_on,omitzero"`
FilingDueOn Date `json:"filing_due_on,omitzero"`
// FilingStatus is unfiled, pending, rejected, filed or marked_as_filed.
FilingStatus string `json:"filing_status,omitempty"`
FiledAt Time `json:"filed_at,omitzero"`
FiledReference string `json:"filed_reference,omitempty"`
Payments []FilingPayment `json:"payments,omitempty"`
Breakdown *VATBreakdown `json:"breakdown,omitempty"`
}
VATReturn is one VAT period and its filing state.
type VATReturnService ¶
type VATReturnService struct {
// contains filtered or unexported fields
}
VATReturnService covers https://dev.freeagent.com/docs/vat_returns
Returns are addressed by period end date. The account must be VAT registered; otherwise the collection is empty.
func (*VATReturnService) Get ¶
func (s *VATReturnService) Get(ctx context.Context, periodEndsOn Date) (*VATReturn, *Response, error)
Get fetches one period by its end date.
func (*VATReturnService) MarkAsFiled ¶
func (s *VATReturnService) MarkAsFiled(ctx context.Context, periodEndsOn Date) (*VATReturn, *Response, error)
MarkAsFiled records the return as filed outside FreeAgent. Needs Full Access.
func (*VATReturnService) MarkAsUnfiled ¶
func (s *VATReturnService) MarkAsUnfiled(ctx context.Context, periodEndsOn Date) (*VATReturn, *Response, error)
MarkAsUnfiled reverses MarkAsFiled.
func (*VATReturnService) MarkPaymentAsPaid ¶
func (s *VATReturnService) MarkPaymentAsPaid(ctx context.Context, periodEndsOn, paymentDate Date) (*VATReturn, *Response, error)
MarkPaymentAsPaid records the payment due on paymentDate as settled.
func (*VATReturnService) MarkPaymentAsUnpaid ¶
func (s *VATReturnService) MarkPaymentAsUnpaid(ctx context.Context, periodEndsOn, paymentDate Date) (*VATReturn, *Response, error)
MarkPaymentAsUnpaid reverses MarkPaymentAsPaid.
func (*VATReturnService) Meta ¶
func (s *VATReturnService) Meta() ResourceMeta
Meta returns the resource metadata.
Source Files
¶
- attachments.go
- auth.go
- bank_accounts.go
- bank_feeds.go
- bank_transaction_explanations.go
- bank_transactions.go
- bills.go
- capital_assets.go
- categories.go
- client.go
- collection.go
- company.go
- contacts.go
- credit_notes.go
- errors.go
- estimates.go
- expenses.go
- final_accounts_reports.go
- invoices.go
- journal_sets.go
- member.go
- notes.go
- pagination.go
- payroll.go
- period_reports.go
- projects.go
- ratelimit.go
- raw.go
- registry.go
- reports.go
- services.go
- stock_items.go
- tasks.go
- timeslips.go
- types.go
- users.go