SAF-T reports

Use this service to generate SAF-T reports. This service only works for documents issued with certified software SaphetyDoc(DOC+).
For more information on SAF-T (PT)

You can request a SAF-T generation using the service /api/Reporting/createSafT
This is an asynchrounous service: when requesting a SAF-T report you will receive an Id (GUID) that you can query for report completion.
SAF-T report generation is part of a group defined as Long running tasks. These tasks may take some time to complete, therefore their asynchrounous nature.

SAF-T query report properties

SAF-T reporting specifies the following parameters:

  • EntityCode
    The entity code that issued the invoice and is responsible for SAFT-T. (Typically <country code + VAT number> ex: PT507957547)

  • SelfInvoiceSellerEntityCode
    Applyed only when issuing self-invoices. Typically <country code + VAT number>. This will generate a SAF-T file for the seller.

  • StartDate and EndDate
    The document dates interval that will define the document inclusion in the report

  • DocumentTypes
    One of the following: INVOICE, DEBIT_NOTE, CREDIT_NOTE, DESPATCH_ADVICE, SIMPLIFIED_INVOICE, INVOICE_RECEIPT, WAYBILL
    Use ALL to include all document types in SAF-T.

Requesting a SAF-T report

Get a token

Check more detail how to get a token in Services overview

# Set Environment
#Integration
server_base_adress = "doc-server-int.saphety.com/Doc.WebApi.Services"
#Quality
#server_base_adress = "doc-server-qa.saphety.com/Doc.WebApi.Services"
#Production
#server_base_adress = "doc-server.saphety.com/Doc.WebApi.Services"
#Set authorization data
#username = 'username'
#password = 'request_password'

username = 'user_api_doc'
password = 'request_password'
## Get a JWT token from your username and password
import requests
import json

service_url = "https://" + server_base_adress + "/api/Account/token"

# Auhtentication data goes in payload as json
payload = {
      'Username': username,
      'Password': password
}
# Payload goes in json, serialize the payloal object to json
request_data=json.dumps(payload)
# Indicate in header that payload is json
headers = {
    'content-type': 'application/json'
    }
# POST request to get a token
response = requests.request("POST", service_url, data=request_data, headers=headers)
# Serializethe response
json_response = json.loads(response.text)
# Your token is at:
token = json_response["Data"];
print ('Your authorization token:' + token)
Your authorization token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiI1NDM5NSIsInVuaXF1ZV9uYW1lIjoidXNlcl9hcGlfZG9jIiwic2Vzc2lvbl9pZCI6ImUxN2M4YjM4LTdmMzQtNDdmNS1hYjU0LWMxYTUyOTIwNDQ3NCIsInN5c3RlbV9hZG1pbiI6IkZhbHNlIiwiZ2xvYl9lZGl0IjoiRmFsc2UiLCJleHRlcm5hbF91c2VybmFtZSI6InVzZXJfYXBpX2RvYyIsImV4dGVybmFsX3N5c3RlbV9hdWRpZW5jZSI6Imh0dHBzOi8vd3d3LnNhcGhldHktaW50LmNvbS9Eb2NTZXJ2ZXIiLCJuYmYiOjE2MjEyNjQ0ODYsImV4cCI6MTYyMTMxNTQ4NiwiaWF0IjoxNjIxMjY0NDI2LCJpc3MiOiJodHRwczovL3d3dy5zYXBoZXR5LmNvbS8iLCJhdWQiOiJodHRwczovL3d3dy5zYXBoZXR5LWludC5jb20vRG9jU2VydmVyIn0.GScY3rDaXrJr4Uxc0DVYFQbH_HYyVaf6ZwnkDLjz-EA

Define SAFT-T criteria

# SAF-T criteria data goes in payload as json
saft_criteria = {
  'EntityCode': "PT560333331", # The company code that you want to list the series for
  'SelfInvoiceSellerEntityCode': None, # Used only when issuing self-invoices
  'StartDate': "2021-04-01",
  'EndDate': "2021-05-30",
  'DocumentTypes': "ALL"
}

Send request and get a request Id

service_url = "https://" + server_base_adress + "/api/Reporting/createSafT"

# Serialize the payloal object to json
request_data=json.dumps(saft_criteria)
# Indicate in header the authorization token
headers = {
    'content-type': 'application/json',
     'Authorization': 'bearer ' + token
    }
# POST data to request SAF-Treport
response = requests.request("POST", service_url, data=request_data, headers=headers)

# formating the response to json for visualization purposes only
json_response = json.loads(response.text)
print(json.dumps(json_response, indent=4))
{
    "CorrelationId": "0fb2cce1-b131-4513-b2ef-09f3dccd096f",
    "IsValid": true,
    "Errors": [],
    "Data": "dca09d84-359a-4358-99a1-4eb97f2428e7"
}
# your request id is at:
request_id = json_response["Data"];
print ('The request id to query on service status: ' + request_id)
The request id to query on service status: dca09d84-359a-4358-99a1-4eb97f2428e7

Check the status of your request

Query the LongRunningTasksMonitor as indicate bellow.
The AsyncStatus of your request must be set to finished and the IsValid property no Errors should be present in the response.

# with the received request_id query the LongRunningTasksMonitor
service_url = "https://" + server_base_adress + "/api/LongRunningTasksMonitor/" + request_id
# build the request
headers = {
    'Authorization': 'bearer ' + token
    }
# POST request to send the invoice
response = requests.request("GET", service_url, headers=headers)
# formating the response to json for visualization purposes only
json_response = json.loads(response.text)
print(json.dumps(json_response, indent=4))
task_status=json_response["Data"]["AsyncStatus"]
task_errors=json_response["Errors"]
print("Your task is: " + task_status)
{
    "CorrelationId": "9518f6e3-78e7-457c-bce1-8ec391819d39",
    "IsValid": true,
    "Errors": [],
    "Data": {
        "Id": "dca09d84-359a-4358-99a1-4eb97f2428e7",
        "UserId": 54395,
        "Queue": "DocGenerateSafT",
        "AsyncStatus": "Queued",
        "CreationDate": "2021-05-17 15:14:47",
        "ExecutionStart": null,
        "ExecutionEnd": null,
        "SerializedInput": "{\"Id\":\"dca09d84-359a-4358-99a1-4eb97f2428e7\",\"Payload\":{\"EntityCode\":\"PT560333331\",\"SelfInvoiceSellerEntityCode\":null,\"StartDate\":\"2021-04-01\",\"EndDate\":\"2021-05-30\",\"DocumentTypes\":\"ALL\"}}",
        "SerializedOutput": null
    }
}
Your task is: Queued

Download SAF-T report

Report characteristics

Once the report task has finished with success a SAF-T report is available for download.
The report is associated to the company that request the SAFT-T. (Property EntityCode in the SAFT-Criteria)
The report will have the following characteristics:

  • Report code: SAFT_PT_GENERATION

  • Report name: SafT_RequesterEntitycode|SelfBillingEntityCode_DocumentStartDate (yyMMdd)_DocumentEndDate (yyMMdd).zip
    Example: SafT_PT506284301_210401_210530.zip

Get a token to download report

Use the service /api/Reporting/SearchEntityReport to find your SAF-T report.
This service returns a token that can be use to download the report.
This service is a paginable services. More info at Services overview
This service can return more then one SAF-T report since severall requests can be done using the same criteria. Use the RestrictionCriteria MaxCreationDate and MinCreationDate to find the target report.

# Search you report by defining in thesearch criteira the report characteristics
service_url = "https://" + server_base_adress + "/api/Reporting/SearchEntityReport"
# Use in the restriction criteria the report characteristics
report_name='SafT_PT560333331_210401_210530.zip'
payload = {
  'RestrictionCriteria': {
    'EntityCode': "PT560333331", # the entity code that requested the report generation
    'Code': "SAFT_PT_GENERATION", # SAF-T report
    'Name': report_name, # report name (check rule names)
    'MaxCreationDate': None,
    'MinCreationDate': None
  },
  'PageNumber': 0,
  'RowsPerPage': 20
}
# Payload goes in json, serialize the payloal object to json
request_data=json.dumps(payload)
# Indicate in header the authorization token
headers = {
    'content-type': 'application/json',
     'Authorization': 'bearer ' + token
    }
# POST request to get a token
response = requests.request("POST", service_url, data=request_data, headers=headers)
print (response)
# Serializethe response
json_response = json.loads(response.text)
print(json_response)
<Response [200]>
{'CorrelationId': 'f0c3fff4-aa45-43f1-bfd6-12d8dfbbd9b8', 'IsValid': True, 'Errors': [], 'Data': [{'Id': 73337, 'EntityCode': 'PT560333331', 'Code': 'SAFT_PT_GENERATION', 'Name': 'SafT_PT560333331_210401_210530.zip', 'Script': None, 'UsersId': 421, 'CreationDate': '2021-05-12 15:33:53', 'ExecutionDate': '2021-05-12 15:33:53', 'Status': 'PROCESSED', 'ExecutionCompleted': '2021-05-12 15:33:54', 'ReportContext': '{"StartDate":"2021-04-01T00:00:00","EndDate":"2021-05-30T00:00:00"}', 'Token': 'DSAj0vBevcCAqgKA1JMweTincsV7IklkIjo3MzMzNywiRW50aXR5Q29kZSI6IlBUNTYwMzMzMzMxIiwiVXNlcklkIjo1NDM5NX0='}, {'Id': 73507, 'EntityCode': 'PT560333331', 'Code': 'SAFT_PT_GENERATION', 'Name': 'SafT_PT560333331_210401_210530.zip', 'Script': None, 'UsersId': 421, 'CreationDate': '2021-05-17 15:14:50', 'ExecutionDate': '2021-05-17 15:14:50', 'Status': 'PROCESSED', 'ExecutionCompleted': '2021-05-17 15:14:51', 'ReportContext': '{"StartDate":"2021-04-01T00:00:00","EndDate":"2021-05-30T00:00:00"}', 'Token': '07EJGB8+0dSUQuGGIIWEqO6V5Cx7IklkIjo3MzUwNywiRW50aXR5Q29kZSI6IlBUNTYwMzMzMzMxIiwiVXNlcklkIjo1NDM5NX0='}]}
# token is at (note that more then one report may have been returned)
report_access_token =json_response["Data"][0]["Token"]
print('Token to download the report: ' + report_access_token)
Token to download the report: DSAj0vBevcCAqgKA1JMweTincsV7IklkIjo3MzMzNywiRW50aXR5Q29kZSI6IlBUNTYwMzMzMzMxIiwiVXNlcklkIjo1NDM5NX0=

Download the report

With the token use the service /api/Reporting/GetReportByToken to download the report

import urllib.parse

# Build the url
report_access_token = urllib.parse.quote(report_access_token);
service_url = "https://" + server_base_adress + "/api/Reporting/GetReportByToken?token=" + report_access_token;
print('SAF-T download url: ' + service_url);
# Indicate in header the authorization token
headers = {
    'content-type': 'application/json',
     'Authorization': 'bearer ' + token
    }
# Use GET to send the request
#r = requests.get(service_url, Stream=True)


response = requests.get(service_url, allow_redirects=True)
with open(report_name,'wb') as report:
    report.write(response.content)

# response = requests.request("GET", service_url, headers=headers)
# print (response)
# Serializethe response
#This service streams the report to the client.
SAF-T download url: https://doc-server-int.saphety.com/Doc.WebApi.Services/api/Reporting/GetReportByToken?token=DSAj0vBevcCAqgKA1JMweTincsV7IklkIjo3MzMzNywiRW50aXR5Q29kZSI6IlBUNTYwMzMzMzMxIiwiVXNlcklkIjo1NDM5NX0%3D