package main
import (
"context"
"fmt"
"log"
"os"
"gohome.4gophers.ru/kovardin/goord/ord"
)
var create = false
func main() {
client, _ := ord.NewClient(
ord.WithBase("https://api-sandbox.ord.vk.com"),
ord.WithToken(os.Getenv("TOKEN")),
)
fmt.Println("Getting list of CIDs...")
cidList, err := client.GetCIDList(context.Background(), 0, 10)
if err != nil {
log.Printf("Error getting CID list: %v\n", err)
} else {
fmt.Printf("Retrieved %d CIDs (total: %d)\n", len(cidList.CIDs), cidList.TotalItemsCount)
for i, id := range cidList.CIDs {
fmt.Printf(" %d. %s\n", i+1, id)
}
}
cidValue := "123e4567-e89b-12d3-a456-426655440000"
if create {
fmt.Println("Creating/updating a CID...")
cid := ord.CID{
CID: cidValue,
Name: "Test CID",
}
err = client.CreateCID(context.Background(), cidValue, cid)
if err != nil {
log.Printf("Error creating CID: %v\n", err)
} else {
fmt.Printf("CID %s created/updated successfully\n", cidValue)
}
}
fmt.Println("Getting a specific CID...")
retrievedCID, err := client.GetCID(context.Background(), cidValue)
if err != nil {
log.Printf("Error getting CID: %v\n", err)
} else {
fmt.Printf("Retrieved CID: %s\n", retrievedCID.CID)
fmt.Printf("CID name: %s\n", retrievedCID.Name)
}
}
package main
import (
"context"
"fmt"
"log"
"os"
"gohome.4gophers.ru/kovardin/goord/ord"
)
var create = false
func main() {
client, _ := ord.NewClient(
ord.WithBase("https://api-sandbox.ord.vk.com"),
ord.WithToken(os.Getenv("TOKEN")),
)
fmt.Println("Getting list of contracts...")
contracts, err := client.GetContracts(context.Background(), 0, 10)
if err != nil {
log.Printf("Error getting contracts: %v\n", err)
} else {
fmt.Printf("Retrieved %d contracts (total: %d)\n", len(contracts.ExternalIDs), contracts.TotalItemsCount)
for i, id := range contracts.ExternalIDs {
fmt.Printf(" %d. %s\n", i+1, id)
}
}
contractExternalID := "test-contract-001"
if create {
fmt.Println("Creating/updating a contract...")
contract := ord.CreateContractRequest{
Type: ord.ContractTypeService,
ClientExternalID: "test-person-001",
ContractorExternalID: "i5c6aq2r0rs-1jaocdo32",
Date: "2026-01-19",
SubjectType: ord.ContractSubjectTypeOther,
}
err = client.CreateContract(context.Background(), contractExternalID, contract)
if err != nil {
log.Printf("Error creating contract: %v\n", err)
} else {
fmt.Printf("Contract %s created/updated successfully\n", contractExternalID)
}
}
fmt.Println("Getting a specific contract...")
retrievedContract, err := client.GetContract(context.Background(), contractExternalID)
if err != nil {
log.Printf("Error getting contract: %v\n", err)
} else {
fmt.Printf("Retrieved contract type: %s\n", retrievedContract.Type)
fmt.Printf("Contract client ID: %s\n", retrievedContract.ClientExternalID)
fmt.Printf("Contract contractor ID: %s\n", retrievedContract.ContractorExternalID)
}
fmt.Println("Requesting a CID for contract...")
err = client.RequestCID(context.Background(), contractExternalID)
if err != nil {
log.Printf("Error requesting CID: %v\n", err)
} else {
fmt.Printf("CID requested successfully\n")
}
}
package main
import (
"context"
"fmt"
"log"
"os"
"gohome.4gophers.ru/kovardin/goord/ord"
)
var create = true
func main() {
client, _ := ord.NewClient(
ord.WithBase("https://api-sandbox.ord.vk.com"),
ord.WithToken(os.Getenv("TOKEN")),
)
fmt.Println("Getting list of creatives...")
creatives, err := client.GetCreatives(context.Background(), 0, 10)
if err != nil {
log.Printf("Error getting creatives: %v\n", err)
} else {
fmt.Printf("Retrieved %d creatives (total: %d)\n", len(creatives.ExternalIDs), creatives.TotalItemsCount)
for i, id := range creatives.ExternalIDs {
fmt.Printf(" %d. %s\n", i+1, id)
}
}
externalID := "test-creative-001"
if create {
fmt.Println("Creating/updating a creative (v3)...")
creative := ord.CreateCreativeV3Request{
PersonExternalID: ord.StringPtr("test-person-001"),
KKTUs: []string{"5.2.3"},
Name: ord.StringPtr("Тестовый креатив"),
Form: ord.CreativeFormBanner,
TargetURLs: &[]string{"https://example.com"},
MediaExternalIDs: &[]string{"test-media-001"},
PayType: ord.StringPtr(ord.CreativePayTypeCPM),
}
err = client.CreateCreativeV3(context.Background(), externalID, creative)
if err != nil {
log.Printf("Error creating creative: %v\n", err)
} else {
fmt.Printf("Creative %s created/updated successfully\n", externalID)
}
}
fmt.Println("Getting a specific creative...")
retrievedCreative, err := client.GetCreativeV3(context.Background(), externalID)
if err != nil {
log.Printf("Error getting creative: %v\n", err)
} else {
fmt.Printf("Retrieved creative: %s\n", *retrievedCreative.Name)
fmt.Printf("Creative form: %s\n", retrievedCreative.Form)
fmt.Printf("Creative KKTVs: %v\n", retrievedCreative.KKTUs)
}
if create {
fmt.Println("Adding texts to creative...")
texts := []string{"Текст рекламы 1", "Текст рекламы 2"}
err = client.AddTextsToCreative(context.Background(), externalID, texts)
if err != nil {
log.Printf("Error adding texts to creative: %v\n", err)
} else {
fmt.Printf("Texts added to creative %s successfully\n", externalID)
}
}
if create {
fmt.Println("Adding media to creative...")
mediaExternalIDs := []string{"test-media-001"}
err = client.AddMediaToCreative(context.Background(), externalID, mediaExternalIDs)
if err != nil {
log.Printf("Error adding media to creative: %v\n", err)
} else {
fmt.Printf("Media added to creative %s successfully\n", externalID)
}
}
fmt.Println("Getting creative ERIDs...")
erids, err := client.GetCreativeERIDs(context.Background(), 0, 10)
if err != nil {
log.Printf("Error getting creative ERIDs: %v\n", err)
} else {
fmt.Printf("Retrieved %d ERIDs (total: %d)\n", len(erids.ERIDs), erids.TotalItemsCount)
for i, erid := range erids.ERIDs {
fmt.Printf(" %d. %s\n", i+1, erid)
}
}
fmt.Println("Getting creative ERID/External ID pairs...")
pairs, err := client.GetCreativeERIDExternalIDPairs(context.Background(), 0, 10)
if err != nil {
log.Printf("Error getting creative ERID/External ID pairs: %v\n", err)
} else {
fmt.Printf("Retrieved %d pairs (total: %d)\n", len(pairs.Items), pairs.TotalItemsCount)
for i, pair := range pairs.Items {
fmt.Printf(" %d. ERID: %s, External ID: %s\n", i+1, pair.ERID, pair.ExternalID)
}
}
}
package main
import (
"context"
"fmt"
"log"
"os"
"gohome.4gophers.ru/kovardin/goord/ord"
)
func main() {
client, _ := ord.NewClient(
ord.WithBase("https://api-sandbox.ord.vk.com"),
ord.WithToken(os.Getenv("TOKEN")),
)
fmt.Println("Getting KKTU codes...")
kktuResponse, err := client.GetKKTUCodes(context.Background(), "test", "ru", 0, 10, []string{})
if err != nil {
log.Printf("Error getting KKTU codes: %v\n", err)
} else {
fmt.Printf("Retrieved %d KKTU items (total: %d)\n", len(kktuResponse.Items), kktuResponse.TotalItemsCount)
for i, item := range kktuResponse.Items {
fmt.Printf(" %d. %s - %s\n", i+1, item.Code, item.Name)
}
}
fmt.Println("Getting ERIR message...")
erirResponse, err := client.GetERIRMessage(context.Background(), "ru", "test")
if err != nil {
log.Printf("Error getting ERIR message: %v\n", err)
} else {
fmt.Printf("Retrieved %d ERIR messages\n", len(erirResponse.Items))
for i, item := range erirResponse.Items {
fmt.Printf(" %d. %s - %s\n", i+1, item.Name, item.Message)
}
}
fmt.Println("Posting ERIR messages...")
messages := []string{"test1", "test2"}
postResponse, err := client.PostERIRMessages(context.Background(), "ru", messages)
if err != nil {
log.Printf("Error posting ERIR messages: %v\n", err)
} else {
fmt.Printf("Posted ERIR messages, received %d items\n", len(postResponse.Items))
for i, item := range postResponse.Items {
fmt.Printf(" %d. %s - %s\n", i+1, item.Name, item.Message)
}
}
}
package main
import (
"context"
"fmt"
"log"
"os"
"gohome.4gophers.ru/kovardin/goord/ord"
)
var create = true
func main() {
client, _ := ord.NewClient(
ord.WithBase("https://api-sandbox.ord.vk.com"),
ord.WithToken(os.Getenv("TOKEN")),
)
fmt.Println("Getting list of invoices...")
invoices, err := client.GetInvoices(context.Background(), 0, 10)
if err != nil {
log.Printf("Error getting invoices: %v\n", err)
} else {
fmt.Printf("Retrieved %d invoices (total: %d)\n", len(invoices.ExternalIDs), invoices.TotalItemsCount)
for i, id := range invoices.ExternalIDs {
fmt.Printf(" %d. %s\n", i+1, id)
}
}
externalID := "test-invoice-001"
if create {
fmt.Println("Creating/updating an invoice...")
amount := ord.InvoiceAmount{
Services: ord.InvoiceAmountGroup{
ExcludingVat: "1000",
VatRate: "20",
Vat: "200",
IncludingVat: "1200",
},
}
invoice := ord.Invoice{
ContractExternalID: "test-contract-001",
Date: "2023-01-01",
DateStart: "2023-01-01",
DateEnd: "2023-01-31",
Amount: amount,
ClientRole: ord.InvoiceClientRoleTypeAdvertiser,
ContractorRole: ord.InvoiceClientRoleTypePublisher,
Flags: []string{"flag1", "flag2"},
}
err = client.CreateInvoiceHeader(context.Background(), externalID, invoice)
if err != nil {
log.Printf("Error creating invoice: %v\n", err)
} else {
fmt.Printf("Invoice %s created/updated successfully\n", externalID)
}
}
fmt.Println("Getting a specific invoice...")
retrievedInvoice, err := client.GetInvoice(context.Background(), externalID)
if err != nil {
log.Printf("Error getting invoice: %v\n", err)
} else {
fmt.Printf("Retrieved invoice contract: %s\n", retrievedInvoice.ContractExternalID)
fmt.Printf("Invoice date: %s\n", retrievedInvoice.Date)
fmt.Printf("Invoice amount: %s\n", retrievedInvoice.Amount.Services.IncludingVat)
}
}
package main
import (
"bytes"
"context"
"fmt"
"image"
"image/color"
"image/png"
"log"
"os"
"gohome.4gophers.ru/kovardin/goord/ord"
)
var create = false
func main() {
client, _ := ord.NewClient(
ord.WithBase("https://api-sandbox.ord.vk.com"),
ord.WithToken(os.Getenv("TOKEN")),
)
fmt.Println("Getting list of media...")
mediaList, err := client.GetMediaList(context.Background(), 0, 10)
if err != nil {
log.Printf("Error getting media list: %v\n", err)
} else {
fmt.Printf("Retrieved %d media items (total: %d)\n", len(mediaList.ExternalIDs), mediaList.TotalItemsCount)
for i, id := range mediaList.ExternalIDs {
fmt.Printf(" %d. %s\n", i+1, id)
}
}
externalID := "test-media-001"
fmt.Println("Uploading media...")
if create {
img := generateTestImage()
var buf bytes.Buffer
err = png.Encode(&buf, img)
if err != nil {
log.Printf("Error encoding image: %v\n", err)
return
}
sha256, err := client.UploadMedia(context.Background(), externalID, "test.png", &buf)
if err != nil {
log.Printf("Error uploading media: %v\n", err)
} else {
fmt.Printf("Media %s uploaded successfully. SHA256: %s\n", externalID, *sha256)
}
fmt.Println("Getting media info...")
mediaInfo, err := client.GetMediaInfo(context.Background(), externalID)
if err != nil {
log.Printf("Error getting media info: %v\n", err)
} else {
fmt.Printf("Media info: %+v\n", mediaInfo)
fmt.Printf("Filename: %s\n", mediaInfo.Filename)
fmt.Printf("Size: %d\n", mediaInfo.Size)
fmt.Printf("Content Type: %s\n", mediaInfo.ContentType)
}
}
fmt.Println("Getting media binary data...")
binaryData, err := client.GetMediaBinary(context.Background(), externalID)
if err != nil {
log.Printf("Error getting media binary data: %v\n", err)
} else {
fmt.Printf("Retrieved binary data of size: %d bytes\n", len(binaryData))
fmt.Printf("First 100 bytes: %v\n", binaryData[:100])
}
fmt.Println("Getting batch media info...")
mediaInfos, err := client.GetMediaInfoBatch(context.Background(), []string{externalID})
if err != nil {
log.Printf("Error getting batch media info: %v\n", err)
} else {
fmt.Printf("Retrieved info for %d media items\n", len(mediaInfos))
for i, info := range mediaInfos {
fmt.Printf(" %d. %s (%s)\n", i+1, info.ExternalID, info.Filename)
}
}
}
func generateTestImage() image.Image {
img := image.NewRGBA(image.Rect(0, 0, 100, 100))
for y := 0; y < 100; y++ {
for x := 0; x < 100; x++ {
r := uint8(x * 255 / 100)
g := uint8(y * 255 / 100)
b := uint8((x + y) * 255 / 200)
img.Set(x, y, color.RGBA{r, g, b, 255})
}
}
return img
}
package main
import (
"context"
"fmt"
"log"
"os"
"gohome.4gophers.ru/kovardin/goord/ord"
)
var create = true
func main() {
client, _ := ord.NewClient(
ord.WithBase("https://api-sandbox.ord.vk.com"),
ord.WithToken(os.Getenv("TOKEN")),
)
fmt.Println("Getting list of pads...")
pads, err := client.GetPads(context.Background(), 0, 10, "")
if err != nil {
log.Printf("Error getting pads: %v\n", err)
} else {
fmt.Printf("Retrieved %d pads (total: %d)\n", len(pads.ExternalIDs), pads.TotalItemsCount)
for i, id := range pads.ExternalIDs {
fmt.Printf(" %d. %s\n", i+1, id)
}
}
fmt.Println("Getting restricted pads...")
restrictedPads, err := client.GetRestrictedPads(context.Background())
if err != nil {
log.Printf("Error getting restricted pads: %v\n", err)
} else {
fmt.Printf("Retrieved %d restricted pads\n", len(restrictedPads))
for i, url := range restrictedPads {
fmt.Printf(" %d. %s\n", i+1, url)
}
}
padExternalID := "test-pad-001"
if create {
fmt.Println("Creating/updating a pad...")
pad := ord.Pad{
PersonExternalID: "test-person-001",
IsOwner: true,
Type: ord.PadTypeWeb,
Name: "Test Pad",
URL: ord.StringPtr("https://example.com"),
}
err = client.CreatePad(context.Background(), padExternalID, pad)
if err != nil {
log.Printf("Error creating pad: %v\n", err)
} else {
fmt.Printf("Pad %s created/updated successfully\n", padExternalID)
}
}
fmt.Println("Getting a specific pad...")
retrievedPad, err := client.GetPad(context.Background(), padExternalID)
if err != nil {
log.Printf("Error getting pad: %v\n", err)
} else {
fmt.Printf("Retrieved pad name: %s\n", retrievedPad.Name)
fmt.Printf("Pad type: %s\n", retrievedPad.Type)
fmt.Printf("Pad person ID: %s\n", retrievedPad.PersonExternalID)
}
}
package main
import (
"context"
"fmt"
"log"
"os"
"gohome.4gophers.ru/kovardin/goord/ord"
)
var create = false
func main() {
client, _ := ord.NewClient(
ord.WithBase("https://api-sandbox.ord.vk.com"),
ord.WithToken(os.Getenv("TOKEN")),
)
fmt.Println("Getting list of persons...")
persons, err := client.GetPersons(context.Background(), 0, 10)
if err != nil {
log.Printf("Error getting persons: %v\n", err)
} else {
fmt.Printf("Retrieved %d persons (total: %d)\n", len(persons.ExternalIDs), persons.TotalItemsCount)
for i, id := range persons.ExternalIDs {
fmt.Printf(" %d. %s\n", i+1, id)
}
}
externalID := "test-person-001"
if create {
fmt.Println("Creating/updating a person...")
juridicalDetails := ord.JuridicalDetails{
Type: ord.PersonTypePhysical,
INN: "910810615691",
}
person := ord.Person{
Name: "Ковардин Артем Сергеевич",
Roles: []string{"advertiser"},
JuridicalDetails: juridicalDetails,
}
err = client.CreatePerson(context.Background(), externalID, person)
if err != nil {
log.Printf("Error creating person: %v\n", err)
} else {
fmt.Printf("Person %s created/updated successfully\n", externalID)
}
}
fmt.Println("Getting a specific person...")
retrievedPerson, err := client.GetPerson(context.Background(), externalID)
if err != nil {
log.Printf("Error getting person: %v\n", err)
} else {
fmt.Printf("Retrieved person: %s\n", retrievedPerson.Name)
fmt.Printf("Person roles: %v\n", retrievedPerson.Roles)
fmt.Printf("Person type: %s\n", retrievedPerson.JuridicalDetails.Type)
}
}
package main
import (
"context"
"fmt"
"log"
"os"
"gohome.4gophers.ru/kovardin/goord/ord"
)
var create = false
func main() {
client, _ := ord.NewClient(
ord.WithBase("https://api-sandbox.ord.vk.com"),
ord.WithToken(os.Getenv("TOKEN")),
)
fmt.Println("Getting list of statistics...")
statistics, err := client.GetStatisticsList(context.Background(), 0, 10)
if err != nil {
log.Printf("Error getting statistics: %v\n", err)
} else {
fmt.Printf("Retrieved %d statistics (total: %d)\n", len(statistics.Items), statistics.TotalItemsCount)
for i, item := range statistics.Items {
fmt.Printf(" %d. Creative: %s, Pad: %s, Shows: %d\n", i+1, item.CreativeExternalID, item.PadExternalID, item.ShowsCount)
}
}
if create {
fmt.Println("Creating statistics...")
var showsCount uint64 = 1000
amount := ord.StatisticsAmount{
ExcludingVAT: "800",
VATRate: "20",
VAT: "160",
IncludingVAT: "960",
}
statisticsItems := ord.StatisticsV2ItemsArray{
Items: []ord.StatisticsV2Item{
{
CreativeExternalID: "01",
PadExternalID: "test-pad-001",
ShowsCount: showsCount,
InvoiceShowsCount: &showsCount,
Amount: &amount,
AmountPerEvent: ord.StringPtr("0.96"),
PayType: ord.StringPtr(ord.StatisticsPayTypeCPM),
DateStartPlanned: ord.StringPtr("2023-01-01"),
DateEndPlanned: ord.StringPtr("2023-01-31"),
DateStartActual: "2023-01-01",
DateEndActual: "2023-01-31",
},
},
}
externalIDs, err := client.CreateStatisticsV2(context.Background(), statisticsItems)
if err != nil {
log.Printf("Error creating statistics: %v\n", err)
} else {
fmt.Printf("Statistics created successfully, external IDs: %v\n", externalIDs)
}
}
deleteReq := ord.DeleteStatisticsRequest{
Items: []struct {
CreativeExternalID string `json:"creative_external_id"`
PadExternalID string `json:"pad_external_id"`
DateStartActual string `json:"date_start_actual"`
}{
{
CreativeExternalID: "test-creative-001",
PadExternalID: "test-pad-001",
DateStartActual: "2023-01-01",
},
},
}
err = client.DeleteStatisticsV3(context.Background(), deleteReq)
if err != nil {
log.Printf("Error deleting statistics: %v\n", err)
} else {
fmt.Println("Statistics deleted successfully")
}
}
package ord
import (
"context"
"fmt"
)
type CID struct {
CID string `json:"cid"`
Name string `json:"name"`
ErirStatus string `json:"erir_status"`
ClientINN *string `json:"client_inn,omitempty"`
ClientPhone *string `json:"client_phone,omitempty"`
ClientForeignEpaymentMethod *string `json:"client_foreign_epayment_method,omitempty"`
ClientForeignRegistrationNumber *string `json:"client_foreign_registration_number,omitempty"`
ClientForeignINN *string `json:"client_foreign_inn,omitempty"`
}
type CIDListResponse struct {
CIDs []string `json:"cids"`
TotalItemsCount int `json:"total_items_count"`
Limit int `json:"limit"`
}
func (c *Client) GetCIDList(ctx context.Context, offset, limit int) (*CIDListResponse, error) {
path := fmt.Sprintf("/v1/cid?offset=%d&limit=%d", offset, limit)
var response CIDListResponse
if err := c.request(ctx, "GET", path, nil, &response); err != nil {
return nil, fmt.Errorf("failed to get CID list: %w", err)
}
return &response, nil
}
func (c *Client) GetCID(ctx context.Context, cidValue string) (*CID, error) {
path := fmt.Sprintf("/v1/cid/%s", cidValue)
var cid CID
if err := c.request(ctx, "GET", path, nil, &cid); err != nil {
return nil, fmt.Errorf("failed to get CID: %w", err)
}
return &cid, nil
}
func (c *Client) CreateCID(ctx context.Context, cidValue string, cid CID) error {
path := fmt.Sprintf("/v1/cid/%s", cidValue)
if err := c.request(ctx, "PUT", path, cid, nil); err != nil {
return fmt.Errorf("failed to create CID: %w", err)
}
return nil
}
package ord
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
)
type Client struct {
base string
http *http.Client
token string
}
func NewClient(options ...Option) (*Client, error) {
cl := &Client{
base: "https://api.ord.vk.com",
http: http.DefaultClient,
}
for _, o := range options {
if err := o(cl); err != nil {
return nil, err
}
}
return cl, nil
}
func (c *Client) SetToken(token string) {
c.token = token
}
// request performs an HTTP request to the ORD VK API
func (c *Client) request(ctx context.Context, method, path string, body interface{}, result interface{}) error {
url := c.base + path
var req *http.Request
var err error
if body != nil {
jsonBody, err := json.Marshal(body)
if err != nil {
return fmt.Errorf("failed to marshal request body: %w", err)
}
req, err = http.NewRequestWithContext(ctx, method, url, bytes.NewBuffer(jsonBody))
if err != nil {
return fmt.Errorf("failed to create request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
} else {
req, err = http.NewRequestWithContext(ctx, method, url, nil)
if err != nil {
return fmt.Errorf("failed to create request: %w", err)
}
}
if c.token != "" {
req.Header.Set("Authorization", "Bearer "+c.token)
}
resp, err := c.http.Do(req)
if err != nil {
return fmt.Errorf("failed to perform request: %w", err)
}
defer func() {
if err := resp.Body.Close(); err != nil {
log.Println("error on close body", err)
}
}()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("failed to read response body: %w", err)
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return fmt.Errorf("API request failed with status %d: %s", resp.StatusCode, string(respBody))
}
if result != nil && len(respBody) > 0 {
if err := json.Unmarshal(respBody, result); err != nil {
return fmt.Errorf("failed to unmarshal response: %w", err)
}
}
return nil
}
package ord
import (
"context"
"fmt"
)
const (
ContractTypeService = "service" // договор оказания услуг.
ContractTypeMediation = "mediation" // посреднический договор. Требует заполнения поля action_type.
ContractTypeAdditional = "additional" // дополнительное соглашение. Требует заполнения поля parent_contract_external_id.
)
const (
ContractActionTypeDistribution = "distribution" // распространение рекламы.
ContractActionTypeConclude = "conclude" // заключение договоров.
ContractActionTypeCommercial = "commercial" // коммерческое представительство.
ContractActionTypeOther = "other" // иное.
)
const (
ContractSubjectTypeRepresentation = "representation" // представительство.
ContractSubjectTypeOrgDistribution = "org_distribution" // организация распространения рекламы.
ContractSubjectTypeMediation = "mediation" // посредничество.
ContractSubjectTypeDistribution = "distribution" // распространение рекламы.
ContractSubjectTypeOther = "other" // иное.
)
const (
// vat_included — все налоги (если есть) включены в сумму договора. Обязателен для значений amount > 0.
ContractFlagVatIncluded = "vat_included"
// contractor_is_creatives_reporter — подрядчик обязуется вести учёт креативов.
// Значение можно указать, только если contractor_external_id — рекламная система.
ContractFlagContractorIsCreativesReporter = "contractor_is_creatives_reporter"
// деньги поступают от подрядчика (исполнителя) клиенту (заказчику).
// Значение можно указать, только если поле type принимает значение mediation.
ContractFlagAgentActingForPublisher = "agent_acting_for_publisher"
// рекламный сбор в размере 3% за всю цепочку распространения рекламы оплачивает
// исполнитель по этому договору. Значение можно указать, только если поле type
// принимает значение mediation и подрядчик (исполнитель) не иностранный контрагент.
// Несовместим с флагом agent_acting_for_publisher.
ContractFlagIsChargePaidByAgent = "is_charge_paid_by_agent"
)
// Contract represents a contract (договор) in the ORD system
type Contract struct {
CreateDate string `json:"create_date,omitempty"`
Type string `json:"type"`
ClientExternalID string `json:"client_external_id"`
ContractorExternalID string `json:"contractor_external_id"`
ActionType *string `json:"action_type,omitempty"`
SubjectType string `json:"subject_type"`
Date string `json:"date"`
DateEnd *string `json:"date_end,omitempty"`
Serial *string `json:"serial,omitempty"`
Flags []string `json:"flags,omitempty"`
ParentContractExternalID *string `json:"parent_contract_external_id,omitempty"`
// maxLength: 29
// minLength: 1
// pattern: ^\d{1,12}(\.\d{1,8})?
// nullable: true
// example: 500.5
Amount *string `json:"amount,omitempty"`
HasAdditionalContracts bool `json:"has_additional_contracts,omitempty"`
CID *string `json:"cid,omitempty"`
LockedFields []LockedField `json:"locked_fields,omitempty"`
}
type ContractListResponse struct {
ExternalIDs []string `json:"external_ids"`
TotalItemsCount int `json:"total_items_count"`
Limit int `json:"limit"`
}
type CreateContractRequest struct {
Type string `json:"type"`
ClientExternalID string `json:"client_external_id"`
ContractorExternalID string `json:"contractor_external_id"`
Date string `json:"date"`
DateEnd *string `json:"date_end,omitempty"`
Serial *string `json:"serial,omitempty"`
ActionType *string `json:"action_type,omitempty"`
SubjectType string `json:"subject_type"`
Flags []string `json:"flags,omitempty"`
ParentContractExternalID *string `json:"parent_contract_external_id,omitempty"`
Amount *string `json:"amount,omitempty"`
}
func (c *Client) GetContracts(ctx context.Context, offset, limit int) (*ContractListResponse, error) {
path := fmt.Sprintf("/v1/contract?offset=%d&limit=%d", offset, limit)
var response ContractListResponse
if err := c.request(ctx, "GET", path, nil, &response); err != nil {
return nil, fmt.Errorf("failed to get contracts: %w", err)
}
return &response, nil
}
func (c *Client) GetContract(ctx context.Context, externalID string) (*Contract, error) {
path := fmt.Sprintf("/v1/contract/%s", externalID)
var contract Contract
if err := c.request(ctx, "GET", path, nil, &contract); err != nil {
return nil, fmt.Errorf("failed to get contract: %w", err)
}
return &contract, nil
}
func (c *Client) CreateContract(ctx context.Context, externalID string, contract CreateContractRequest) error {
path := fmt.Sprintf("/v1/contract/%s", externalID)
if err := c.request(ctx, "PUT", path, contract, nil); err != nil {
return fmt.Errorf("failed to create contract: %w", err)
}
return nil
}
func (c *Client) RequestCID(ctx context.Context, externalID string) error {
path := fmt.Sprintf("/v1/contract/%s/create_cid", externalID)
if err := c.request(ctx, "POST", path, nil, nil); err != nil {
return fmt.Errorf("failed to request CID: %w", err)
}
return nil
}
package ord
import (
"context"
"fmt"
"net/url"
)
const (
CreativePayTypeCPA = "cpa" // Cost Per Action, цена за действие.
CreativePayTypeCPC = "cpc" // Cost Per Click, цена за клик.
CreativePayTypeCPM = "cpm" // Cost Per Millennium, цена за 1 000 показов.
CreativePayTypeOther = "other" // иное.
)
const (
CreativeFormBanner = "banner" // баннер.
CreativeFormText = "text" // текстовый блок.
CreativeFormAudio = "audio" // аудиозапись.
CreativeFormVideo = "video" // видеоролик.
CreativeFormLiveAudio = "live_audio" // аудиотрансляция в прямом эфире.
CreativeFormLiveVideo = "live_video" // видеотрансляция в прямом эфире.
CreativeFormTextVideoBlock = "text_video_block" // текстовый блок с видео
CreativeFormTextGraphicBlock = "text_graphic_block" // текстово-графический блок
CreativeFormTextAudioBlock = "text_audio_block" // текстовый блок с аудио
CreativeFormTextGraphicVideoBlock = "text_graphic_video_block" // текстово-графический блок с видео
CreativeFormTextAudioVideoBlock = "text_audio_video_block" // текстовый блок с аудио и видео
CreativeFormTextGraphicAudioBlock = "text_graphic_audio_block" // текстово-графический блок с видео
CreativeFormTextGraphicAudioVideoBlock = "text_graphic_audio_video_block" // текстово-графический блок с аудио и видео
CreativeFormBannerHTML5 = "banner_html5" // HTML5-баннер
)
const (
CreativeFlagSocial = "social" // социальная реклама.
CreativeFlagNative = "native" // нативная реклама (только в GET, PUT не поддерживается).
CreativeFlagSocialQuota = "social_quota" // социальная реклама по квоте.
)
type Creative struct {
CreateDate string `json:"create_date,omitempty"`
ERID string `json:"erid"`
PersonExternalID *string `json:"person_external_id,omitempty"`
ContractExternalID *string `json:"contract_external_id,omitempty"`
ContractExternalIDs *[]string `json:"contract_external_ids,omitempty"`
CIDs *[]string `json:"cids,omitempty"`
OKVEDs *[]string `json:"okveds,omitempty"`
KKTUs []string `json:"kktus"`
Name *string `json:"name,omitempty"`
Brand *string `json:"brand,omitempty"`
Category *string `json:"category,omitempty"`
Description *string `json:"description,omitempty"`
PayType *string `json:"pay_type,omitempty"`
Form string `json:"form"`
Targeting *string `json:"targeting,omitempty"`
TargetURLs *[]string `json:"target_urls,omitempty"`
Texts *[]string `json:"texts,omitempty"`
MediaExternalIDs *[]string `json:"media_external_ids,omitempty"`
MediaURLs *[]string `json:"media_urls,omitempty"`
Flags *[]string `json:"flags,omitempty"`
}
// CreativeListResponse represents the response for getting a list of creatives
type CreativeListResponse struct {
ExternalIDs []string `json:"external_ids"`
TotalItemsCount int `json:"total_items_count"`
Limit int `json:"limit"`
}
// CreativeERIDsListResponse represents the response for getting a list of creative ERIDs
type CreativeERIDsListResponse struct {
ERIDs []string `json:"erids"`
TotalItemsCount int `json:"total_items_count"`
Limit int `json:"limit"`
}
// CreativeERIDExternalIDPair represents a pair of ERID and external ID
type CreativeERIDExternalIDPair struct {
ERID string `json:"erid"`
ExternalID string `json:"external_id"`
}
// CreativeERIDExternalIDPairsResponse represents the response for getting pairs of ERIDs and external IDs
type CreativeERIDExternalIDPairsResponse struct {
Items []CreativeERIDExternalIDPair `json:"items"`
TotalItemsCount int `json:"total_items_count"`
Limit int `json:"limit"`
}
// AddTextsToCreativeRequest represents the request body for adding texts to a creative
type AddTextsToCreativeRequest struct {
Texts []string `json:"texts"`
}
// AddMediaToCreativeRequest represents the request body for adding media to a creative
type AddMediaToCreativeRequest struct {
MediaExternalIDs []string `json:"media_external_ids"`
}
// CreateCreativeV2Request represents the request body for creating/updating a creative (v2)
type CreateCreativeV2Request struct {
PersonExternalID *string `json:"person_external_id,omitempty"`
ContractExternalID *string `json:"contract_external_id,omitempty"`
OKVEDs *[]string `json:"okveds,omitempty"`
KKTUs []string `json:"kktus"`
Name *string `json:"name,omitempty"`
Brand *string `json:"brand,omitempty"`
Category *string `json:"category,omitempty"`
Description *string `json:"description,omitempty"`
PayType *string `json:"pay_type,omitempty"`
Form string `json:"form"`
Targeting *string `json:"targeting,omitempty"`
TargetURLs *[]string `json:"target_urls,omitempty"`
Texts *[]string `json:"texts,omitempty"`
MediaExternalIDs *[]string `json:"media_external_ids,omitempty"`
MediaURLs *[]string `json:"media_urls,omitempty"`
Flags *[]string `json:"flags,omitempty"`
}
// CreateCreativeV3Request represents the request body for creating/updating a creative (v3)
type CreateCreativeV3Request struct {
PersonExternalID *string `json:"person_external_id,omitempty"`
ContractExternalIDs *[]string `json:"contract_external_ids,omitempty"`
CIDs *[]string `json:"cids,omitempty"`
KKTUs []string `json:"kktus"`
Name *string `json:"name,omitempty"`
Brand *string `json:"brand,omitempty"`
Category *string `json:"category,omitempty"`
Description *string `json:"description,omitempty"`
PayType *string `json:"pay_type,omitempty"`
Form string `json:"form"`
Targeting *string `json:"targeting,omitempty"`
TargetURLs *[]string `json:"target_urls,omitempty"`
Texts *[]string `json:"texts,omitempty"`
MediaExternalIDs *[]string `json:"media_external_ids,omitempty"`
MediaURLs *[]string `json:"media_urls,omitempty"`
Flags *[]string `json:"flags,omitempty"`
}
// GetCreatives retrieves a list of creatives
// GET /v3/creative
func (c *Client) GetCreatives(ctx context.Context, offset, limit int) (*CreativeListResponse, error) {
path := fmt.Sprintf("/v3/creative?offset=%d&limit=%d", offset, limit)
var response CreativeListResponse
if err := c.request(ctx, "GET", path, nil, &response); err != nil {
return nil, fmt.Errorf("failed to get creatives: %w", err)
}
return &response, nil
}
// GetCreativeERIDs retrieves a list of creative ERIDs
// GET /v3/creative/list/erids
func (c *Client) GetCreativeERIDs(ctx context.Context, offset, limit int) (*CreativeERIDsListResponse, error) {
path := fmt.Sprintf("/v3/creative/list/erids?offset=%d&limit=%d", offset, limit)
var response CreativeERIDsListResponse
if err := c.request(ctx, "GET", path, nil, &response); err != nil {
return nil, fmt.Errorf("failed to get creative ERIDs: %w", err)
}
return &response, nil
}
// GetCreativeERIDExternalIDPairs retrieves a list of pairs of ERIDs and external IDs
// GET /v3/creative/list/erid_external_ids
func (c *Client) GetCreativeERIDExternalIDPairs(ctx context.Context, offset, limit int) (*CreativeERIDExternalIDPairsResponse, error) {
path := fmt.Sprintf("/v3/creative/list/erid_external_ids?offset=%d&limit=%d", offset, limit)
var response CreativeERIDExternalIDPairsResponse
if err := c.request(ctx, "GET", path, nil, &response); err != nil {
return nil, fmt.Errorf("failed to get creative ERID/external ID pairs: %w", err)
}
return &response, nil
}
// CreateCreativeV2 creates or updates a creative (v2)
// PUT /v2/creative/{external_id}
func (c *Client) CreateCreativeV2(ctx context.Context, externalID string, creative CreateCreativeV2Request) error {
path := fmt.Sprintf("/v2/creative/%s", externalID)
if err := c.request(ctx, "PUT", path, creative, nil); err != nil {
return fmt.Errorf("failed to create creative (v2): %w", err)
}
return nil
}
// GetCreativeV2 retrieves a creative by external ID (v2)
// GET /v2/creative/{external_id}
func (c *Client) GetCreativeV2(ctx context.Context, externalID string) (*Creative, error) {
path := fmt.Sprintf("/v2/creative/%s", externalID)
var creative Creative
if err := c.request(ctx, "GET", path, nil, &creative); err != nil {
return nil, fmt.Errorf("failed to get creative (v2): %w", err)
}
return &creative, nil
}
// GetCreativeByERIDV2 retrieves a creative by ERID (v2)
// GET /v2/creative/by_erid/{erid}
func (c *Client) GetCreativeByERIDV2(ctx context.Context, erid string) (*Creative, error) {
path := fmt.Sprintf("/v2/creative/by_erid/%s", url.PathEscape(erid))
var creative Creative
if err := c.request(ctx, "GET", path, nil, &creative); err != nil {
return nil, fmt.Errorf("failed to get creative by ERID (v2): %w", err)
}
return &creative, nil
}
// CreateCreativeV3 creates or updates a creative (v3)
// PUT /v3/creative/{external_id}
func (c *Client) CreateCreativeV3(ctx context.Context, externalID string, creative CreateCreativeV3Request) error {
path := fmt.Sprintf("/v3/creative/%s", externalID)
if err := c.request(ctx, "PUT", path, creative, nil); err != nil {
return fmt.Errorf("failed to create creative (v3): %w", err)
}
return nil
}
// GetCreativeV3 retrieves a creative by external ID (v3)
// GET /v3/creative/{external_id}
func (c *Client) GetCreativeV3(ctx context.Context, externalID string) (*Creative, error) {
path := fmt.Sprintf("/v3/creative/%s", externalID)
var creative Creative
if err := c.request(ctx, "GET", path, nil, &creative); err != nil {
return nil, fmt.Errorf("failed to get creative (v3): %w", err)
}
return &creative, nil
}
// GetCreativeByERIDV3 retrieves a creative by ERID (v3)
// GET /v3/creative/by_erid/{erid}
func (c *Client) GetCreativeByERIDV3(ctx context.Context, erid string) (*Creative, error) {
path := fmt.Sprintf("/v3/creative/by_erid/%s", url.PathEscape(erid))
var creative Creative
if err := c.request(ctx, "GET", path, nil, &creative); err != nil {
return nil, fmt.Errorf("failed to get creative by ERID (v3): %w", err)
}
return &creative, nil
}
// AddTextsToCreative adds texts to a creative
// POST /v3/creative/{external_id}/add_text
func (c *Client) AddTextsToCreative(ctx context.Context, externalID string, texts []string) error {
path := fmt.Sprintf("/v3/creative/%s/add_text", externalID)
request := AddTextsToCreativeRequest{
Texts: texts,
}
if err := c.request(ctx, "POST", path, request, nil); err != nil {
return fmt.Errorf("failed to add texts to creative: %w", err)
}
return nil
}
// AddMediaToCreative adds media to a creative
// POST /v3/creative/{external_id}/add_media
func (c *Client) AddMediaToCreative(ctx context.Context, externalID string, mediaExternalIDs []string) error {
path := fmt.Sprintf("/v3/creative/%s/add_media", externalID)
request := AddMediaToCreativeRequest{
MediaExternalIDs: mediaExternalIDs,
}
if err := c.request(ctx, "POST", path, request, nil); err != nil {
return fmt.Errorf("failed to add media to creative: %w", err)
}
return nil
}
package ord
import (
"context"
"fmt"
"net/http"
"net/url"
)
type KKTUItem struct {
Code string `json:"code"`
Name string `json:"name"`
}
type KKTUResponse struct {
TotalItemsCount int `json:"total_items_count"`
Limit int `json:"limit"`
Items []KKTUItem `json:"items"`
}
type ERIRMessageItem struct {
Message string `json:"message"`
Name string `json:"name"`
}
type ERIRMessageResponse struct {
Items []ERIRMessageItem `json:"items"`
}
func (s *Client) GetKKTUCodes(ctx context.Context, search, lang string, offset, limit int, codes []string) (*KKTUResponse, error) {
params := url.Values{}
if search != "" {
params.Set("search", search)
}
if lang != "" {
params.Set("lang", lang)
}
if offset > 0 {
params.Set("offset", fmt.Sprintf("%d", offset))
}
if limit > 0 {
params.Set("limit", fmt.Sprintf("%d", limit))
}
if len(codes) > 0 {
params.Set("codes", fmt.Sprintf("%v", codes))
}
path := "/v1/dict/kktu"
if len(params) > 0 {
path += "?" + params.Encode()
}
var response KKTUResponse
err := s.request(ctx, http.MethodGet, path, nil, &response)
if err != nil {
return nil, err
}
return &response, nil
}
func (s *Client) GetERIRMessage(ctx context.Context, lang, message string) (*ERIRMessageResponse, error) {
params := url.Values{}
if lang != "" {
params.Set("lang", lang)
}
if message != "" {
params.Set("message", message)
}
path := "/v1/dict/erir_message"
if len(params) > 0 {
path += "?" + params.Encode()
}
var response ERIRMessageResponse
err := s.request(ctx, http.MethodGet, path, nil, &response)
if err != nil {
return nil, err
}
return &response, nil
}
func (s *Client) PostERIRMessages(ctx context.Context, lang string, messages []string) (*ERIRMessageResponse, error) {
type request struct {
Lang string `json:"lang,omitempty"`
Messages []string `json:"messages"`
}
req := request{
Lang: lang,
Messages: messages,
}
var response ERIRMessageResponse
err := s.request(ctx, http.MethodPost, "/v1/dict/erir_message", req, &response)
if err != nil {
return nil, err
}
return &response, nil
}
package ord
import (
"context"
"fmt"
"net/url"
)
type ErirStatusEntity struct {
ErirStatus string `json:"erir_status"`
UpdatedByUserTs string `json:"updated_by_user_ts"`
FinalizedTs *string `json:"finalized_ts,omitempty"`
Messages []string `json:"messages,omitempty"`
}
type ErirStatusEntityItem struct {
DataType string `json:"data_type"`
ExternalID string `json:"external_id"`
Name string `json:"name"`
ErirTaxStatus string `json:"erir_tax_status"`
ErirStatus string `json:"erir_status"`
UpdatedByUserTs string `json:"updated_by_user_ts"`
FinalizedTs *string `json:"finalized_ts,omitempty"`
Messages []string `json:"messages,omitempty"`
}
type ErirStatusEntities struct {
TotalItemsCount int `json:"total_items_count"`
Limit int `json:"limit"`
LimitPerEntity int `json:"limit_per_entity"`
Items []ErirStatusEntityItem `json:"items"`
}
func (c *Client) GetErirStatus(ctx context.Context, dataType, externalID string) (*ErirStatusEntity, error) {
path := fmt.Sprintf("/v1/%s/%s/erir_status", dataType, externalID)
var status ErirStatusEntity
if err := c.request(ctx, "GET", path, nil, &status); err != nil {
return nil, fmt.Errorf("failed to get object processing status: %w", err)
}
return &status, nil
}
func (c *Client) GetErirStatuses(ctx context.Context, dataType, erirStatus string, offset, limit, limitPerEntity int, externalIDs []string) (*ErirStatusEntities, error) {
params := url.Values{}
if dataType != "" {
params.Set("data_type", dataType)
}
if erirStatus != "" {
params.Set("erir_status", erirStatus)
}
params.Set("offset", fmt.Sprintf("%d", offset))
params.Set("limit", fmt.Sprintf("%d", limit))
params.Set("limit_per_entity", fmt.Sprintf("%d", limitPerEntity))
for _, id := range externalIDs {
params.Add("external_id", id)
}
path := "/v1/erir_statuses?" + params.Encode()
var statuses ErirStatusEntities
if err := c.request(ctx, "GET", path, nil, &statuses); err != nil {
return nil, fmt.Errorf("failed to get ad object processing statuses: %w", err)
}
return &statuses, nil
}
type ErirStatusRequest struct {
DataType string `json:"data_type,omitempty"`
ErirStatus string `json:"erir_status,omitempty"`
ExternalID []string `json:"external_id,omitempty"`
Offset int `json:"offset,omitempty"`
Limit int `json:"limit,omitempty"`
LimitPerEntity int `json:"limit_per_entity,omitempty"`
}
func (c *Client) PostErirStatuses(ctx context.Context, request ErirStatusRequest) (*ErirStatusEntities, error) {
path := "/v1/erir_statuses"
var statuses ErirStatusEntities
if err := c.request(ctx, "POST", path, request, &statuses); err != nil {
return nil, fmt.Errorf("failed to post ad object processing statuses: %w", err)
}
return &statuses, nil
}
package ord
import (
"context"
"fmt"
)
const (
InvoiceClientRoleTypeAdvertiser = "advertiser" // рекламодатель.
InvoiceClientRoleTypeAgency = "agency" // рекламное агентство.
InvoiceClientRoleTypeOrs = "ors" // оператор рекламной системы.
InvoiceClientRoleTypePublisher = "publisher" // издатель, рекламораспространитель.
InvoiceClientRoleTypeMediator = "mediator" // посредник
)
type Invoice struct {
ContractExternalID string `json:"contract_external_id"`
OrderContractExternalID *string `json:"order_contract_external_id,omitempty"`
Date string `json:"date"`
Serial *string `json:"serial,omitempty"`
DateStart string `json:"date_start"`
DateEnd string `json:"date_end"`
Amount InvoiceAmount `json:"amount"`
ClientRole string `json:"client_role"`
ContractorRole string `json:"contractor_role"`
Flags []string `json:"flags,omitempty"`
Items []InvoiceItem `json:"items,omitempty"`
Status *string `json:"status,omitempty"`
ErirTaxStatus *string `json:"erir_tax_status,omitempty"`
}
type InvoiceAmount struct {
Services InvoiceAmountGroup `json:"services"`
Commission *InvoiceCommission `json:"commission,omitempty"`
}
type InvoiceAmountGroup struct {
ExcludingVat string `json:"excluding_vat"`
VatRate string `json:"vat_rate"`
Vat string `json:"vat"`
IncludingVat string `json:"including_vat"`
}
type InvoiceCommission struct {
Serial *string `json:"serial,omitempty"`
Date *string `json:"date,omitempty"`
Amount InvoiceAmountGroup `json:"amount"`
}
type InvoiceItem struct {
ContractExternalID *string `json:"contract_external_id,omitempty"`
Cid *string `json:"cid,omitempty"`
Amount InvoiceAmountGroup `json:"amount"`
Creatives []InvoiceCreative `json:"creatives,omitempty"`
}
type InvoiceCreative struct {
CreativeExternalID string `json:"creative_external_id"`
Platforms []InvoiceCreativePlatform `json:"platforms,omitempty"`
}
type InvoiceCreativePlatform struct {
PadExternalID string `json:"pad_external_id"`
ShowsCount int64 `json:"shows_count"`
InvoiceShowsCount int64 `json:"invoice_shows_count"`
Amount InvoiceAmountGroup `json:"amount"`
AmountPerEvent *string `json:"amount_per_event,omitempty"`
DateStartPlanned string `json:"date_start_planned"`
DateEndPlanned string `json:"date_end_planned"`
DateStartActual string `json:"date_start_actual"`
DateEndActual string `json:"date_end_actual"`
PayType string `json:"pay_type"`
}
type InvoiceListResponse struct {
ExternalIDs []string `json:"external_ids"`
TotalItemsCount int `json:"total_items_count"`
Limit int `json:"limit"`
}
func (c *Client) GetInvoices(ctx context.Context, offset, limit int) (*InvoiceListResponse, error) {
path := fmt.Sprintf("/v1/invoice?offset=%d&limit=%d", offset, limit)
var response InvoiceListResponse
if err := c.request(ctx, "GET", path, nil, &response); err != nil {
return nil, fmt.Errorf("failed to get invoices: %w", err)
}
return &response, nil
}
func (c *Client) GetInvoice(ctx context.Context, externalID string) (*Invoice, error) {
path := fmt.Sprintf("/v4/invoice/%s", externalID)
var invoice Invoice
if err := c.request(ctx, "GET", path, nil, &invoice); err != nil {
return nil, fmt.Errorf("failed to get invoice: %w", err)
}
return &invoice, nil
}
func (c *Client) CreateInvoiceHeader(ctx context.Context, externalID string, invoice Invoice) error {
path := fmt.Sprintf("/v4/invoice/%s/header", externalID)
if err := c.request(ctx, "PUT", path, invoice, nil); err != nil {
return fmt.Errorf("failed to create invoice header: %w", err)
}
return nil
}
func (c *Client) AddContractsToInvoice(ctx context.Context, externalID string, items []InvoiceItem) error {
path := fmt.Sprintf("/v4/invoice/%s/items", externalID)
requestBody := map[string]interface{}{
"items": items,
}
if err := c.request(ctx, "PATCH", path, requestBody, nil); err != nil {
return fmt.Errorf("failed to add contracts to invoice: %w", err)
}
return nil
}
func (c *Client) DeleteInvoice(ctx context.Context, externalID string) error {
path := fmt.Sprintf("/v4/invoice/%s", externalID)
if err := c.request(ctx, "DELETE", path, nil, nil); err != nil {
return fmt.Errorf("failed to delete invoice: %w", err)
}
return nil
}
func (c *Client) SendInvoiceToErir(ctx context.Context, externalID string) error {
path := fmt.Sprintf("/v4/invoice/%s/ready", externalID)
if err := c.request(ctx, "POST", path, nil, nil); err != nil {
return fmt.Errorf("failed to send invoice to ERIR: %w", err)
}
return nil
}
func (c *Client) DeleteContractsFromInvoice(ctx context.Context, externalID string, deleteInfo interface{}) error {
path := fmt.Sprintf("/v4/invoice/%s/delete", externalID)
if err := c.request(ctx, "POST", path, deleteInfo, nil); err != nil {
return fmt.Errorf("failed to delete contracts from invoice: %w", err)
}
return nil
}
func (c *Client) CreateWholeInvoice(ctx context.Context, externalID string, invoice Invoice) error {
path := fmt.Sprintf("/v4/invoice/%s", externalID)
if err := c.request(ctx, "PUT", path, invoice, nil); err != nil {
return fmt.Errorf("failed to create whole invoice: %w", err)
}
return nil
}
package ord
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"log"
"mime/multipart"
"net/http"
"net/url"
)
type MediaInfo struct {
ExternalID string `json:"external_id"`
Filename string `json:"filename"`
SHA256 string `json:"sha256"`
CreateDate string `json:"create_date"`
Size int64 `json:"size"`
ContentType string `json:"content_type"`
Description string `json:"description,omitempty"`
}
type MediaListResponse struct {
ExternalIDs []string `json:"external_ids"`
TotalItemsCount int `json:"total_items_count"`
Limit int `json:"limit"`
}
func (c *Client) GetMediaList(ctx context.Context, offset, limit int) (*MediaListResponse, error) {
path := fmt.Sprintf("/v1/media?offset=%d&limit=%d", offset, limit)
var response MediaListResponse
if err := c.request(ctx, "GET", path, nil, &response); err != nil {
return nil, fmt.Errorf("failed to get media list: %w", err)
}
return &response, nil
}
func (c *Client) UploadMedia(ctx context.Context, externalID string, filename string, fileReader io.Reader) (*string, error) {
path := fmt.Sprintf("/v1/media/%s", url.PathEscape(externalID))
var b bytes.Buffer
w := multipart.NewWriter(&b)
fw, err := w.CreateFormFile("media_file", filename)
if err != nil {
return nil, fmt.Errorf("failed to create form file: %w", err)
}
if _, err = io.Copy(fw, fileReader); err != nil {
return nil, fmt.Errorf("failed to copy file data: %w", err)
}
if err := w.Close(); err != nil {
return nil, fmt.Errorf("failed to close writer: %w", err)
}
url := c.base + path
req, err := http.NewRequestWithContext(ctx, "PUT", url, &b)
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}
req.Header.Set("Content-Type", w.FormDataContentType())
if c.token != "" {
req.Header.Set("Authorization", "Bearer "+c.token)
}
resp, err := c.http.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to perform request: %w", err)
}
defer func() {
if err := resp.Body.Close(); err != nil {
log.Println("failed to close response body", err)
}
}()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response body: %w", err)
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return nil, fmt.Errorf("API request failed with status %d: %s", resp.StatusCode, string(respBody))
}
var result struct {
SHA256 string `json:"sha256"`
}
if err := json.Unmarshal(respBody, &result); err != nil {
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
}
return &result.SHA256, nil
}
func (c *Client) GetMediaBinary(ctx context.Context, externalID string) ([]byte, error) {
path := fmt.Sprintf("/v1/media/%s", url.PathEscape(externalID))
url := c.base + path
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}
if c.token != "" {
req.Header.Set("Authorization", "Bearer "+c.token)
}
resp, err := c.http.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to perform request: %w", err)
}
defer func() {
if err := resp.Body.Close(); err != nil {
log.Println("failed to close response body", err)
}
}()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response body: %w", err)
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return nil, fmt.Errorf("API request failed with status %d: %s", resp.StatusCode, string(respBody))
}
return respBody, nil
}
func (c *Client) GetMediaInfo(ctx context.Context, externalID string) (*MediaInfo, error) {
path := fmt.Sprintf("/v1/media/%s/info", url.PathEscape(externalID))
var mediaInfo MediaInfo
if err := c.request(ctx, "GET", path, nil, &mediaInfo); err != nil {
return nil, fmt.Errorf("failed to get media info: %w", err)
}
return &mediaInfo, nil
}
func (c *Client) GetMediaInfoBatch(ctx context.Context, externalIDs []string) ([]MediaInfo, error) {
path := "/v1/get_media_info"
request := struct {
ExternalIDs []string `json:"external_ids"`
}{
ExternalIDs: externalIDs,
}
var response struct {
Media []MediaInfo `json:"media"`
}
if err := c.request(ctx, "POST", path, request, &response); err != nil {
return nil, fmt.Errorf("failed to get media info batch: %w", err)
}
return response.Media, nil
}
package ord
import "net/http"
type Option func(a *Client) error
func WithToken(token string) Option {
return func(c *Client) error {
c.token = token
return nil
}
}
func WithHttpClient(cl *http.Client) Option {
return func(c *Client) error {
c.http = cl
return nil
}
}
func WithBase(base string) Option {
return func(c *Client) error {
c.base = base
return nil
}
}
package ord
import (
"context"
"fmt"
)
const (
PadTypeWeb = "web" // веб-страница, включая мобильные версии сайтов или профили социальной сети.
PadTypeMobileApp = "mobile_app" // приложение.
PadTypeHbbTV = "hbbtv" // приложение HbbTV
PadTypeSmartTV = "smarttv" // приложение SmartTV
)
type Pad struct {
CreateDate string `json:"create_date,omitempty"`
PersonExternalID string `json:"person_external_id"`
IsOwner bool `json:"is_owner"`
Type string `json:"type"`
Name string `json:"name"`
URL *string `json:"url,omitempty"`
}
type PadListResponse struct {
ExternalIDs []string `json:"external_ids"`
TotalItemsCount int `json:"total_items_count"`
Limit int `json:"limit"`
}
func (c *Client) GetPads(ctx context.Context, offset, limit int, personExternalID string) (*PadListResponse, error) {
path := fmt.Sprintf("/v1/pad?offset=%d&limit=%d", offset, limit)
if personExternalID != "" {
path = fmt.Sprintf("%s&person_external_id=%s", path, personExternalID)
}
var response PadListResponse
if err := c.request(ctx, "GET", path, nil, &response); err != nil {
return nil, fmt.Errorf("failed to get pads: %w", err)
}
return &response, nil
}
func (c *Client) GetRestrictedPads(ctx context.Context) ([]string, error) {
path := "/v1/pad/info/restricted"
var response struct {
URLs []string `json:"urls"`
}
if err := c.request(ctx, "GET", path, nil, &response); err != nil {
return nil, fmt.Errorf("failed to get restricted pads: %w", err)
}
return response.URLs, nil
}
func (c *Client) GetPad(ctx context.Context, externalID string) (*Pad, error) {
path := fmt.Sprintf("/v1/pad/%s", externalID)
var pad Pad
if err := c.request(ctx, "GET", path, nil, &pad); err != nil {
return nil, fmt.Errorf("failed to get pad: %w", err)
}
return &pad, nil
}
func (c *Client) CreatePad(ctx context.Context, externalID string, pad Pad) error {
path := fmt.Sprintf("/v1/pad/%s", externalID)
if err := c.request(ctx, "PUT", path, pad, nil); err != nil {
return fmt.Errorf("failed to create pad: %w", err)
}
return nil
}
package ord
import (
"context"
"fmt"
)
type Person struct {
CreateDate string `json:"create_date,omitempty"`
Name string `json:"name"`
RsURL *string `json:"rs_url,omitempty"`
Roles []string `json:"roles"`
JuridicalDetails JuridicalDetails `json:"juridical_details"`
LockedFields []LockedField `json:"locked_fields,omitempty"`
}
const (
PersonTypePhysical = "physical" // физическое лицо.
PersonTypeJuridical = "juridical" // юридическое лицо.
PersonTypeIP = "ip" // индивидуальный предприниматель.
PersonTypeForeignPhysical = "foreign_physical" // иностранное физическое лицо.
PersonTypeForeignJuridical = "foreign_juridical" // иностранное юридическое лицо.
)
type JuridicalDetails struct {
Type string `json:"type"`
INN string `json:"inn"`
KPP *string `json:"kpp,omitempty"`
Phone *string `json:"phone,omitempty"`
ForeignEpaymentMethod *string `json:"foreign_epayment_method,omitempty"`
ForeignRegistrationNumber *string `json:"foreign_registration_number,omitempty"`
ForeignINN *string `json:"foreign_inn,omitempty"`
ForeignOKSMCountryCode *string `json:"foreign_oksm_country_code,omitempty"`
}
type LockedField struct {
Field string `json:"field"`
Reasons []string `json:"reasons"`
}
type PersonListResponse struct {
ExternalIDs []string `json:"external_ids"`
TotalItemsCount int `json:"total_items_count"`
Limit int `json:"limit"`
}
func (c *Client) GetPersons(ctx context.Context, offset, limit int) (*PersonListResponse, error) {
path := fmt.Sprintf("/v1/person?offset=%d&limit=%d", offset, limit)
var response PersonListResponse
if err := c.request(ctx, "GET", path, nil, &response); err != nil {
return nil, fmt.Errorf("failed to get persons: %w", err)
}
return &response, nil
}
func (c *Client) GetPerson(ctx context.Context, externalID string) (*Person, error) {
path := fmt.Sprintf("/v1/person/%s", externalID)
var person Person
if err := c.request(ctx, "GET", path, nil, &person); err != nil {
return nil, fmt.Errorf("failed to get person: %w", err)
}
return &person, nil
}
func (c *Client) CreatePerson(ctx context.Context, externalID string, person Person) error {
path := fmt.Sprintf("/v1/person/%s", externalID)
if err := c.request(ctx, "PUT", path, person, nil); err != nil {
return fmt.Errorf("failed to create person: %w", err)
}
return nil
}
package ord
import (
"context"
"fmt"
)
const (
StatisticsPayTypeCPA = "cpa" // Cost Per Action, цена за действие.
StatisticsPayTypeCPC = "cpc" // Cost Per Click, цена за клик.
StatisticsPayTypeCPM = "cpm" // Cost Per Millennium, цена за 1 000 показов.
PStatisticsayTypeOther = "other" // иное.
)
type StatisticsV2Item struct {
CreativeExternalID string `json:"creative_external_id"`
PadExternalID string `json:"pad_external_id"`
ShowsCount uint64 `json:"shows_count"`
InvoiceShowsCount *uint64 `json:"invoice_shows_count,omitempty"`
Amount *StatisticsAmount `json:"amount,omitempty"`
AmountPerEvent *string `json:"amount_per_event,omitempty"`
PayType *string `json:"pay_type,omitempty"`
DateStartPlanned *string `json:"date_start_planned,omitempty"`
DateEndPlanned *string `json:"date_end_planned,omitempty"`
DateStartActual string `json:"date_start_actual"`
DateEndActual string `json:"date_end_actual"`
}
type StatisticsAmount struct {
ExcludingVAT string `json:"excluding_vat"`
VATRate string `json:"vat_rate"`
VAT string `json:"vat"`
IncludingVAT string `json:"including_vat"`
}
type StatisticsV3Item struct {
StatisticsV2Item
}
type StatisticsV2ItemsArray struct {
Items []StatisticsV2Item `json:"items"`
}
type StatisticsV3ItemsArray struct {
Items []StatisticsV3Item `json:"items"`
}
type StatisticsListResponse struct {
Items []StatisticsV2Item `json:"items"`
TotalItemsCount int `json:"total_items_count"`
Limit int `json:"limit"`
}
type StatisticsExternalID string
type DeleteStatisticsRequest struct {
Items []struct {
CreativeExternalID string `json:"creative_external_id"`
PadExternalID string `json:"pad_external_id"`
DateStartActual string `json:"date_start_actual"`
} `json:"items"`
}
func (c *Client) CreateStatisticsV2(ctx context.Context, statistics StatisticsV2ItemsArray) ([]StatisticsExternalID, error) {
path := "/v2/statistics"
var response struct {
ExternalIDs []StatisticsExternalID `json:"external_ids"`
}
if err := c.request(ctx, "POST", path, statistics, &response); err != nil {
return nil, fmt.Errorf("failed to create statistics v2: %w", err)
}
return response.ExternalIDs, nil
}
func (c *Client) CreateStatisticsV3(ctx context.Context, statistics StatisticsV3ItemsArray) ([]StatisticsExternalID, error) {
path := "/v3/statistics"
var response struct {
ExternalIDs []StatisticsExternalID `json:"external_ids"`
}
if err := c.request(ctx, "POST", path, statistics, &response); err != nil {
return nil, fmt.Errorf("failed to create statistics v3: %w", err)
}
return response.ExternalIDs, nil
}
func (c *Client) GetStatisticsList(ctx context.Context, offset, limit int) (*StatisticsListResponse, error) {
path := fmt.Sprintf("/v3/statistics/list?offset=%d&limit=%d", offset, limit)
var response StatisticsListResponse
if err := c.request(ctx, "GET", path, nil, &response); err != nil {
return nil, fmt.Errorf("failed to get statistics list: %w", err)
}
return &response, nil
}
func (c *Client) DeleteStatisticsV3(ctx context.Context, deleteReq DeleteStatisticsRequest) error {
path := "/v3/statistics/delete"
if err := c.request(ctx, "POST", path, deleteReq, nil); err != nil {
return fmt.Errorf("failed to delete statistics: %w", err)
}
return nil
}
package ord
func StringPtr(str string) *string {
return &str
}